Skip to content

Create a shipment for a sales order

Open .md

POST/v2/api/store/{team_slug}/v2/sales_order/{unique_key}/shipment

v2Operation ID v2_public_sales_order_shipment_create

Creates an empty shipment for an order: one address, one shipping type. Add its lines with the shipment line operations afterwards.

The shipment takes the team's next shipment number, the starting shipment status, the customer's primary brand profile, and the team's default shipping type unless you send one.

Safe retries: send your own operation_key. Sending the same key with the same fields again returns the shipment already created instead of a second one.

The answer is the shipment. {unique_key} is the order's id (for example V4keXwwxMQyXw7) or its unique_key (ord_…).

Permission

Any member of the team.

Business rules

  • A published order needs a customer first: "Select a customer before creating a shipment."
  • The same operation_key with different fields is refused with 422 shipment_create_operation_payload_conflict. Reusing the key of a shipment that was deleted since is refused with 422 shipment_create_operation_removed.
  • Refused when the Shopify order was deleted in Shopify.

Side effects

  • Refreshes the order for people who have it open in the web app; on a published order, Customer Portal pages the customer has open refresh too.

Path parameters

  • team_slugstringrequired

    Your team slug, shown as Team ID next to your API key in Profile.

    • Example your-team
  • unique_keystringrequired

    The sales order's or quote's id (a hash id), or its unique_key (ord_…). The order number (scoped_id) does not work.

    • Example V4keXwwxMQyXw7

Request body

application/json, required.

  • Accepted but ignored: the shipment always belongs to the order's customer.

  • customer_profile_idstring | null

    Accepted but ignored: the shipment takes the customer's primary brand profile.

  • operation_keystring | null

    Your idempotency key for this create, up to 100 characters.

    • At most 100 characters
  • receiver_contact_idstring | null

    The contact who receives it.

  • scoped_idstring

    Your own shipment number, without the SHIP- the answer puts in front of it. Leave it out for the team's next number.

  • The address to ship to.

  • shipping_type_idstring | null

    A shipping type id. Leave it out for the team's default.

Response

200Successful response.

  • dataobjectrequired

    A shipment.

    Child fields (21)
    • idstringrequired
    • order_idstringrequired
    • status_idstringrequired
    • billable_fee_totaldecimal pair

      Shipping charged to the customer. A decimal pair: the amount is value ÷ 10^dp ({ "value": 125000, "dp": 4 } is 12.50). Kept with 4 decimal places; an amount never set can come as { "value": 0, "dp": 0 }. Read dp every time: it can differ between fields and records.

    • cost_totaldecimal pair

      Shipping cost. A decimal pair: the amount is value ÷ 10^dp ({ "value": 125000, "dp": 4 } is 12.50). Kept with 4 decimal places; an amount never set can come as { "value": 0, "dp": 0 }. Read dp every time: it can differ between fields and records.

    • customer_due_datestring (date-time) | null

      The order's in-hands date. ISO 8601 with offset, or null.

    • customer_idstring | null
    • delivery_notesstring | null
    • internal_notesstring | null
    • is_externalboolean | null

      null in this answer for a new shipment; read the shipment back (Get a shipment) for the stored value, false unless it was synced from an integration. A repeated create with the same operation_key answers the stored shipment, with false.

    • is_validboolean
    • itemsarray of objects

      Shipment lines (list only).

    • receiver_contact_idstring | null
    • scoped_idstring

      The shipment number.

    • shipment_estimatesarray of objects

      Shipping estimates (list only).

    • shipment_packagesarray of objects

      Packages (list only).

    • shipping_address_idstring | null
    • shipping_type_idstring | null
    • statusobject | null

      A status, as the status operations return it.

      Child fields (9)
      • colorstringrequired

        A hex color, such as #2196f3.

      • customer_labelstringrequired

        What customers see in the customer portal. When none is set: Pending for start, In Progress for in_progress and pre_production, Completed for end.

      • idstringrequired
      • labelstringrequired

        The status name people see.

      • positionintegerrequired

        Sort order within its list, lowest first.

      • rolestringrequired

        Which list the status belongs to: order, quote, job, shipment, purchase_order, pipeline or customer_message.

      • trashedbooleanrequired

        true for a deleted status.

      • typestringrequired

        start is the first status of its list and end the last; pre_production and in_progress are the ones in between.

        • One of: "start", "pre_production", "in_progress", "end"
      • The task preset, for pipeline statuses only; absent for other roles.

  • statusintegerrequired
  • successbooleanrequired

Errors

  • 401The API key is missing or wrong (unauthenticated).

  • 403You are not allowed to do this. api_access_not_in_plan: your team's plan doesn't include API access (Pro and above, with an active subscription or trial), so every request answers this until the team upgrades. When your role lacks the permission the operation needs, the body is only {"message": "Insufficient Permission"}. Other refusals use the error envelope, with unauthorized or user_is_not_authorized.

  • 404Not found. page_not_found: the team slug is unknown, you are not a member of the team, or an id in the path is not one of this team's. code: null, with a message that starts "No query results for": there is no record with that id.

  • 422The request was refused and changed nothing. validation_failed lists what to fix in error.fields; other codes name a business rule, explained in error.message. A few checks answer with only {"message": "..."}. An operation that calls another service (a payment provider, a carrier, an accounting app) can answer connect_timeout ("Please retry again") when that service does not answer in time: the change may or may not have happened there, so read the record back before you retry.

    When
    No customer on a published order ("Select a customer before creating a shipment."), or a bad id.
    Fix
    Set the order's customer first, or check the ids.
    When
    The operation_key was used before with other fields (shipment_create_operation_payload_conflict), or its shipment was deleted (shipment_create_operation_removed).
    Fix
    Resend the first request unchanged, or use a new key.