# Fulfill orders

> Ship a paid Shoplazza order from your app: create a fulfillment, complete or cancel it, and write carrier tracking information back with the Open API.

Once an order is paid, ship it: create a fulfillment, mark it complete, or cancel it.

## When to use this

Integrating a warehouse or carrier, and writing tracking info back to Shoplazza.

## Prerequisites

- A working public app with OAuth and token storage — follow [Develop a standalone app](/docs/app/getting-started/create-public-app/develop-app) first. Every request below carries an `Access-Token: {token}` header, using the token you saved for each shop.
- The order access scope granted during OAuth.
- The order is paid — react to the `orders/paid` webhook (see [Listen for order events](/docs/app/use-cases/orders-and-fulfillment/listen-for-order-events)).

### Create a fulfillment

Fulfill the whole order by shipping every line item. `ship_quantity: 0` ships all remaining quantity of that item. `tracking_number` and `tracking_company` are optional.

`POST /openapi/2026-01/orders/{id}/fulfillments`

Request body:

```json5
{
  "fulfillment": {
    "line_items": [
      { "id": "cb43fba8-2e19-4add-aa70-5d0a81c6f746", "ship_quantity": 0 } // 0 = ship all remaining quantity of this item
    ],
    "tracking_number": "1Z999AA10123456784", // optional
    "tracking_company": "UPS" // optional
  }
}
```

Response (excerpt, fulfillment under `data.data.fulfillment`):

```json
{
  "code": "Success",
  "data": {
    "fulfillment": {
      "id": "92db3f11-39ca-4253-8b26-6e2408e5ea21",
      "order_id": "2386979206088637521556",
      "status": "shipped",
      "created_at": "2026-07-02T03:05:00Z",
      "updated_at": "2026-07-02T03:05:00Z",
      "line_items": [
        {
          "id": "cb43fba8-2e19-4add-aa70-5d0a81c6f746",
          "product_title": "Hoodie",
          "variant_id": "fbb31d0c-0809-4394-87df-b5be865b30a7",
          "quantity": 1,
          "price": "83.22",
          "sku": "A002020",
          "fulfillment_status": "shipped",
          "ship_quantity": 1
        }
      ]
    }
  }
}
```

Full request body (partial shipments, tracking fields) is in [Create fulfillment](/api/fulfillment-create).

### Complete or cancel a fulfillment

Both take the `fulfillment_id` returned by create (or from [List fulfillments](/api/fulfillments)).

`POST /openapi/2026-01/orders/{id}/fulfillments/{fulfillment_id}/complete`

Response (excerpt, same fulfillment shape, `status` turns `finished`):

```json
{
  "code": "Success",
  "data": {
    "fulfillment": {
      "id": "92db3f11-39ca-4253-8b26-6e2408e5ea21",
      "order_id": "2386979206088637521556",
      "status": "finished",
      "updated_at": "2026-07-02T03:15:18Z"
    }
  }
}
```

Full fields: see [Complete fulfillment](/api/fulfillment-complete).

`POST /openapi/2026-01/orders/{id}/fulfillments/{fulfillment_id}/cancel`

Returns the same fulfillment, with `status` turned to its cancelled state. See [Cancel fulfillment](/api/fulfillment-cancel).

## Next steps

- [Refunds and post-sales](/docs/app/use-cases/orders-and-fulfillment/refunds-and-post-sales)
- [Listen for order events](/docs/app/use-cases/orders-and-fulfillment/listen-for-order-events)
