# Fulfillment (/ai/reference/orders/fulfillment)

Toolset `fulfillment`, 10 tools.

## Records [#records]

### `label_run` [#label_run]

A batch that books carrier parcels and prints labels for a set of orders, with each order's outcome (booked, reused, skipped, blocked, failed). Runs are kept for 7 days, newest first.

- Permission: `orders.read`
- Tools: `label_run_list`, `label_run_get`

Filters on the list:

| Filter | Type | Required | Description |
| --- | --- | --- | --- |
| `today` | boolean |  | Only the runs of the store's today |

### `label_settings` [#label_settings]

How labels print by default (format, packing slips, pick list) and when an order turns shipped. There is one record; pass any id, e.g. "current".

- Permission: `orders.read`
- Tools: `label_settings_get`

## Actions [#actions]

### `fulfillment_cancel` [#fulfillment_cancel]

Cancel a fulfillment that has not shipped; its items return to stock.

- Action key: `fulfillment.cancel`
- Permission: `orders.write`
- Approval: Always waits for a person to approve it.
- Effect: Changes the live store.
- Destructive: in compact mode it runs with `run_destructive_action`.
- Retries: runs at most once; a repeat with the same idempotency key returns the first result.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `order_id` | string | yes | Order ID (order_…), not the display number |
| `fulfillment_id` | string | yes | Fulfillment ID from order_get with include fulfillments |
| `notify_customer` | boolean |  | Whether the customer gets the email; defaults to the store setting |

Example input:

```json
{
  "order_id": "019bb3ef-6501-7dc3-a2e7-726e91520b7a",
  "fulfillment_id": "019bb2c1-7e7c-780c-856c-88686b112a4d"
}
```

### `fulfillment_mark_delivered` [#fulfillment_mark_delivered]

Record that a fulfillment reached the customer.

- Action key: `fulfillment.mark_delivered`
- Permission: `orders.write`
- Approval: Waits for approval when the store requires it for this action.
- Effect: Changes the live store.
- Retries: safe to repeat with the same input.
- Sends something to customers.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `order_id` | string | yes | Order ID (order_…), not the display number |
| `fulfillment_id` | string | yes | Fulfillment ID from order_get with include fulfillments |
| `notify_customer` | boolean |  | Whether the customer gets the email; defaults to the store setting |

Example input:

```json
{
  "order_id": "019bb3ef-6501-7dc3-a2e7-726e91520b7a",
  "fulfillment_id": "019bb2c1-7e7c-780c-856c-88686b112a4d"
}
```

### `fulfillment_ship` [#fulfillment_ship]

Record that a fulfillment left, with its tracking numbers.

Omit items to ship everything in the fulfillment. Carrier apps mark their own parcels shipped as the label settings say; use this for parcels sent outside them.

- Action key: `fulfillment.ship`
- Permission: `orders.write`
- Approval: Waits for approval when the store requires it for this action.
- Effect: Changes the live store.
- Retries: runs at most once; a repeat with the same idempotency key returns the first result.
- Sends something to customers.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `order_id` | string | yes | Order ID (order_…), not the display number |
| `fulfillment_id` | string | yes | Fulfillment ID from order_get with include fulfillments |
| `items` | list of object |  | at least 1 items |
| `items[].id` | string | yes | Order line item ID |
| `items[].quantity` | integer | yes | above 0 |
| `labels` | list of object |  |  |
| `labels[].tracking_number` | string | yes |  |
| `labels[].tracking_url` | string | yes | format uri |
| `labels[].label_url` | string | yes | format uri |
| `notify_customer` | boolean |  | Whether the customer gets the email; defaults to the store setting |

Example input:

```json
{
  "order_id": "019bb3ef-6501-7dc3-a2e7-726e91520b7a",
  "fulfillment_id": "019bb2c1-7e7c-780c-856c-88686b112a4d",
  "labels": [
    {
      "tracking_number": "00340434",
      "tracking_url": "https://track.example/00340434",
      "label_url": "https://track.example/00340434.pdf"
    }
  ]
}
```

### `label_run_create` [#label_run_create]

Book parcels with each order's carrier app and print their labels, packing slips and pick list.

Carriers are not chosen here: every order goes to the carrier app that owns its shipping method, and orders without one are skipped. An order that already has a label is reprinted, not booked again. A dry run counts the orders per carrier and what the pick list would hold, and books nothing. The run works in the background; follow it with label_run_get.

- Action key: `label_run.create`
- Permission: `orders.write`
- Approval: Always waits for a person to approve it.
- Effect: Changes the live store.
- Retries: runs at most once; a repeat with the same idempotency key returns the first result.
- Dry run: supported, with `dry_run` set to true.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `order_ids` | list of string | yes | Order IDs (order_…); each order is booked with the carrier app of its shipping method. 1 to 200 items |
| `format` | string |  | Defaults to the label settings. one of "label_printer", "a4" |
| `start_slot` | integer |  | 1 to 4 |
| `packing_slips` | boolean |  |  |
| `full_slip` | boolean |  |  |
| `pick_list` | string |  | one of "off", "same_pdf", "separate_pdf" |
| `reprint_only` | boolean |  | Only reprint labels that exist; book nothing |

Example input:

```json
{
  "order_ids": [
    "019bb3ef-6501-7dc3-a2e7-726e91520b7a",
    "019bb3ed-0ffa-704d-bcb2-11c42a2a5600"
  ]
}
```

### `label_run_retry` [#label_run_retry]

Start a new run of the orders a label run could not print, with the same choices.

Orders whose booking may have reached the carrier unrecorded are never booked again; check them from the order (include parcels).

- Action key: `label_run.retry`
- Permission: `orders.write`
- Approval: Always waits for a person to approve it.
- Effect: Changes the live store.
- Retries: runs at most once; a repeat with the same idempotency key returns the first result.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `label_run_id` | string | yes |  |

Example input:

```json
{
  "label_run_id": "019bb36b-d42c-7ea1-8b73-c0b3228ab5d2"
}
```

### `label_settings_update` [#label_settings_update]

Change the label printing defaults and when orders turn shipped.

mark_shipped: picked_up turns an order shipped at the carrier first scan, label_ready as soon as its label exists, manual only when someone marks it. Only the fields passed change.

- Action key: `label_settings.update`
- Permission: `orders.write`
- Approval: Waits for approval when the store requires it for this action.
- Effect: Changes the live store.
- Retries: safe to repeat with the same input.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `format` | string |  | one of "label_printer", "a4" |
| `packing_slips` | boolean |  |  |
| `slip_prices` | boolean |  |  |
| `full_slip` | boolean |  |  |
| `pick_list` | string |  | one of "off", "same_pdf", "separate_pdf" |
| `pick_list_images` | boolean |  |  |
| `mark_shipped` | string |  | one of "picked_up", "label_ready", "manual" |

Example input:

```json
{
  "format": "label_printer",
  "packing_slips": true
}
```

### `order_fulfill` [#order_fulfill]

Create a fulfillment for order lines, taking them from a stock location.

For carrier parcels and labels use label_run_create instead: it books the parcel with the carrier app and fulfills the order in one go.

- Action key: `order.fulfill`
- Permission: `orders.write`
- Approval: Waits for approval when the store requires it for this action.
- Effect: Changes the live store.
- Retries: runs at most once; a repeat with the same idempotency key returns the first result.
- Sends something to customers.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `order_id` | string | yes | Order ID (order_…), not the display number |
| `items` | list of object | yes | at least 1 items |
| `items[].id` | string | yes | Order line item ID |
| `items[].quantity` | integer | yes | above 0 |
| `location_id` | string |  | Stock location the items leave from |
| `shipping_option_id` | string |  |  |
| `notify_customer` | boolean |  | Whether the customer gets the email; defaults to the store setting |

Example input:

```json
{
  "order_id": "019bb3ef-6501-7dc3-a2e7-726e91520b7a",
  "items": [
    {
      "id": "019bb496-a0e1-70c9-a373-1b205a23af28",
      "quantity": 1
    }
  ]
}
```
