Fulfill a fulfillment order

Updated May 29, 20262 min read

Fulfilling an FO records that its items have been picked and packed and are leaving (or have left) the location. You can optionally have Carriyo create a shipment in the same call.

Scenario

A fulfillment order at the New Jersey warehouse holds two lines: a keyboard and a monitor. The warehouse has picked and packed both. Ops marks the FO fulfilled and asks Carriyo to create a draft shipment, so it can be reviewed before booking with a carrier.

Prerequisites

Starting state

Order OMP7782ABCDEF, fulfillment order FOMP7782NJ001 at NJ-WH-01, in allocated, carrying:

  • Keyboard, line item id line-kbd, quantity 1
  • Monitor, line item id line-mon, quantity 1

Fulfill the FO

curl -X POST \
  'https://api.carriyo.com/orders/OMP7782ABCDEF/fulfillment-orders/FOMP7782NJ001/fulfill?create_draft_shipment=true' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
  -H 'tenant-id: YOUR_TENANT_ID' \
  -H 'x-api-key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "partner_fulfillment_reference": "NJ-FUL-2026-05-12-0042",
    "line_items": [
      { "id": "line-kbd", "quantity": 1 },
      { "id": "line-mon", "quantity": 1 }
    ]
  }'
  • line_items names the lines (and quantities) being fulfilled, referenced by the order line item id. Each must be open or allocated.
  • partner_fulfillment_reference is your warehouse's reference for this fulfillment, recorded against each fulfilled line.

Two query parameters control what happens to shipping:

  • create_draft_shipment=true (used here): create a draft shipment alongside the fulfillment, for review before you book it with a carrier. See Draft then confirm.
  • skip_shipping=true: fulfill without creating any shipment. Useful for digital goods or in-store collection.

Omit both to fulfill and book a shipment with a carrier in one step. Booking is asynchronous: the shipment is submitted to the carrier and comes back pending, resolving to booked (or error) later via webhook. See Book a shipment.

Read the response

The FO transitions to fulfilled, and each line carries a fulfillment_id:

{
  "order_id": "OMP7782ABCDEF",
  "status": "fulfilled",
  "fulfillment_orders": [
    {
      "fulfillment_order_id": "FOMP7782NJ001",
      "location_id": "NJ-WH-01",
      "status": "fulfilled",
      "line_items": [
        {
          "id": "line-kbd",
          "quantity": 1,
          "status": "fulfilled",
          "fulfillment_id": "FUL-1B9C8D3E-001",
          "partner_fulfillment_reference": "NJ-FUL-2026-05-12-0042"
        },
        {
          "id": "line-mon",
          "quantity": 1,
          "status": "fulfilled",
          "fulfillment_id": "FUL-1B9C8D3E-001",
          "partner_fulfillment_reference": "NJ-FUL-2026-05-12-0042"
        }
      ]
    }
  ]
}

The order moves to fulfilled once all its lines reach a terminal state with at least one fulfilled. It moves on to closed when the resulting shipment(s) are delivered.

Partial fulfillment

Fulfill a subset by sending only the relevant lines (or a smaller quantity). The remaining lines stay in allocated and the FO stays in processing until the rest are fulfilled or cancelled.

Pitfalls

  • Lines must be open or allocated. Only those can be fulfilled; already-fulfilled or cancelled lines are rejected.
  • id is the order line-item id. The line_items[].id is the order line item id, not a SKU.
  • Draft vs booked. With create_draft_shipment=true the shipment is created as a draft and is not booked with the carrier until you confirm it.