openapi: 3.1.0
info:
  title: Planning API
  version: 1.5.0
  description: >
    The planning API provides information about plannings and their lifecycle. 


    You can find out more in our [developer
    portal](https://developer.conundra.eu/developer-portal/planning/).
  contact:
    name: API support
    url: https://servicedesk.conundra.eu
servers:
  - url: https://api.conundra.eu/planning/v1
    description: Production Api
security:
  - clientCredentials: []
tags:
  - name: health
    x-displayName: Health
    description: |
      Validate connection and accessibility of the API.
  - name: plannings
    x-displayName: Plannings
    description: >
      Endpoints used for retrieving information about plannings and its
      releases.
  - name: location-workload-levelling
    x-displayName: Location Workload Levelling
    description: |
      Endpoints used for managing location workload levelling sets.
  - name: order-order-restrictions
    x-displayName: Order-Order Restrictions
    description: |
      Endpoints used for managing order-order restriction sets.
  - name: depot-sets
    x-displayName: Depot Sets [EXPERIMENTAL]
    description: |
      Endpoints used for managing depot sets.
x-tagGroups:
  - name: Health
    tags:
      - health
  - name: Plannings
    tags:
      - plannings
  - name: Settings
    tags:
      - location-workload-levelling
      - order-order-restrictions
  - name: Locations
    tags:
      - depot-sets
paths:
  /ping:
    get:
      tags:
        - health
      summary: Returns a single `pong` string
      description: >
        The `ping`-endpoint can be used for validating a connection with the
        application.

        It will authenticate the caller and returns a `pong` response when
        everything is set-up correctly.
      operationId: ping
      responses:
        '200':
          description: Everything set-up correctly
          content:
            text/plain:
              schema:
                type: string
              example: pong
        '401':
          $ref: '#/components/responses/401'
  /plannings:
    get:
      tags:
        - plannings
      summary: Get a cursor paged list of plannings
      description: >
        Returns a cursor paged list of plannings. Results are sorted by
        `created_at` in descending order.

        You can find out more about how to use cursors in our [developer
        portal](https://developer.conundra.eu/developer-portal/cursor-paging/).
      operationId: getPlannings
      parameters:
        - in: query
          name: released_since
          schema:
            type: string
            format: date-time
            example: '2021-01-01T10:15:30Z'
          description: >
            When provided, only plannings which have been released since
            (exclusive) the given date will be returned.
        - in: query
          name: cursor
          schema:
            type: string
          description: Cursor of the page to retrieve.
        - in: query
          name: limit
          schema:
            type: integer
            format: int32
            minimum: 1
            maximum: 1000
            default: 100
            example: 100
          description: >-
            The maximum amount of plannings that should be returned in the
            response
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GetPlanningsResponse'
        '400':
          $ref: '#/components/responses/400'
        '401':
          $ref: '#/components/responses/401'
  /plannings/{id}/releases/latest:
    get:
      tags:
        - plannings
      summary: Retrieve a released planning using a given planning id
      description: >
        Retrieves detailed information on the given released planning.


        Note that information about releases are only stored for 2 weeks after
        the release was made. If you try to retrieve a release which is older
        than 2 weeks, you will get a 404 Not Found response.
      operationId: getLatestReleaseByPlanningId
      parameters:
        - in: path
          name: id
          description: The unique identifier of a planning
          schema:
            type: string
          required: true
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Release'
        '401':
          $ref: '#/components/responses/401'
        '404':
          $ref: '#/components/responses/404'
  /settings/location-workload-levelling-sets:
    get:
      tags:
        - location-workload-levelling
      summary: List the existing location workload levelling sets
      description: >
        Retrieves detailed information on all `location workload levelling
        set`s, limited to at most 100 items.
      operationId: listLocationWorkloadLevellingSets
      parameters:
        - in: query
          name: cursor
          schema:
            type: string
          description: Cursor of the page to retrieve.
          required: false
        - in: query
          name: limit
          schema:
            type: integer
            format: int32
            minimum: 1
            maximum: 100
            default: 100
            example: 100
          description: >-
            The maximum amount of `location workload levelling set`s that should
            be returned in the response
          required: false
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CursorPageLocationWorkloadLevellingSets'
        '401':
          $ref: '#/components/responses/401'
  /settings/location-workload-levelling-sets/{business_id}:
    get:
      tags:
        - location-workload-levelling
      summary: Get location workload levelling set
      description: >
        Retrieves detailed information on the given `location workload levelling
        set`.
      operationId: getLocationWorkloadLevellingSet
      parameters:
        - $ref: '#/components/parameters/business_id'
      responses:
        '200':
          description: OK
          headers:
            ETag:
              $ref: '#/components/headers/ETag'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LocationWorkloadLevellingSet'
        '401':
          $ref: '#/components/responses/401'
        '404':
          $ref: '#/components/responses/404'
    put:
      tags:
        - location-workload-levelling
      summary: Upsert location workload levelling set
      description: >
        Create or update a `location workload levelling set`. A unique ID
        (`business_id`) is required to identify the `location workload levelling
        set`. 

        Calling this endpoint with an existing `business_id` will update the
        `location workload levelling set`.
      operationId: upsertLocationWorkloadLevellingSet
      parameters:
        - $ref: '#/components/parameters/business_id'
        - $ref: '#/components/parameters/if-match'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/LocationWorkloadLevellingSet'
      responses:
        '201':
          description: location workload levelling set created successful
          headers:
            ETag:
              $ref: '#/components/headers/ETag'
            Location:
              description: The URL of the newly created resource
              schema:
                type: string
                example: >-
                  /settings/location-workload-levelling-sets/86b54c9d-21d7-4b37-af3d-25f03886153b
        '204':
          description: location workload levelling set updated successful
          headers:
            ETag:
              $ref: '#/components/headers/ETag'
        '400':
          $ref: '#/components/responses/400'
        '401':
          $ref: '#/components/responses/401'
        '404':
          $ref: '#/components/responses/404'
        '409':
          $ref: '#/components/responses/409'
        '412':
          $ref: '#/components/responses/412'
    delete:
      tags:
        - location-workload-levelling
      summary: Delete location workload levelling set
      description: |
        Delete a `location workload levelling set` by it's `business_id`.
      operationId: deleteLocationWorkloadLevellingSet
      parameters:
        - $ref: '#/components/parameters/business_id'
        - $ref: '#/components/parameters/if-match'
      responses:
        '204':
          description: Delete successful
        '400':
          $ref: '#/components/responses/400'
        '401':
          $ref: '#/components/responses/401'
        '404':
          $ref: '#/components/responses/404'
        '412':
          $ref: '#/components/responses/412'
  /locations/depot-sets:
    get:
      tags:
        - depot-sets
      summary: List the existing depot sets
      description: >
        Retrieve depot sets using cursor-based paging (see the Cursor-based
        pagination documentation on the PTV Developer Portal for more details).
      operationId: listDepotSets
      parameters:
        - in: query
          name: cursor
          schema:
            type: string
          description: >-
            The cursor of the page to retrieve. No cursor is needed to retrieve
            the first page.
          required: false
        - in: query
          name: limit
          schema:
            type: integer
            format: int32
            minimum: 1
            maximum: 1000
            default: 100
            example: 250
          description: >-
            The maximum amount of depot sets that should be returned in the
            response
          required: false
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CursorPageDepotSets'
        '401':
          $ref: '#/components/responses/401'
  /locations/depot-sets/{business_id}:
    get:
      tags:
        - depot-sets
      summary: Get depot set
      description: |
        Retrieves detailed information on the given depot set.
      operationId: getDepotSet
      parameters:
        - $ref: '#/components/parameters/business_id'
      responses:
        '200':
          description: OK
          headers:
            ETag:
              $ref: '#/components/headers/ETag'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DepotSet'
        '401':
          $ref: '#/components/responses/401'
        '404':
          $ref: '#/components/responses/404'
    put:
      tags:
        - depot-sets
      summary: Upsert depot set
      description: >
        Create or update a depot set. A unique ID (business_id) is required to
        identify the depot set.

        Calling this endpoint with an existing business_id will update the depot
        set.
      operationId: upsertDepotSet
      parameters:
        - $ref: '#/components/parameters/business_id'
        - $ref: '#/components/parameters/if-match'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DepotSet'
      responses:
        '201':
          description: depot set created successfully
          headers:
            ETag:
              $ref: '#/components/headers/ETag'
        '204':
          description: depot set updated successfully
          headers:
            ETag:
              $ref: '#/components/headers/ETag'
        '400':
          $ref: '#/components/responses/400'
        '401':
          $ref: '#/components/responses/401'
        '412':
          $ref: '#/components/responses/412'
    delete:
      tags:
        - depot-sets
      summary: Delete depot set
      description: |
        Delete a depot set by its business_id.
      operationId: deleteDepotSet
      parameters:
        - $ref: '#/components/parameters/business_id'
        - $ref: '#/components/parameters/if-match'
      responses:
        '204':
          description: Delete successful
        '400':
          $ref: '#/components/responses/400'
        '401':
          $ref: '#/components/responses/401'
        '404':
          $ref: '#/components/responses/404'
        '412':
          $ref: '#/components/responses/412'
  /settings/order-order-restriction-sets:
    get:
      tags:
        - order-order-restrictions
      summary: List the existing order-order restriction sets
      description: >
        Retrieves detailed information on all `order-order restriction set`s,
        limited to at most 100 items.
      operationId: listOrderOrderRestrictionSets
      parameters:
        - in: query
          name: cursor
          schema:
            type: string
          description: Cursor of the page to retrieve.
          required: false
        - in: query
          name: limit
          schema:
            type: integer
            format: int32
            minimum: 1
            maximum: 100
            default: 100
            example: 100
          description: >-
            The maximum amount of `order-order restriction set`s that should be
            returned in the response
          required: false
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CursorPageOrderOrderRestrictionSets'
        '401':
          $ref: '#/components/responses/401'
  /settings/order-order-restriction-sets/{business_id}:
    get:
      tags:
        - order-order-restrictions
      summary: Get order-order restriction set
      description: >
        Retrieves detailed information on the given `order-order restriction
        set`.
      operationId: getOrderOrderRestrictionSet
      parameters:
        - $ref: '#/components/parameters/business_id'
      responses:
        '200':
          description: OK
          headers:
            ETag:
              $ref: '#/components/headers/ETag'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OrderOrderRestrictionSetDetail'
        '401':
          $ref: '#/components/responses/401'
        '404':
          $ref: '#/components/responses/404'
    put:
      tags:
        - order-order-restrictions
      summary: Upsert order-order restriction set
      description: >
        Create or update an `order-order restriction set`. A unique ID
        (`business_id`) is required to identify the `order-order restriction
        set`. 

        Calling this endpoint with an existing `business_id` will update the
        `order-order restriction set`.
      operationId: upsertOrderOrderRestrictionSet
      parameters:
        - $ref: '#/components/parameters/business_id'
        - $ref: '#/components/parameters/if-match'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/OrderOrderRestrictionSetRequest'
      responses:
        '201':
          description: order-order restriction set created successful
          headers:
            ETag:
              $ref: '#/components/headers/ETag'
            Location:
              description: The URL of the newly created resource
              schema:
                type: string
                example: /settings/order-order-restriction-sets/a-business-id
        '204':
          description: order-order restriction set updated successful
          headers:
            ETag:
              $ref: '#/components/headers/ETag'
        '400':
          $ref: '#/components/responses/400'
        '401':
          $ref: '#/components/responses/401'
        '404':
          $ref: '#/components/responses/404'
        '409':
          $ref: '#/components/responses/409'
        '412':
          $ref: '#/components/responses/412'
    delete:
      tags:
        - order-order-restrictions
      summary: Delete order-order restriction set
      description: |
        Delete an `order-order restriction set` by it's `business_id`.
      operationId: deleteOrderOrderRestrictionSet
      parameters:
        - $ref: '#/components/parameters/business_id'
        - $ref: '#/components/parameters/if-match'
      responses:
        '204':
          description: Delete successful
        '400':
          $ref: '#/components/responses/400'
        '401':
          $ref: '#/components/responses/401'
        '404':
          $ref: '#/components/responses/404'
        '412':
          $ref: '#/components/responses/412'
        '428':
          $ref: '#/components/responses/428'
components:
  parameters:
    business_id:
      in: path
      name: business_id
      description: The unique identifier of an entity
      schema:
        type: string
        pattern: ^[a-zA-Z0-9.~\-_]+$
      required: true
    if-match:
      name: If-Match
      in: header
      description: Weak Etag used for optimistic locking.
      schema:
        type: string
        example: W/"24"
  headers:
    ETag:
      description: >-
        A weak Etag (ex `W/"<etag_value>"`) which contains the current version
        of the entity
      schema:
        type: string
        example: W/"25"
  responses:
    '400':
      description: Bad request
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'
    '401':
      description: Authentication required
    '404':
      description: Not found
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'
    '409':
      description: Conflict
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'
    '412':
      description: >-
        This status is returned when an entity is updated with an outdated
        version in the If-Match header.
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'
    '428':
      description: This status is returned when the If-Match header is missing.
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'
  schemas:
    Address:
      description: Information on the physical address of a `Location`
      type: object
      properties:
        address_line:
          type: string
          example: Voordries 41b
        city:
          type: string
          example: Oosterzele
        zip_code:
          type: string
          example: '9860'
        country_code:
          $ref: '#/components/schemas/CountryCode'
    Break:
      type: object
      properties:
        at:
          description: The planned time of the break
          type: string
          format: date-time
          example: '2024-12-01T11:15:30Z'
        duration:
          description: The duration of the break
          type: string
          format: duration
          example: PT45M
      required:
        - at
        - duration
    Capacity:
      type: object
      description: Dimensional value of a capacity.
      properties:
        type:
          type: string
          enum:
            - volume
            - weight
            - loadingMeters
            - capacity1
            - capacity2
            - capacity3
            - capacity4
            - capacity5
          description: >-
            Characterization of a capacity, representing the dimension in which
            this `Capacity` is expressed.
          default: volume
          example: weight
        value:
          type: number
          format: double
          example: 20.02
      required:
        - type
        - value
    CountryCode:
      description: represents the ISO3166-1 alpha-2 two letter country codes
      type: string
      pattern: ^[A-Z]{2}$
      example: BE
    Cursor:
      type: object
      properties:
        self:
          type: string
          description: >-
            The cursor for this page. Not present when the result contains no
            data.
          example: c2VsZl9fcGFnZQ
        prev:
          type: string
          description: >-
            The cursor for the previous page. Not present when fetching data for
            the first page.
          example: cHJldmlvdXNfX3BhZ2U
        next:
          type: string
          description: >-
            The cursor for the next page. Not present when fetching data for the
            last page.
          example: bmV4dF9fcGFnZQ
    CustomData:
      description: Custom data is an extendable hashmap of key-value pairs.
      additionalProperties:
        type: string
      example:
        shop_manager: John Smith
    Delivery:
      description: A delivery order
      type: object
      properties:
        order:
          $ref: '#/components/schemas/OrderInformation'
        timings:
          $ref: '#/components/schemas/OrderTimings'
      required:
        - order
        - timings
    Employee:
      description: Person driving the transport resource
      properties:
        business_id:
          description: Identifier of the employee
          type: string
          example: EMP-18
        name:
          description: Name of the employee
          type: string
          example: Patrick Simmons
        custom_data:
          $ref: '#/components/schemas/CustomData'
      required:
        - business_id
        - name
    GeoPoint:
      description: Geodetic coordinates of the `Location`
      type: object
      properties:
        latitude:
          type: number
          format: double
          description: >-
            The latitude value of the `Location` in degrees (WGS84/EPSG:4326)
            from south to north.
          maximum: 90
          minimum: -90
          example: 50.9514048
        longitude:
          type: number
          format: double
          description: >-
            The longitude value of the `Location` in degrees (WGS84/EPSG:4326)
            from west to east.
          maximum: 180
          minimum: -180
          example: 3.8067878
      required:
        - latitude
        - longitude
    GeoPointWithResolvedInfo:
      properties:
        latitude:
          type: number
          format: double
          example: 50.9514048
          minimum: -90
          maximum: 90
        longitude:
          type: number
          format: double
          example: 3.8067878
          minimum: -180
          maximum: 180
        resolved:
          readOnly: true
          type: object
          description: Geocoding resolution information.
          properties:
            geocoded:
              type: boolean
              description: >
                Indicates if the provided address was geocoded or not.

                Geocoding only happens when the provided address does not yet
                have a geo-point.
              example: true
            address:
              type: string
              description: >-
                The address that matches the resolved geo-point. Only present
                when `geocoded` is `true`.
              example: Voordries 41, 9860 Oosterzele
            precision:
              type: integer
              description: >
                Geocoding confidence score from 0-10.

                10 indicates 100% confidence that the coordinates match the
                provided address. 0 indicates no confidence in the match.

                Only present when `geocoded` is `true`.
              minimum: 0
              maximum: 10
              example: 9
      required:
        - latitude
        - longitude
    GetPlanningsResponse:
      type: object
      properties:
        plannings:
          type: array
          items:
            $ref: '#/components/schemas/PlanningSummary'
        cursor:
          $ref: '#/components/schemas/Cursor'
      required:
        - plannings
        - cursor
    Location:
      description: A physical `Location` at which an activity occurs.
      type: object
      properties:
        business_id:
          description: Unique identifier of the location
          type: string
          example: LOC_001
        name:
          type: string
          example: Conundra (Oosterzele)
        type:
          $ref: '#/components/schemas/LocationType'
        geo_point:
          $ref: '#/components/schemas/GeoPoint'
        address:
          $ref: '#/components/schemas/Address'
      required:
        - business_id
        - type
        - geo_point
    LocationType:
      description: >
        Type of the `Location`.

        CAUTION: The `type` of every `Location` of a `RouteBoundary` is
        currently always `DEPOT`. This could change in the future.
      type: string
      enum:
        - DEPOT
        - CUSTOMER
      example: CUSTOMER
    OrderInformation:
      description: Detailed information of the `Order`
      type: object
      properties:
        business_id:
          type: string
          description: Unique identifier of the order
          example: O_554
        description:
          type: string
          example: Order 554
        capacities:
          type: array
          minItems: 0
          maxItems: 8
          uniqueItems: true
          items:
            $ref: '#/components/schemas/Capacity'
        custom_data:
          $ref: '#/components/schemas/CustomData'
      required:
        - business_id
        - capacities
        - custom_data
    OrderTimings:
      description: Contains summary values of the timings of an `Order`
      properties:
        arrival_at:
          description: The planned time of arrival at the order
          type: string
          format: date-time
          example: '2024-12-01T10:30:00Z'
        earliest_arrival_at:
          description: The planned time of earliest arrival
          type: string
          format: date-time
          example: '2024-12-01T10:00:00Z'
        latest_arrival_at:
          description: The planned time of latest arrival
          type: string
          format: date-time
          example: '2024-12-01T12:00:00Z'
        service_time:
          description: >-
            The summation of the service time and extra time on arrival and, for
            the first order, also the location stop.
          type: string
          format: duration
          example: PT15M
        wait_time:
          description: The wait time at the order
          type: string
          format: duration
          example: PT30M
        departure_at:
          description: The planned time of departure at the order
          type: string
          format: date-time
          example: '2024-12-01T11:15:00Z'
      required:
        - arrival_at
        - service_time
        - wait_time
        - departure_at
    Pickup:
      description: A pickup order
      type: object
      properties:
        order:
          $ref: '#/components/schemas/OrderInformation'
        timings:
          $ref: '#/components/schemas/OrderTimings'
      required:
        - order
        - timings
    PlanningSummary:
      type: object
      properties:
        id:
          description: The identifier for this planning
          type: string
          example: 86b54c9d-21d7-4b37-af3d-25f03886153b
        created_at:
          description: Timestamp defining when the planning was created
          type: string
          format: date-time
          example: '2024-11-30T08:15:00Z'
        released_at:
          description: Timestamp defining when the planning has been released
          type: string
          format: date-time
          example: '2024-11-30T10:00:00Z'
        name:
          description: The name of the planning
          type: string
          example: Operational Planning
        labels:
          description: The labels added to the planning
          type: array
          items:
            type: string
          example:
            - operational
            - DEMO
            - label-xyz
      required:
        - id
        - created_at
    Problem:
      type: object
      properties:
        type:
          type: string
          format: uri
          description: >
            An absolute URI that identifies the problem type.  When
            dereferenced,

            it SHOULD provide human-readable documentation for the problem type

            (e.g., using HTML).
          example: >-
            https://developer.conundra.eu/developer-portal/problem/#constraint-violation
        title:
          type: string
          example: Bad Request
          description: >
            A short, summary of the problem type. Written in english and
            readable

            for engineers (usually not suited for non technical stakeholders and

            not localized)
        status:
          type: integer
          format: int32
          description: >
            The HTTP status code generated by the origin server for this
            occurrence

            of the problem.
          minimum: 100
          maximum: 599
          example: 400
        detail:
          type: string
          description: |
            A human readable explanation specific to this occurrence of the
            problem.
          example: Bad request. See violations for more details.
        violations:
          type: array
          items:
            $ref: '#/components/schemas/Violation'
      required:
        - type
        - title
        - status
        - detail
    Release:
      type: object
      properties:
        release_metadata:
          $ref: '#/components/schemas/ReleaseMetadata'
        routes:
          type: array
          items:
            $ref: '#/components/schemas/Route'
      required:
        - release_metadata
        - routes
    ReleaseMetadata:
      type: object
      properties:
        planning_id:
          description: The identifier of the planning that this release belongs to
          type: string
          example: 86b54c9d-21d7-4b37-af3d-25f03886153b
        released_at:
          description: Timestamp defining when the planning has been released
          type: string
          format: date-time
          example: '2024-11-30T10:00:00Z'
      required:
        - planning_id
        - released_at
    ResourceCombination:
      description: >-
        The combination of the `Employee` and their assigned `Transport
        Resources`
      type: object
      properties:
        id:
          type: string
          description: Unique identifier of the resource combination
          example: 5a4e8c43-80c0-4d5b-8f7e-32ec94f25d79
        employee:
          $ref: '#/components/schemas/Employee'
        transport_resources:
          type: array
          items:
            $ref: '#/components/schemas/TransportResource'
      required:
        - id
        - employee
        - transport_resources
    Route:
      type: object
      properties:
        id:
          type: string
          description: Unique identifier of the route
          example: d2c6013e-9194-46ac-a44c-855abf1176ca
        resource_combination:
          $ref: '#/components/schemas/ResourceCombination'
        start:
          $ref: '#/components/schemas/RouteBoundary'
        end:
          $ref: '#/components/schemas/RouteBoundary'
        breaks:
          type: array
          items:
            $ref: '#/components/schemas/Break'
        trips:
          type: array
          items:
            $ref: '#/components/schemas/Trip'
      required:
        - id
        - resource_combination
        - start
        - end
    RouteBoundary:
      description: >-
        CAUTION: The `type` of the `location` is currently always `DEPOT`. This
        could change in the future.
      type: object
      properties:
        location:
          $ref: '#/components/schemas/Location'
        timings:
          $ref: '#/components/schemas/RouteBoundaryTimings'
      required:
        - location
        - timings
    RouteBoundaryTimings:
      description: >-
        Contains summary values of the timings for the start or the end of a
        route.
      properties:
        arrival_at:
          description: The planned time of arrival at the start / end of the route
          type: string
          format: date-time
          example: '2024-12-01T10:30:00Z'
        service_time:
          description: The planned service time at the start / end of the route
          type: string
          format: duration
          example: PT45M
        departure_at:
          description: The planned time of departure at the start / end of the route
          type: string
          format: date-time
          example: '2024-12-01T11:15:00Z'
      required:
        - arrival_at
        - service_time
        - departure_at
    Stop:
      type: object
      properties:
        location:
          $ref: '#/components/schemas/Location'
        deliveries:
          description: |
            The deliveries at this stop are in the sequence they are executed. 
            For depots we assume the deliveries are executed LIFO.
          type: array
          minItems: 0
          uniqueItems: true
          items:
            $ref: '#/components/schemas/Delivery'
        pickups:
          description: |
            The pickups at this stop are in the sequence they are executed. 
            For depots we assume the pickups are executed LIFO.
          type: array
          minItems: 0
          uniqueItems: true
          items:
            $ref: '#/components/schemas/Pickup'
        timings:
          $ref: '#/components/schemas/StopTimings'
      required:
        - location
        - deliveries
        - pickups
        - timings
    StopTimings:
      description: Contains summary values of the timings at a `Stop`
      properties:
        arrival_at:
          description: The planned time of arrival at the `Stop`
          type: string
          format: date-time
          example: '2024-12-01T10:30:00Z'
        service_time:
          description: This is the summation of the individual order service times.
          type: string
          format: duration
          example: PT15M
        wait_time:
          description: This is the summation of the individual order wait times.
          type: string
          format: duration
          example: PT30M
        departure_at:
          description: The planned time of departure at the stop
          type: string
          format: date-time
          example: '2024-12-01T11:15:00Z'
      required:
        - arrival_at
        - service_time
        - wait_time
        - departure_at
    TransportResource:
      type: object
      properties:
        business_id:
          description: Unique identifier of the transport resource
          type: string
          example: TR-14
        license_plate:
          description: License plate of the transport resource
          type: string
          example: 2-QBD-124
        custom_data:
          $ref: '#/components/schemas/CustomData'
      required:
        - business_id
    Trip:
      type: object
      properties:
        stops:
          type: array
          items:
            $ref: '#/components/schemas/Stop'
      required:
        - stops
    Violation:
      type: object
      properties:
        field:
          type: string
          description: >-
            A reference to the field in the request that triggered this
            violation.
          example: limit
        message:
          type: string
          description: A message explaining the violation in the referenced field.
          example: Limit must be strictly positive.
      required:
        - message
    CursorPageLocationWorkloadLevellingSets:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/LocationWorkloadLevellingSetResponse'
          description: >
            Subset of `Location Workload Levelling Set`s matching the provided
            query, limited to the `limit` specified in the request.
        cursor:
          $ref: '#/components/schemas/Cursor'
      required:
        - data
        - cursor
    LocationWorkloadLevellingSet:
      type: object
      properties:
        business_id:
          description: The identifier for this location workload levelling set
          type: string
          pattern: ^[a-zA-Z0-9.~\-_]+$
          minLength: 1
          maxLength: 250
          example: 86b54c9d-21d7-4b37-af3d-25f03886153b
        name:
          description: The name of the location workload levelling set
          type: string
          example: Weekday
        settings:
          type: array
          items:
            $ref: '#/components/schemas/LocationWorkloadLevellingSetting'
    LocationWorkloadLevellingSetResponse:
      allOf:
        - $ref: '#/components/schemas/LocationWorkloadLevellingSet'
        - type: object
          properties:
            etag:
              $ref: '#/components/schemas/Etag'
    LocationWorkloadLevellingSetting:
      type: object
      properties:
        location_business_ids:
          description: List of business IDs of locations this setting applies to
          type: array
          items:
            type: string
          example:
            - LOC_001
            - LOC_002
        loading_zones:
          description: List of loading zones available at the locations
          type: array
          items:
            $ref: '#/components/schemas/LoadingZone'
        minimum_buffer_duration:
          description: >-
            The minimum buffer duration between vehicles using the same loading
            zone. Must be an ISO-8601 compliant Duration string.
          type: string
          format: ISO-8601
          example: PT30M
    LoadingZone:
      type: object
      properties:
        cost:
          description: The cost associated with using this loading zone
          type: number
          format: double
          example: 10
    Etag:
      type: string
      example: W/"1"
    CursorPageOrderOrderRestrictionSets:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/OrderOrderRestrictionSetResponse'
          description: >
            Subset of `Order-Order Restriction Set`s matching the provided
            query, limited to the `limit` specified in the request.
        cursor:
          $ref: '#/components/schemas/Cursor'
      required:
        - data
        - cursor
    OrderOrderRestrictionSet:
      type: object
      properties:
        business_id:
          description: The identifier for this order-order restriction set
          type: string
          pattern: ^[a-zA-Z0-9.~\-_]+$
          minLength: 1
          maxLength: 250
          example: a-business-id
        name:
          description: The name of the order-order restriction set
          type: string
          minLength: 1
          maxLength: 250
          example: Ambient goods not with chilled goods
    OrderOrderRestrictionSetResponse:
      allOf:
        - $ref: '#/components/schemas/OrderOrderRestrictionSet'
        - type: object
          properties:
            etag:
              $ref: '#/components/schemas/Etag'
    OrderOrderRestrictionSetDetail:
      allOf:
        - $ref: '#/components/schemas/OrderOrderRestrictionSet'
        - type: object
          properties:
            restrictions:
              type: array
              items:
                $ref: '#/components/schemas/OrderOrderRestriction'
              description: List of order-order restrictions in this set
    OrderOrderRestrictionSetRequest:
      type: object
      properties:
        name:
          description: The name of the order-order restriction set
          type: string
          minLength: 1
          maxLength: 250
          example: Ambient goods not with chilled goods
        restrictions:
          type: array
          minItems: 1
          items:
            $ref: '#/components/schemas/OrderOrderRestriction'
          description: List of order-order restrictions in this set
      required:
        - name
        - restrictions
    OrderOrderRestriction:
      type: object
      properties:
        order_label_1:
          type: string
          description: First label
          minLength: 1
          example: ambient
        type:
          $ref: '#/components/schemas/OrderOrderRestrictionType'
        order_label_2:
          type: string
          description: Second label
          minLength: 1
          example: chilled
        vehicle_label:
          oneOf:
            - type: string
              minLength: 1
            - type: 'null'
          description: Vehicle label
          example: cooler truck
      required:
        - order_label_1
        - type
        - order_label_2
    OrderOrderRestrictionType:
      type: string
      enum:
        - NOT_TOGETHER_IN_VEHICLE_WITH
        - NOT_LOADED_OR_UNLOADED_WHILE_VEHICLE_CONTAINS
        - NOT_AFTER
        - NOT_IMMEDIATELY_AFTER
        - NOT_BEFORE
        - NOT_LOADED_WHILE_VEHICLE_CONTAINS
        - NOT_UNLOADED_WHILE_VEHICLE_CONTAINS
      description: Type of restriction
      example: NOT_TOGETHER_IN_VEHICLE_WITH
    CursorPageDepotSets:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/DepotSetListSummary'
          description: |
            The set of results for the current page.
        cursor:
          $ref: '#/components/schemas/Cursor'
    DepotSetListSummary:
      type: object
      properties:
        business_id:
          description: The unique identifier for the depot set.
          type: string
          example: cb1fb12c-0abc-413c-a69d-63c62566685f
        name:
          description: The name of the depot set
          type: string
          example: Belgian Depots
        etag:
          $ref: '#/components/schemas/Etag'
    DepotSet:
      type: object
      properties:
        business_id:
          description: The unique identifier for the depot set.
          type: string
          example: cb1fb12c-0abc-413c-a69d-63c62566685f
          readOnly: true
        name:
          description: The name of the depot set
          type: string
          minLength: 1
          maxLength: 200
          example: Belgian Depots
        depots:
          type: array
          minItems: 1
          maxItems: 50
          items:
            $ref: '#/components/schemas/Depot'
          description: List of depots in this set
      required:
        - name
        - depots
    Depot:
      type: object
      properties:
        business_id:
          description: Identifier of a depot unique within the set
          type: string
          pattern: ^[a-zA-Z0-9.~\-_]{1,512}$
          example: depot-ghent
        name:
          description: Name of the depot
          type: string
          minLength: 1
          maxLength: 200
          example: Depot Ghent
        address:
          $ref: '#/components/schemas/DepotAddress'
        stop_time:
          description: Stop time at the depot in ISO-8601 duration format
          type: string
          format: duration
          example: PT5M
          default: PT0M
      required:
        - business_id
        - name
        - address
    DepotAddress:
      type: object
      description: >
        Address information for the depot.

        When geo_point is provided, address fields (address_line, city,
        zip_code, country_code) are optional.

        When geo_point is omitted, address fields must be provided so that the
        address can be geo-coded.
      properties:
        address_line:
          type: string
          minLength: 1
          maxLength: 500
          example: Voordries 41
          description: >
            The part of the address that includes the street name, house number,
            bus number etc. 

            Required when omitting `geo_point`.
        city:
          type: string
          minLength: 1
          maxLength: 200
          example: Oosterzele
          description: |
            City name. Required when omitting `geo_point`.
        zip_code:
          type: string
          minLength: 1
          maxLength: 20
          example: '9860'
          description: |
            Postal code. Required when omitting `geo_point`.
        country_code:
          $ref: '#/components/schemas/CountryCode'
        geo_point:
          $ref: '#/components/schemas/GeoPointWithResolvedInfo'
  securitySchemes:
    clientCredentials:
      type: oauth2
      description: >
        This API uses OAuth2 with the Client Credentials flow for M2M
        communication. Client ID and secret should be provided as a HTTP Basic
        Auth header.
      flows:
        clientCredentials:
          tokenUrl: >-
            https://auth.conundra.eu/auth/realms/prod/protocol/openid-connect/token
          scopes: {}
