> ## Documentation Index
> Fetch the complete documentation index at: https://developers.perform.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Create Booking

> Books an existing **Open Shipment** with a carrier and provisions the
shipping label(s). On success you receive the carrier-generated
tracking number, the booking status, the label document(s), and — for
PUDO bookings — the confirmed location details.

Create the Open Shipment first with the carrier-required information
(addresses, weight, line items as the carrier demands), then book it
here. The Booking feature requires account enablement — contact your
account team.

A booking can succeed **before** the carrier finishes generating the
label: the response is then HTTP 299 and `download_url` /
`base64_content` inside `documents` may be `null`. Fetch the label
later with Retrieve a Document (URL + Base64) or List Labels (URL
only).



## OpenAPI

````yaml /specs/public-api-v5.yaml post /v5/booking/
openapi: 3.1.0
info:
  title: Perform.AI Public API (v5)
  version: 5.0.0
  description: |-
    The Perform.AI Public API lets you create and manage shipments, returns,
    bookings, tracking events, and documents, and retrieve reference data such
    as PUDO locations and carrier configurations.

    All endpoints accept HTTPS connections only and are secured with OAuth 2.0.
    Generate a Bearer access token with your API credentials (Client ID and
    Client Secret, from **Integrations > API** in your account), then send it in
    the `Authorization` header of every request.

    This specification covers the following endpoints:
    - `POST /auth/oauth/token/`
    - `POST /v5/shipment/`
    - `POST /v5/shipment/update/`
    - `POST /v5-2-0/shipment/update/`
    - `GET /v5/shipment/list/`
    - `GET /v5/shipment/details/`
    - `GET /v5-2-0/shipment/details/`
    - `POST /v5/events/create/`
    - `POST /v5/return/`
    - `POST /v5/return/update/`
    - `GET /v5/shipments/documents/`
    - `GET /v5/shipments/documents/{document_uuid}/`
    - `GET /v5/shipments/documents/labels/`
    - `POST /v5/booking/`
    - `GET /v5/pudo-locations/`
    - `GET /v5/carrier-configs/`
servers:
  - url: https://api.perform.ai
security:
  - BearerAuth: []
tags:
  - name: Authentication
    description: Generate the Bearer access token used by every other endpoint.
  - name: Shipments
    description: Create, update, search, and retrieve Shipments.
  - name: Events
    description: Add manual tracking events to Shipments.
  - name: Returns
    description: Create and update Returns and their Return Shipments.
  - name: Documents
    description: Retrieve documents attached to Shipments.
  - name: Booking
    description: Book Open Shipments with carriers and provision shipping labels.
  - name: PUDO locations
    description: Search pick-up/drop-off locations across your configured carriers.
  - name: Carrier configurations
    description: Discover the carriers configured in your account.
  - name: Webhooks
    description: Shipment update payloads Perform.AI pushes to your endpoint.
paths:
  /v5/booking/:
    post:
      tags:
        - Booking
      summary: Create Booking
      description: |-
        Books an existing **Open Shipment** with a carrier and provisions the
        shipping label(s). On success you receive the carrier-generated
        tracking number, the booking status, the label document(s), and — for
        PUDO bookings — the confirmed location details.

        Create the Open Shipment first with the carrier-required information
        (addresses, weight, line items as the carrier demands), then book it
        here. The Booking feature requires account enablement — contact your
        account team.

        A booking can succeed **before** the carrier finishes generating the
        label: the response is then HTTP 299 and `download_url` /
        `base64_content` inside `documents` may be `null`. Fetch the label
        later with Retrieve a Document (URL + Base64) or List Labels (URL
        only).
      operationId: post-v5-booking
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                shipment_uuid:
                  type: string
                  format: uuid
                  description: >-
                    The Open Shipment's Perform.AI identifier. Provide this or
                    `shipment_id`.
                shipment_id:
                  type: string
                  maxLength: 50
                  description: >-
                    The Open Shipment's identifier in your system. Provide this
                    or `shipment_uuid`.
                carrier_reference:
                  type: string
                  maxLength: 50
                  description: >-
                    The carrier configuration to book with, from **Settings >
                    Carriers**; it must be enabled for booking (outbound or
                    return). Optional when the Shipment already has a
                    `carrier_reference` — the booking then uses the Shipment's
                    carrier. When provided, the request's value is used for the
                    carrier booking. Avoid sending a value that conflicts with
                    the Shipment's own carrier reference — omit the field or
                    keep them consistent. Do not send it as `null` or an empty
                    string.
                pudo_location_uuid:
                  type: string
                  format: uuid
                  description: >-
                    Route the booking to a specific PUDO location, from the PUDO
                    locations endpoint.
                additional_info:
                  type: object
                  description: Carrier-specific booking metadata.
            example:
              shipment_id: SHP-2026-000115
              carrier_reference: dhl-ecommerce-de
      responses:
        '200':
          description: Booking successful; all labels returned.
          content:
            application/json:
              schema:
                type: object
                properties:
                  api_response:
                    type: string
                  data:
                    $ref: '#/components/schemas/BookingData'
        '299':
          description: |-
            Booking successful, but the label is still being processed —
            `documents[].download_url` and/or `base64_content` are `null`.
            Warnings: `Label download_url is still under processing…` /
            `Label base64_content is still under processing…`. Fetch the label
            later; do not rebook.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessWithWarnings'
        '400':
          description: |-
            Validation failed — note the booking-specific error envelope:
            `errors` sits inside `data` alongside the Shipment identifiers, and
            each entry carries an `api_response` and `standard_error_message`.
            Nested form for fields inside objects (e.g. an address), flat form
            otherwise. Common causes: carrier not configured for
            outbound/return booking, missing address fields the carrier
            requires, or unit mismatches.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BookingValidationError'
              example:
                api_response: '4030'
                message: Validation error
                data:
                  errors:
                    carrier_reference:
                      - api_response: '4030'
                        standard_error_message: >-
                          Value provided is not defined for outbound or return.
                          Please provide the correct carrier_reference or reach
                          out to Perform.AI Customer Success team for
                          assistance.
                  shipment_id: SHP-2026-000115
                  shipment_uuid: 026c09d3-4243-4056-b412-c62411827878
        '403':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/Throttled'
        '500':
          description: System error, carrier unavailable (503), or carrier timeout (504).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RequestError'
components:
  schemas:
    BookingData:
      type: object
      description: The `data` object of a successful booking.
      properties:
        booking_uuid:
          type: string
          format: uuid
        shipment_uuid:
          type: string
          format: uuid
        shipment_id:
          type:
            - string
            - 'null'
        carrier_reference:
          type: string
        shipping_service:
          type:
            - string
            - 'null'
          description: The carrier service selected, from your carrier configuration.
        carrier_shipment_identifier:
          type:
            - string
            - 'null'
          description: Carrier-internal identifier; only some carriers provide it.
        tracking_number:
          type: string
          description: Carrier-generated tracking number.
        type_of_shipment:
          type: string
          enum:
            - outbound
            - return
        status:
          type: string
          enum:
            - booked
            - return_initiated
          description: >-
            `booked` for outbound bookings, `return_initiated` for return
            bookings.
        documents:
          type: array
          items:
            $ref: '#/components/schemas/BookingDocument'
          description: Empty when the carrier issues no label.
        pudo_location_uuid:
          type:
            - string
            - 'null'
          description: Present for PUDO bookings only.
        pudo_locations:
          type: array
          items:
            $ref: '#/components/schemas/PudoLocation'
          description: Confirmed PUDO location details; PUDO bookings only.
        carrier_additional_info:
          type: object
          description: Non-standard information returned by the carrier.
        created_date:
          type: string
        updated_date:
          type: string
    SuccessWithWarnings:
      type: object
      description: >-
        HTTP 299 — the request succeeded, but parts of it could not be applied.
        The `warnings` object maps each affected field to its messages.
      required:
        - api_response
        - warnings
      properties:
        api_response:
          type: string
          description: Always `"299"`.
        data:
          type: object
          description: The endpoint's normal success payload, when it has one.
        warnings:
          type: object
          description: Affected field → array of warning messages.
          additionalProperties:
            type: array
            items:
              type: string
    BookingValidationError:
      type: object
      description: >-
        Booking-specific validation envelope: `errors` sits inside `data`
        alongside the Shipment identifiers. Each error entry carries an
        `api_response` and a `standard_error_message`. Fields inside objects
        (e.g. an address) nest one level deeper under the object name.
      properties:
        api_response:
          type: string
          description: Always `"4030"`.
        message:
          type: string
          description: Always `Validation error`.
        data:
          type: object
          properties:
            shipment_id:
              type:
                - string
                - 'null'
            shipment_uuid:
              type:
                - string
                - 'null'
            errors:
              type: object
              description: >-
                Field (or object → field) → array of `{api_response,
                standard_error_message}` entries.
    RequestError:
      type: object
      description: >-
        A request-level error such as `4000` (invalid request format), `4041`
        (no results found), or a `5XX` system error.
      required:
        - api_response
        - message
      properties:
        api_response:
          type: string
          description: Error code as a string, e.g. `"4000"`, `"4041"`, `"500"`.
        message:
          type: string
    BookingDocument:
      type: object
      description: A label or document generated by the carrier for a booking.
      properties:
        document_uuid:
          type: string
          format: uuid
        document_id:
          type:
            - string
            - 'null'
        name:
          type: string
        type:
          type: string
          description: E.g. `shipping_label`, `shipping_label_qr`, `commercial_invoice`.
        file_format:
          type: string
        download_url:
          type:
            - string
            - 'null'
          description: >-
            1-hour expiry, regenerated per call. `null` while the label is still
            processing (HTTP 299).
        base64_content:
          type:
            - string
            - 'null'
          description: '`null` while the label is still processing (HTTP 299).'
        created_date:
          type: string
        additional_info:
          type: object
          description: E.g. label size (A6, 4x6) or ZPL dialect.
    PudoLocation:
      type: object
      description: One pick-up/drop-off location.
      properties:
        pudo_location_uuid:
          type: string
          format: uuid
        uuid:
          type: string
          format: uuid
          deprecated: true
          description: Legacy name for `pudo_location_uuid`. Removed end of July 2026.
        carrier_id:
          type: string
          description: Perform.AI 6-character carrier ID operating this location.
        pudo_location_id:
          type: string
          description: Carrier-unique location ID.
        address:
          $ref: '#/components/schemas/PudoAddress'
        lat:
          type: number
        lng:
          type: number
        distance_meters:
          type:
            - number
            - 'null'
          description: >-
            Distance from the provided `coordinates` or `search` address; used
            for distance sorting.
        operating_hours_calc:
          type: array
          items:
            type: object
            properties:
              service_name:
                type:
                  - string
                  - 'null'
              operating_day:
                type: string
              time_zone:
                type: string
              first_open_hours:
                type:
                  - string
                  - 'null'
              second_open_hours:
                type:
                  - string
                  - 'null'
              first_cutoff:
                type:
                  - string
                  - 'null'
              second_cutoff:
                type:
                  - string
                  - 'null'
        opening_hours:
          type: array
          items:
            type: object
            properties:
              day_of_week:
                type: string
              open_hour:
                type: string
              close_hour:
                type: string
        cutoff_hours:
          type: array
          items:
            type: object
            properties:
              service:
                type:
                  - string
                  - 'null'
              day_of_week:
                type: string
              cutoff_at:
                type: string
        closing_periods:
          type: array
          items:
            type: object
            properties:
              from_date:
                type: string
              to_date:
                type: string
              reason:
                type:
                  - string
                  - 'null'
        validity_period:
          type: object
          properties:
            from_date:
              type: string
            to_date:
              type: string
        services:
          type: array
          items:
            type: string
        additional_info:
          type: object
          description: Non-standardized carrier-specific information.
        updated_date:
          type: string
    GatewayError:
      type: object
      description: >-
        An error generated at the API gateway — authorization (`403`) or
        throttling (`429`). Note `api_response` is a number here, unlike
        application-level responses where it is a string.
      required:
        - api_response
        - message
      properties:
        api_response:
          type: integer
          description: '`403` or `429`.'
        message:
          type: string
          description: E.g. `Key not authorized`, `Quota exceeded`, `Throttled`.
    PudoAddress:
      type: object
      description: Standardized address of a PUDO location.
      properties:
        location_types:
          type: array
          items:
            type: string
          description: Carrier-original location types.
        mapped_location_types:
          type: array
          items:
            type: string
          description: Perform.AI standardized location types.
        location_type:
          type:
            - string
            - 'null'
          deprecated: true
          description: >-
            Legacy single value. Removed end of August 2026 — use
            `location_types`.
        mapped_location_type:
          type:
            - string
            - 'null'
          deprecated: true
          description: >-
            Legacy single value. Removed end of August 2026 — use
            `mapped_location_types`.
        entity_reference:
          type:
            - string
            - 'null'
        address_name:
          type:
            - string
            - 'null'
        full:
          type: string
        line1:
          type:
            - string
            - 'null'
        line2:
          type:
            - string
            - 'null'
        line3:
          type:
            - string
            - 'null'
        street_name:
          type:
            - string
            - 'null'
        house_number:
          type:
            - string
            - 'null'
        postal_code:
          type:
            - string
            - 'null'
        city:
          type:
            - string
            - 'null'
        state_or_province:
          type:
            - string
            - 'null'
        region:
          type:
            - string
            - 'null'
        country:
          type:
            - string
            - 'null'
        country_code:
          type:
            - string
            - 'null'
        phone:
          type:
            - string
            - 'null'
          description: Not subscribed to notifications.
  responses:
    Unauthorized:
      description: >-
        The Bearer token is expired, invalid, or missing — or the account lacks
        access.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/GatewayError'
          example:
            api_response: 403
            message: Key not authorized
    Throttled:
      description: Rate limit exceeded (40 requests per second per account).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/GatewayError'
          example:
            api_response: 429
            message: Throttled
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      description: >-
        Used by every functional endpoint. Generate the token with `POST
        /auth/oauth/token/` and send it as `Authorization: Bearer {token}`.

````