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

# Show a fulfillment request with its picking lines



## OpenAPI

````yaml /openapi-v2beta.json get /teams/{teamUuid}/wms/fulfillments/{fulfillmentIdentifier}
openapi: 3.1.0
info:
  title: Smart Send API
  description: >
    Shipment-centred API for discovering shipping services, booking immutable
    shipments, tracking parcels, downloading business documents, and printing.


    ## Contract status


    This v2 beta specification describes the target API contract agreed during
    the API design review. It is not a declaration that every operation and
    behaviour has already been deployed. The implementation must be brought into
    conformance before this contract is announced as available.


    ## Shipments and booking


    A shipment represents one logical carrier booking. Integrations own their
    webshop orders and store the returned shipment UUID, tracking numbers,
    documents and drop-off codes on those orders. There is no order
    synchronisation resource and no editing or rebooking of accepted shipment
    input.


    POST /teams/{teamUuid}/shipments validates before persistence and starts
    booking immediately. Upfront validation failure is 422 and creates no
    shipment. A successful booking returns 201. A definitive carrier rejection
    returns 424 with the persisted failed ShipmentResponse. Technical failures
    use appropriate 5xx responses. 424 is the application-specific use of Failed
    Dependency defined by RFC 4918, not a universal carrier convention.


    The server waits up to 10 seconds for the complete booking workflow. If
    processing continues, it returns 202 with ShipmentResponse, Location
    pointing to the ordinary shipment GET, and Retry-After: 5. Follow Location
    with GET. A successful GET always returns 200 with the current
    ShipmentResponse, including while booking is in progress or has failed. The
    response schema is the same; the representation is current, not a frozen
    copy of an earlier HTTP body. The worker's final booking deadline is
    separate from this HTTP wait. A rare late carrier success updates the same
    shipment.


    Booked means the carrier booking has succeeded and all required documents,
    QR codes and drop-off codes are ready. Printing is a separate process and
    does not delay booked. A completed carrier booking must never be repeated to
    recover a document-generation failure. Once the carrier has accepted a
    booking, deletion is forbidden even if document generation subsequently
    fails.


    ## Carrier roles


    Shipment delivery and shipment-specific delivery options expose carrier and
    last_mile_carrier as separate objects, each containing code, name, logo_url
    and icon_url. carrier identifies the provider whose service and account are
    used to book the shipment. service_code continues to identify that carrier's
    service; last_mile_carrier is response data and cannot be selected
    independently in booking input.


    last_mile_carrier is the expected final delivery partner configured for the
    selected shipping route. It is null when unknown. When the booking carrier
    also performs final delivery, return that carrier explicitly in both fields.
    This is planned delivery information, not a confirmation of a physical
    handoff or delivery. Snapshot the expected partner when accepting the
    shipment; later route-configuration changes do not rewrite that shipment's
    attribution. A last-mile partner does not require a separate carrier account
    for the team.


    Last mile follows the physical direction: delivery to the customer for
    outbound shipments, and delivery to the merchant for returns. It does not
    identify the customer's return drop-off network. Carrier branding does not
    change service-point identifiers or tracking numbers and URLs.


    The general GET /teams/{teamUuid}/routes response does not expose
    last_mile_carrier in this version. Its carrier object describes the provider
    whose services the team can book.


    ## Parties, delivery and defaults


    parties.merchant and parties.customer have stable commercial meanings,
    including on returns. When merchant is omitted, use the team's outbound
    sender address or return address as appropriate, falling back to the
    outbound address when no return address is configured. Pickup points,
    selected addons and delivery windows belong to delivery.


    Resolve and snapshot effective booking settings when accepting the shipment,
    including when adding it to an open batch. Later team-setting changes do not
    mutate accepted shipments. This contract has no per-booking overrides of
    team document or automatic-print preferences. Ordered team format
    preferences are negotiated up front; reject an incompatible selection with
    422 rather than silently choosing an unaccepted format. Carrier-specific
    constraints can still cause a subsequent booking failure.


    ## Currency and measurement units


    Each shipment must explicitly supply currency, weight_unit and
    dimension_unit, including each shipment submitted to a batch. The same
    requirement applies to shipment-specific delivery-options input. Missing,
    null or invalid values return 422; these fields never fall back to team
    defaults. Upfront shipment validation creates no shipment, and batch-add
    validation adds none of that request.


    A shipment uses one currency for its monetary amounts, one weight unit for
    all parcel and item weights, and one dimension unit for all parcel and item
    dimensions. Per-value overrides are not supported. Preserve the explicitly
    accepted values in responses. A batch or list may contain shipments with
    different units; each shipment carries its own context. Templates may be
    partial, but the integration must include all three fields in the final
    merged request.


    Service-point proximity results retain a distance object with value and unit
    on each result. Distance is returned only by the closest search, in metres,
    and is not moved into response metadata.


    ## Documents and codes


    Document means a completed business document intended for viewing or
    printing, such as a label, customs declaration, report or end-of-day
    manifest. Documents are team resources and may be associated with shipments,
    reports or manifests. QR images and machine-readable data exports are not
    Document resources.


    Shipment.documents embeds its booking documents, including metadata and
    expiring download URLs, never base64 file data. A document may cover
    multiple parcels or multiple document types. qr_codes and drop_off_codes are
    separate arrays directly on Shipment. A shared QR code is one array entry.
    Where a carrier returns one code per parcel, array index n corresponds to
    parcels[n]; no explicit parcel relation is exposed for these codes. Parcel
    and code order remains stable across responses.


    GET and idempotent replay can refresh file URLs without rebooking,
    generating documents again, or submitting print jobs. Access to an expired
    URL is recovered by retrieving the owning resource again.


    ## Documents, printers and print jobs


    Document represents one completed file. Its metadata is identical when
    embedded in a shipment or returned by document list/detail endpoints. width
    and height are distance objects in millimetres at document level; page_count
    is the number of pages or labels in the file. Every page or label must have
    the same dimensions in its finished orientation. For example, 101.6 × 152.4
    mm labels and an A4 invoice are separate documents with separate files. A
    document can contain multiple pages of the same size. Dimensions and
    page_count are null when unknown or not applicable, such as an XLSX report
    without fixed pagination. Null must not be used to disguise mixed page
    sizes. Store dimensions and page count when producing the file so metadata
    reads do not fetch or parse file contents.


    Document.print_status exposes the progress of the most recently created
    local print attempt directly in document and shipment responses. A null
    print_status means no local print request exists; the field is still
    present. Null does not mean an unknown outcome. pending means the request is
    recorded and Smart Send is preparing or waiting to submit it; queued means
    the print service has accepted it; printing means the provider reports
    processing; printed means the best available successful completion
    acknowledgement; failed means a known failure; unknown means the current
    outcome cannot be established. These attempt states have the same meanings
    as PrintJob.state. Printed currently means delivery to the operating-system
    print queue. Printing a downloaded file outside Smart Send is not observed.


    Select the most recently created print attempt by creation time and a stable
    creation-order tie-breaker, not by updated_at or callback arrival time. A
    new reprint immediately becomes the attempt represented by print_status,
    even after an earlier print succeeded. For example, printed can become
    pending and then failed. Delayed updates to older jobs update their own
    history without overriding the newer attempt's status.


    Retrieve all print attempts separately with GET
    /teams/{teamUuid}/print-jobs?document_uuid=... and follow the cursor until
    the end. Each PrintJob contains its state, fixed printer identity, copy
    count, error and timestamps. Earlier successful attempts remain in the
    history after a later failure. Document.updated_at advances when its
    published print_status or other document metadata changes; each job has its
    own updated_at. Print updates do not advance Shipment.updated_at or change
    its booking or tracking state. On a thin print_job.updated webhook, use
    document_uuid to retrieve the current document; the notification may concern
    an older attempt.


    Printer is current team configuration: identity, display name, availability,
    supported formats and paper_sizes. paper_sizes is null when unknown,
    otherwise an array of driver-advertised named sizes with width and height
    distance objects in millimetres. Individual dimensions are null when only
    the name is known. An empty array means the provider reported no named
    sizes, not that printing or custom sizes are unsupported. Multiple sizes may
    be advertised at once. This list does not map sizes to trays or confirm
    which paper is currently loaded. GET /printers/{printer} returns that
    current resource. Default selection rules are part of team settings and may
    choose different printers for different file formats and page layouts. Print
    jobs embed only the selected printer identity captured for the attempt, so
    later renames, availability changes or removal do not rewrite history. They
    also embed the document identity and display metadata captured when the job
    was created; current document metadata is retrieved through the document
    endpoint.


    One PrintJob represents one logical print attempt for an entire completed
    file and a copy count. All print attempts use the same public
    representation, regardless of how they were initiated. Record accepted print
    intent locally before file preparation or external submission; setup failure
    then produces a failed job rather than disappearing. When booking also
    requests printing, record the corresponding local jobs before returning
    document metadata so the response shows pending, or a later state if already
    reached. Printing itself remains asynchronous. printer may be null if an
    accepted attempt has not selected a target or failed before selection. Once
    selected, the target is fixed for the attempt. POST /print-jobs validates
    its target before accepting a job and returns 422 when invalid. Rejected
    requests create no print attempt and do not change the document's current
    print_status.


    POST /print-jobs returns 201 once the local job is durably accepted,
    normally pending. Printing continues asynchronously; retrieve Location or
    consume print_job.updated notifications. POST and GET return the same
    PrintJobResponse structure. queued means accepted by the print service;
    printed requires its best available completion acknowledgement, currently
    delivery to the operating-system print queue. Printing is independent of
    document readiness and shipment booking state. Duplicate or delayed provider
    updates must not erase a confirmed success; a subsequent successful
    acknowledgement clears a previous failure on the same job. Reprints create
    separate jobs, and unknown outcomes must be checked before requesting
    another print to avoid duplicate output.


    ## Idempotency


    Idempotency-Key is optional on operations that declare it. Without a key,
    each valid create request is independent, even for identical content. No key
    is generated from the payload. Use a fresh client-generated key for each
    intended action and reuse it for recovery after a lost response.


    Keys are scoped to the team, HTTP method and canonical target path. A key
    binds atomically to the accepted action and its resources, with a request
    fingerprint. Object-key ordering is ignored; array order is significant.
    Resolve defaults only once for the accepted action. A changed payload with
    the same key is 422 with a validation error for Idempotency-Key. A
    concurrent duplicate is 409 with Retry-After and, when known, Location. Once
    completed, reconstruct the result from the stored outcome and current
    resource representation and return Idempotency-Replayed: true. URLs and
    subsequent resource state can therefore differ from the first response. For
    shipment creation, the status reflects the booking outcome: 201 for success
    or 424 for carrier rejection, even if a later cancellation has changed the
    current shipment state.


    Retain keys for at least 24 hours from acceptance and never expire an
    actively processing action. After expiry, reusing a key may execute a new
    action. Authentication, authorisation and upfront validation failures do not
    reserve a key. The header does not replace the 202/Location polling flow.
    Idempotency-Replayed is this API's documented extension, not a standard HTTP
    header.


    ## HTTP errors


    Request errors use JSON: message for an ordinary error, with an additional
    errors object for 422 validation failures. There is no custom error code
    field. Use the HTTP status, documented response headers and resource state
    to decide what to do; message text may be localised and can change. Send
    Accept: application/json.


    | Status | Meaning | Client action |

    | --- | --- | --- |

    | 401 | Missing or invalid authentication. | Supply valid credentials. |

    | 403 | Missing permission or scope. | Check team access and permissions. |

    | 404 | Resource unavailable to this team. | Check the resource identifier
    and team. |

    | 409 with Retry-After | An action with this idempotency key is still
    processing. | Wait, then GET Location if supplied; otherwise retry the
    original request with the same key and payload. |

    | 409 without Retry-After | Conflict with resource state or an ambiguous
    tracking lookup. | Retrieve current state or supply the documented tracking
    filters. Do not automatically repeat an unchanged request. |

    | 410 | Tracking cursor expired. | Resynchronise and establish a new feed
    position. |

    | 422 | Invalid input, including reuse of a key with different input. |
    Correct the entries in errors. Upfront booking validation creates no
    shipment; batch-add validation adds none of that request. |

    | 424 | Carrier rejected an accepted booking. | Inspect the persisted failed
    ShipmentResponse. Corrected input requires a new shipment. |

    | 429 | Rate limit reached. | Wait for Retry-After. |

    | 500 | Unexpected server failure. | Recover using the known resource URL or
    original idempotency key; include Request-ID in support reports. |

    | 502 | Accepted booking workflow failed technically. | Inspect the failed
    ShipmentResponse; recover documents without rebooking after carrier
    acceptance. |

    | 503 | Temporary service unavailability. | Wait for Retry-After; preserve
    the original idempotency key when retrying an action. |

    | 504 | Final booking deadline expired. | Inspect the persisted failed
    ShipmentResponse; a rare late carrier success may still update it. |


    The distinction between the two 409 cases using Retry-After is this API's
    convention, not a universal HTTP rule. The usual 10-second booking wait
    returns 202, not 504. A later GET returns 200 when retrieval succeeds, even
    when the shipment's state is failed. Booking-specific 424/502/504 responses
    keep the ShipmentResponse shape rather than switching to a generic
    message-only body.


    ### Invalid shipment input


    ```http

    HTTP/1.1 422 Unprocessable Content

    Content-Type: application/json

    Request-ID: req-example-validation


    {
      "message": "The customer postal code is required.",
      "errors": {
        "parties.customer.address.postal_code": [
          "The customer postal code is required."
        ]
      }
    }

    ```


    ### Batch membership is locked


    ```http

    HTTP/1.1 409 Conflict

    Content-Type: application/json

    Request-ID: req-example-batch


    {
      "message": "Shipments can only be added to an open batch."
    }

    ```


    ### An idempotent request is still processing


    ```http

    HTTP/1.1 409 Conflict

    Content-Type: application/json

    Retry-After: 5

    Request-ID: req-example-processing


    {
      "message": "A request with this Idempotency-Key is still being processed."
    }

    ```


    Location may additionally identify the resource when known. Browser clients
    must be able to read Location, Retry-After, Request-ID and
    Idempotency-Replayed on cross-origin responses; the server exposes these
    through Access-Control-Expose-Headers.


    ## Pagination and synchronisation


    Paginated requests use cursor and per_page for cursor pagination, or page
    and per_page for page pagination. Omit cursor or page for the first page.
    Page numbers start at 1; cursors are opaque. Page-size defaults and limits
    are declared for each endpoint.


    All paginated responses contain data, links and meta. links always contains
    first, last, prev and next. Cursor pagination sets first and last to null;
    its meta contains path, per_page, next_cursor and prev_cursor. Page
    pagination provides first/last URLs and meta.current_page, from, last_page,
    links, path, per_page, to and total. Its meta.links is a navigation window;
    labels are display text, and ellipsis entries omit page. An empty page has
    an empty data array and null from/to. meta.path is the collection URL
    without query parameters.


    Follow the returned navigation URLs with GET. They preserve filters,
    sorting, per_page and the fixed sync boundary where applicable. Changing
    these values starts a new page sequence. Shipments add meta.sync_until and
    tracking adds meta.resume_cursor as endpoint-specific extensions. Cursor
    pagination does not provide a total count or last page number.


    Shipment lists represent current resources, not every intermediate change.
    Shipment.updated_at follows its booking lifecycle, including cancellation;
    tracking changes, print updates and refreshed file URLs do not advance it.
    For incremental sync use inclusive updated_since, sort=updated_at and the
    server-provided sync_until boundary. Follow all next links, then persist
    that boundary. On the next round, subtract an overlap (60 seconds is a
    suggested starting point) and upsert by shipment UUID. Mutable timestamps
    can cause duplicates or omit intermediate states; overlap does not turn this
    into a lossless history. Use include_deleted=true for minimal deletion
    markers and periodic reconciliation where necessary.


    The dedicated tracking/events endpoint is append-only and uses publication
    order, not carrier event time. Its resume_cursor remains usable at the end
    of a page sequence, including empty responses. ETA changes also produce feed
    entries. Tracking and print resources have their own timestamps.


    ## Webhooks and batch callbacks


    Team webhooks are configured through team settings. A batch may additionally
    register its own callback during creation. Both use the same signed thin
    event envelopes: event id, type, occurred_at, team_uuid and affected
    resource identifiers. Retrieve full resource data through the ordinary
    authenticated API when needed. A GET returns current state, which can differ
    from the state when the event occurred. Tracking notifications wake the
    consumer to resume the tracking event feed; deletion notifications identify
    what to remove without requiring a successful GET. Full payloads may be
    added later as an explicit opt-in. Delivery can be duplicated or arrive out
    of order; deduplicate by event id and retrieve the current resource when
    needed. A callback failure never repeats a booking or print action.
    Signatures follow the Standard Webhooks convention. See the callback and
    webhook definitions for delivery and acknowledgement rules.


    ## Localisation and request identification


    Accept-Language takes precedence over the team's default language, with
    English as fallback. Carrier, service and addon codes are stable; names and
    messages may be localised. Error messages are for people, not client control
    flow. A descriptive User-Agent identifies the integration. Request-ID is
    returned on every API response and should be included in support reports.
    Currency amounts use the ISO 4217 currency's minor unit; null means unknown,
    not zero. Dates use RFC 3339 with an explicit UTC offset.
  version: 2.0.0-beta
  contact:
    name: Smart Send
    url: https://www.smartsend.io
  x-contract-status: design
  x-design-defaults:
    http_wait_seconds: 10
    poll_after_seconds: 5
    idempotency_retention_hours: 24
    list_default_per_page: 100
    list_max_per_page: 1000
    batch_add_max_shipments: 100
    webhook_retry_window_hours: 24
    tracking_feed_retention_days: 90
  x-webhook-payload-mode: thin
servers:
  - url: https://api.smartsend.io/v2
    description: Production
security:
  - bearerAuth: []
  - oauth2: []
tags:
  - name: Me
    description: Information about the authenticated user
  - name: Teams
    description: Teams available to the authenticated user
  - name: Service Points
    description: Pickup points and delivery locations
  - name: Carrier Catalog
    description: >-
      Global reference data for carriers, services, and addons. Not
      team-specific.
  - name: Routing
    description: >-
      Team-specific listing of available carriers, services, and addons based on
      configured carrier accounts. Pre-shipment meaning no shipment details
      required.
  - name: Delivery Options
    description: >-
      Shipment-specific delivery options including available services, addons,
      estimated pricing, and delivery windows.
  - name: Tracking
    description: Shipment tracking information and event history
  - name: Shipments
    description: >-
      Immutable booking input, one logical booking per shipment, cancellation
      and synchronisation.
  - name: Booking batches
    description: >-
      Validate shipments before adding them to a batch; after start, book one
      shipment at a time in insertion order.
    externalDocs:
      description: Batch booking documentation
      url: https://docs.smartsend.io/features/booking#batch-booking
  - name: Shipment Templates
    description: >-
      Reusable shipment templates for quickly creating shipments with
      pre-configured delivery, consignment, and parcel settings.
  - name: WMS Experimental
    description: >-
      Warehouse management for a team's configured WMS driver. Covers
      fulfillment requests (listing open requests, inspecting picking lines,
      recording packed lines), inventory levels (listing, moving between bins,
      adjusting counts), and catalog items (SKU lookup).
  - name: Documents
    description: >-
      Completed business documents for viewing or printing, with metadata and
      download links.
  - name: Printing
    description: Discover printers and follow document print jobs.
  - name: Webhooks
    description: Signed resource updates and batch-specific callbacks.
paths:
  /teams/{teamUuid}/wms/fulfillments/{fulfillmentIdentifier}:
    parameters:
      - $ref: '#/components/parameters/teamUuid'
      - $ref: '#/components/parameters/wmsFulfillmentIdentifier'
    get:
      tags:
        - WMS Experimental
      summary: Show a fulfillment request with its picking lines
      operationId: showWmsFulfillment
      parameters:
        - $ref: '#/components/parameters/Request-ID'
      responses:
        '200':
          description: The fulfillment request and its lines.
          headers:
            Request-ID:
              $ref: '#/components/headers/Request-ID'
          content:
            application/json:
              schema:
                type: object
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/WmsFulfillmentDetail'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'
      security:
        - bearerAuth: []
        - oauth2:
            - fulfillment:read
components:
  parameters:
    teamUuid:
      name: teamUuid
      in: path
      required: true
      schema:
        type: string
        format: uuid
      description: Team uuid. All resources are scoped to this team.
    wmsFulfillmentIdentifier:
      name: fulfillmentIdentifier
      in: path
      required: true
      schema:
        type: string
        minLength: 1
        examples:
          - '1234567890'
      description: >-
        Identifier of a fulfillment request as returned by the team's WMS
        driver.
    Request-ID:
      name: Request-ID
      in: header
      required: false
      schema:
        type: string
        minLength: 1
        maxLength: 64
        pattern: ^[A-Za-z0-9._-]{1,64}$
      description: >-
        Optional client-supplied request identifier. When provided and matching
        the validation pattern, the value is echoed back in the `Request-ID`
        response header. Otherwise the server generates one. Use this to
        correlate requests between client and server when reporting issues.
      examples:
        uuid:
          summary: UUID v7
          value: 019c486f-c237-76f5-85e1-ba7017a77024
        opaque:
          summary: Opaque client-generated key
          value: booking-12345-at-1768609378
  headers:
    Request-ID:
      description: >-
        Unique identifier for this HTTP request. Always present in responses.
        Echoes the client-supplied `Request-ID` request header when it matches
        the validation pattern; otherwise the server generates a UUIDv7. Include
        this value when reporting issues so support can locate the request in
        logs.
      schema:
        type: string
        minLength: 1
        maxLength: 64
        pattern: ^[A-Za-z0-9._-]{1,64}$
    Retry-After:
      description: >-
        Delay in seconds before the next polling or retry request. Booking
        polling normally uses 5.
      schema:
        type: integer
        minimum: 1
        examples:
          - 5
  schemas:
    WmsFulfillmentDetail:
      allOf:
        - $ref: '#/components/schemas/WmsFulfillment'
        - type: object
          required:
            - lines
          properties:
            lines:
              type: array
              description: Picking lines for this fulfillment request.
              items:
                $ref: '#/components/schemas/WmsFulfillmentLine'
    WmsFulfillment:
      type: object
      description: >-
        A fulfillment request emitted by the team's WMS driver. A single order
        may produce multiple fulfillment requests (e.g. items shipped from
        different locations).
      required:
        - identifier
        - order_identifier
        - order_reference
        - status
      properties:
        identifier:
          type: string
          description: Driver-specific fulfillment request identifier.
          examples:
            - '1234567890'
        order_identifier:
          type: string
          description: The order identifier this fulfillment belongs to.
          examples:
            - '9876543210'
        order_reference:
          type: string
          description: Human-readable order reference.
          examples:
            - '#1001'
        status:
          type: string
          enum:
            - OPEN
            - IN_PROGRESS
          description: Fulfillment request status as reported by the driver.
          examples:
            - OPEN
    WmsFulfillmentLine:
      type: object
      description: A single picking line within a fulfillment request.
      required:
        - identifier
        - sku
        - description
        - quantity
      properties:
        identifier:
          type: string
          description: Driver-specific line identifier.
          examples:
            - '555000111'
        sku:
          type: string
          examples:
            - TSHIRT-RED-M
        barcode:
          type:
            - string
            - 'null'
          description: EAN/barcode if the item carries one.
          examples:
            - '5901234123457'
        description:
          type: string
          examples:
            - Red T-shirt, size M
        quantity:
          type: integer
          minimum: 0
          examples:
            - 2
        image_url:
          type:
            - string
            - 'null'
          format: uri
        bin:
          type:
            - string
            - 'null'
          description: Bin location to pick from, when known.
          examples:
            - A1-04
    ErrorResponse:
      type: object
      required:
        - message
      properties:
        message:
          type: string
          description: Human-readable error message
          examples:
            - Something unexpected happened.
    RateLimitErrorResponse:
      type: object
      required:
        - message
      properties:
        message:
          type: string
          description: Human-readable error message indicating rate limit exceeded
  responses:
    Unauthorized:
      description: Authentication credentials were missing or invalid.
      headers:
        Request-ID:
          $ref: '#/components/headers/Request-ID'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            Unauthenticated:
              $ref: '#/components/examples/Unauthenticated'
    Forbidden:
      description: The authenticated user does not have permission to perform this action.
      headers:
        Request-ID:
          $ref: '#/components/headers/Request-ID'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            PermissionDenied:
              $ref: '#/components/examples/PermissionDenied'
    NotFound:
      description: The requested resource was not found.
      headers:
        Request-ID:
          $ref: '#/components/headers/Request-ID'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            ResourceNotFound:
              $ref: '#/components/examples/ResourceNotFound'
    TooManyRequests:
      description: Rate limit exceeded. Wait before retrying.
      headers:
        Request-ID:
          $ref: '#/components/headers/Request-ID'
        Retry-After:
          $ref: '#/components/headers/Retry-After'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/RateLimitErrorResponse'
          examples:
            TooManyRequests:
              $ref: '#/components/examples/TooManyRequests'
    InternalServerError:
      description: An unexpected error occurred on the server.
      headers:
        Request-ID:
          $ref: '#/components/headers/Request-ID'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            ServerError:
              $ref: '#/components/examples/ServerError'
  examples:
    Unauthenticated:
      summary: 401 — Missing or invalid credentials
      value:
        message: Unauthenticated.
      description: >-
        Supply a valid API token. Repeating the same credentials does not
        resolve this response.
    PermissionDenied:
      summary: 403 — Insufficient team permission
      value:
        message: This action is unauthorized.
      description: Use credentials with the required team permission or scope.
    ResourceNotFound:
      summary: 404 — Resource unavailable to this team
      value:
        message: The requested resource was not found.
      description: >-
        Check the resource UUID and team. A missing, deleted or other-team
        resource uses the same response.
    TooManyRequests:
      summary: 429 — Rate limit reached
      value:
        message: Too Many Attempts.
      description: >-
        Wait for the number of seconds in Retry-After before sending another
        request.
    ServerError:
      summary: 500 — Unexpected server failure
      value:
        message: Server Error
      description: >-
        An action may already have been accepted. Recover through its known
        resource URL or retry with the original Idempotency-Key. Include
        Request-ID when contacting support.
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
    oauth2:
      type: oauth2
      description: OAuth 2.0 Authorization Code flow for API access
      flows:
        authorizationCode:
          authorizationUrl: https://app.smartsend.io/oauth/authorize
          tokenUrl: https://app.smartsend.io/oauth/token
          scopes:
            teams:read: Access team information
            members:read: Read team member information
            members:write: Manage team members
            service_points: Access service points and pickup locations
            routing: Access team-specific routing (pre-shipment discovery)
            delivery-options:read: Get shipping rates and pricing
            tracking:read: Access shipment tracking information
            shipment:read: Read shipment information
            shipment:write: Create and manage shipments
            inventory:read: Read team WMS inventory levels and items
            inventory:write: Mutate team WMS inventory (move stock, update counts)
            fulfillment:read: Read team WMS fulfillment requests
            fulfillment:write: Mutate team WMS fulfillment requests (pack)
            documents:read: Read team business documents, including reports and manifests
            printing:read: Read printers and document print jobs
            printing:write: Create document print and reprint jobs

````