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

# Add available services to a shipment

> The response to the `ship-by-loop.services.requested` webhook.

### Required OAuth scope
- `ship_by_loop:write`



## OpenAPI

````yaml post /ship-by-loop/shipments/{shipmentId}/services
openapi: 3.1.0
info:
  title: Ship by Loop - External Shipping Provider API
  version: 1.0.0
  description: >-
    Endpoints an external shipping provider uses to fulfill shipments created
    within Ship by Loop.


    A provider calls these endpoints in response to the webhooks documented in
    [Ship by Loop shipment
    events](/webhook-reference/topics/ship-by-loop-shipment-webhook):


    1. `POST /ship-by-loop/shipments/{shipmentId}/services` — add available
       service(s) to the shipment, in response to `ship-by-loop.services.requested`.
    2. `POST /ship-by-loop/shipments/{shipmentId}/orders` — record order
       information for the services purchased, along with tracking and label
       details, in response to `ship-by-loop.purchase.requested`.
    3. `POST /ship-by-loop/shipments/{shipmentId}/errors` — report one or more
       problems the provider could not resolve on its own (e.g. the carrier
       rejected an address, or a package can't be serviced). Call this any
       time such an error occurs — it isn't tied to a specific webhook trigger.
servers:
  - url: https://api.loopreturns.com/api/{version}
    description: Production
    variables:
      version:
        default: latest
        description: >-
          `v2` is not a valid version segment — a request to `/api/v2/...`
          returns a 404. Use one of the values listed below instead.
        enum:
          - v1
          - latest
          - 2026-07
          - 2026-10
          - unstable
security:
  - oauth2:
      - ship_by_loop:write
tags:
  - name: Ship by Loop
paths:
  /ship-by-loop/shipments/{shipmentId}/services:
    post:
      tags:
        - Ship by Loop
      summary: Add available services to a shipment
      description: |-
        The response to the `ship-by-loop.services.requested` webhook.

        ### Required OAuth scope
        - `ship_by_loop:write`
      operationId: addShipmentServices
      parameters:
        - $ref: '#/components/parameters/ShipmentId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AddServicesRequest'
            examples:
              singleService:
                summary: One service covering one package
                value:
                  services:
                    - external_id: svc_ground
                      name: Ground Advantage
                      carrier: USPS
                      packages:
                        - 385e1705-ca07-41ba-b62e-49ac9065f2a4
              multipleServices:
                summary: Two services covering two packages
                value:
                  services:
                    - external_id: svc_ground
                      name: Ground Advantage
                      carrier: USPS
                      packages:
                        - bcc9cd48-ebdc-4d95-8116-fc58a323f3b7
                    - external_id: svc_express
                      name: Express 2-Day
                      carrier: UPS
                      packages:
                        - 37542eb3-1e35-4a0e-9c88-db3e3962091e
              sharedPackage:
                summary: >-
                  Two services offered for the same package (shopper carrier
                  choice)
                value:
                  services:
                    - external_id: svc_ground
                      name: Ground Advantage
                      carrier: USPS
                      packages:
                        - 6f2b6a34-df3c-4a1b-9e3e-6a7b6a1c2d3e
                    - external_id: svc_express
                      name: Express 2-Day
                      carrier: UPS
                      packages:
                        - 6f2b6a34-df3c-4a1b-9e3e-6a7b6a1c2d3e
              oneServiceAllPackages:
                summary: One service covering every package in the shipment
                value:
                  services:
                    - external_id: svc_ground
                      name: Ground Advantage
                      carrier: USPS
                      packages:
                        - 6f2b6a34-df3c-4a1b-9e3e-6a7b6a1c2d3e
                        - 8a1c2d3e-6f2b-4a34-9e3e-df3c6a7b6a1c
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/ShipmentNotFound'
        '422':
          $ref: '#/components/responses/AddServicesUnprocessableEntity'
        '500':
          $ref: '#/components/responses/InternalServerError'
components:
  parameters:
    ShipmentId:
      name: shipmentId
      in: path
      required: true
      description: The id of the Shipment
      schema:
        type: string
        examples:
          - ff8a4470-41e0-4cc3-9bfe-44564f4286b7
  schemas:
    AddServicesRequest:
      type: object
      additionalProperties: false
      required:
        - services
      properties:
        services:
          type: array
          minItems: 1
          items:
            $ref: '#/components/schemas/ExternalService'
    ExternalService:
      type: object
      additionalProperties: false
      required:
        - external_id
        - name
        - carrier
        - packages
      properties:
        external_id:
          type: string
          maxLength: 64
          description: The provider's identifier for the service
          examples:
            - svc_ground
        name:
          type: string
          maxLength: 100
          description: The human-readable service name
          examples:
            - Ground Advantage
        carrier:
          type: string
          maxLength: 100
          description: The carrier fulfilling the service
          examples:
            - USPS
        packages:
          type: array
          minItems: 1
          description: >-
            The ids of the packages this service covers. The same package id may
            appear under more than one service (e.g. offering the shopper a
            carrier choice), and a single service may list every package id in
            the shipment.
          items:
            type: string
            examples:
              - 0565b5e0-f2dd-469e-9ad7-f913fa689fc4
    AuthError:
      type: object
      description: >-
        Returned when the access token or API key itself is missing, invalid,
        expired, or unrecognized.
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              examples:
                - '401'
            http_code:
              type: string
            message:
              type: string
              examples:
                - Unauthorized.
    ScopeError:
      type: object
      description: >-
        Returned when the credentials are valid but lack the
        `ship_by_loop:write` scope for this endpoint.
      required:
        - errors
      properties:
        errors:
          type: string
          examples:
            - Unauthorized.
    ValidationError:
      type: object
      description: Request body failed validation.
      properties:
        message:
          type: string
          examples:
            - The services field is required
        errors:
          type: object
          additionalProperties:
            type: array
            items:
              type: string
          examples:
            - services:
                - The services field is required
    ShippingError:
      type: object
      properties:
        errors:
          type: array
          items:
            type: string
            examples:
              - >-
                Package 27edf77e-21f5-4ae7-8d4c-b32901d51226 does not belong to
                shipment faf035fd-9064-4b75-94a2-a6aeac7eac31
  responses:
    NoContent:
      description: The request was processed successfully
    Unauthorized:
      description: >-
        The access token is missing, invalid, or expired, or it lacks the
        `ship_by_loop:write` scope. The response body differs depending on which
        of those is the case (see the two examples below).
      content:
        application/json:
          schema:
            oneOf:
              - $ref: '#/components/schemas/AuthError'
              - $ref: '#/components/schemas/ScopeError'
          examples:
            invalidCredentials:
              summary: Missing, invalid, or expired credentials
              value:
                error:
                  code: '401'
                  http_code: GEN-UNAUTHORIZED
                  message: Unauthorized.
            missingScope:
              summary: Valid credentials, missing the required scope
              value:
                errors: Unauthorized.
    Forbidden:
      description: >-
        The caller is not permitted to modify this shipment. The response body
        is empty.
    ShipmentNotFound:
      description: No shipment matches `shipmentId`. The response body is empty.
    AddServicesUnprocessableEntity:
      description: The request could not be processed
      content:
        application/json:
          schema:
            oneOf:
              - $ref: '#/components/schemas/ValidationError'
              - $ref: '#/components/schemas/ShippingError'
          examples:
            validationFailure:
              summary: Payload failed validation
              value:
                errors:
                  services:
                    - The services field is required
            domainFailure:
              summary: Business rule violation
              value:
                errors:
                  - >-
                    Package a25cc361-6d65-4f8b-a78b-15b0657bc35a does not belong
                    to shipment 7cdfc082-6dc7-4e9d-8f77-c4250b9cd573
    InternalServerError:
      description: An error occurred. The response body is empty.
  securitySchemes:
    oauth2:
      type: oauth2
      flows:
        authorizationCode:
          authorizationUrl: https://oauth.loopreturns.com/authorize
          tokenUrl: https://oauth.loopreturns.com/oauth/token
          scopes:
            ship_by_loop:write: Submit services, orders, and errors for Ship by Loop shipments

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.