> For the complete documentation index, see [llms.txt](https://lmile.gitbook.io/lmile-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://lmile.gitbook.io/lmile-docs/fulfillment-api/fulfillment.md).

# Fulfillment — 出荷ステータス遷移・ラベル

[Routing](/lmile-docs/routing-api/orders.md) で各在庫ロケーションへ引き当てた後の、**引き当てロケーション（from-location）単位の進捗**を報告するエンドポイント。状態が **確保済（secured）** へ遷移した shipment については、注文の**出荷元（fulfillment source location）の `action: "label"` 設定（**[**Dispatch Config**](/lmile-docs/configuration/dispatch-config.md)**）を使ってラベルを生成**し、応答から**追跡番号**と**ラベル PDF** を取り込みます。

> **Base URL** `https://api.lmile.io` · **認証** `x-ingest-secret` ヘッダー または operator JWT（`Authorization: Bearer`）（[詳細](/lmile-docs/getting-started/authentication.md)） · `shop` はリクエストボディに含めます（API キーで呼ぶ場合は省略できます）

> `/api/routing/fulfillment` は機械間 secret（`x-ingest-secret`）と倉庫スタッフの operator JWT のどちらでも呼べます（系統はヘッダの有無で明示判別。[詳細](https://lmile.gitbook.io/lmile-docs/fulfillment-api/pages/7cB70I8yeRnMpvcdLkNu#routing-write-の-2-系統認証)）。operator JWT 経由は操作スタッフを記録します。

> 取り込んだラベル PDF は Supabase Storage に保存され、出荷元に `action: "print"` 設定（[Dispatch Config](https://lmile.gitbook.io/lmile-docs/fulfillment-api/pages/bGOYICmcj4SdTpefqrDg#actionprint-ラベル物理印刷)）があれば**生成直後に出荷元の print server へ自動印刷**されます（LM-605）。印刷の手動再実行は [Print Label](/lmile-docs/fulfillment-api/print-label.md)。

## ライフサイクル状態

`/api/routing/orders` で引き当て・dispatch されると、各出荷元は `allocated` で作成されます。以降の遷移を本 API で報告します。

| status                        | 業務上の意味                                                                                      |
| ----------------------------- | ------------------------------------------------------------------------------------------- |
| `unallocated`                 | 1: 未引当                                                                                      |
| `allocated`                   | 引当・出荷指示済 / 未確保（routing 直後の初期状態）                                                             |
| `secured`                     | 2: 確保済 → **ラベル生成トリガー**                                                                      |
| `oversell_pending`            | 売越発生中                                                                                       |
| `oversell_secured`            | 売越在庫確保済 → **ラベル生成トリガー**                                                                     |
| `oversell_returning`          | 売越返送中                                                                                       |
| `oversell_warehouse_received` | 売越商品倉庫受付完了                                                                                  |
| `in_transit_to_mfc`           | 3: 引当店舗から MFC センターへ移動中                                                                      |
| `packing`                     | 4: 梱包作業開始                                                                                   |
| `shipped`                     | 5: 出荷完了                                                                                     |
| `cancelled`                   | 注文取消による終端（[Cancel / Update](/lmile-docs/routing-api/cancel-update.md)。`shipped` は保護され遷移しない） |

> 注文全体の確保状況（**一部確保済み**を含む）は `public.lm_v_routing_order_fulfillment` で集計参照できます（`secured` / `partially_secured` / `allocated` / `shipped` / `cancelled`）。

## エンドポイント

| Method | Path                       | 用途                       |
| ------ | -------------------------- | ------------------------ |
| `POST` | `/api/routing/fulfillment` | 出荷元単位の状態遷移を報告（確保済でラベル生成） |

***

## `POST` /api/routing/fulfillment

### リクエスト

```http
POST https://api.lmile.io/api/routing/fulfillment
x-ingest-secret: {INGEST_SECRET}
Content-Type: application/json
```

```json
{
  "shop": "demo-store.myshopify.com",
  "sourceSystem": "shopify",
  "externalOrderRef": "1001",
  "shipments": [
    { "fromLocationId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "status": "secured" }
  ]
}
```

| パラメータ                               | 型             |  必須 | 説明                                                                                  |
| ----------------------------------- | ------------- | :-: | ----------------------------------------------------------------------------------- |
| `shop`                              | string        |  ✓  | 店舗ドメイン（API キーで呼ぶ場合は省略できます）                                                          |
| `routingOrderId`                    | string (uuid) |  △  | 対象注文。無ければ `sourceSystem` + `externalOrderRef` で特定                                   |
| `sourceSystem` / `externalOrderRef` | string        |  △  | `routingOrderId` 未指定時に必須                                                            |
| `tag`                               | string        |     | ラベル設定解決の tag 条件（省略時は注文 / 出荷指示の tag を使用）                                             |
| `shipments`                         | array         |  ✓  | 出荷元ごとの状態更新（1〜1000 件）                                                                |
| `shipments[].fromLocationId`        | string (uuid) |  ✓  | 対象の在庫ロケーション（引き当て先）                                                                  |
| `shipments[].status`                | string        |  ✓  | 上記ライフサイクル状態のいずれか                                                                    |
| `shipments[].targetMfcLocationId`   | string (uuid) |  △  | `status='in_transit_to_mfc'` のとき必須。移動先 MFC ロケーション（MFC でなければ `422`）。単位の現在在庫ロケーションを更新 |

### 挙動

* 各出荷元の状態を更新し、状態に応じたタイムスタンプ（`secured_at` / `in_transit_at` / `packing_started_at` / `shipped_at`）を記録します。
* `secured` / `oversell_secured` への**遷移時のみ**（既に確保系だった場合は再生成しない）、その location の `action: "label"` 設定でラベルを生成し、`tracking_number` / `carrier_code` / `label_pdf_path` を書き戻します。
* ラベル設定の無い location は `labelStatus: "skipped"` を返し、確保状態は維持します。
* ラベル生成に失敗しても確保状態は巻き戻しません（`last_label_error` に記録、`labelStatus: "failed"`）。
* ラベル生成成功時、出荷元の `action: "print"` 設定があれば PDF を出荷元の print server へ自動印刷します（`label_printed_at` を記録）。印刷失敗してもラベル生成・確保は維持され `last_print_error` に記録します（`printStatus: "failed"`）。`print` 設定の無い出荷元は `printStatus: "skipped"`。
* ヘッダの状態は配下の**単位**（[Units](/lmile-docs/fulfillment-api/units.md)）へ cascade します。`in_transit_to_mfc` のときは `targetMfcLocationId` を**単位の現在在庫ロケーション**（`current_inventory_location_id`）に設定します（引当店舗→MFC 移動を状態で表現。在庫数量 `inventory_levels` は変更しません）。
* **在庫確保**（status 2）は単位ごとに行う [`/api/routing/secure`](/lmile-docs/fulfillment-api/units.md) が主経路です。本 API に `secured` を直接送った場合もヘッダ + 単位へ反映します。
* status が遷移した shipment は [Fulfillment Status Webhook](/lmile-docs/webhooks/fulfillment-status.md) で外部へ通知されます（設定時のみ）。
* operator JWT で呼んだ場合、報告した出荷元ヘッダに操作スタッフ（検証済の `auth.users.id`）を記録します。`x-ingest-secret`（機械間）経由の挙動は不変です。

### レスポンス

```json
{
  "ok": true,
  "routingOrderId": "0f1e2d3c-4b5a-6789-0abc-def123456789",
  "shipments": [
    {
      "fromLocationId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "status": "secured",
      "trackingNumber": "1234-5678-9012",
      "labelPdfPath": "demo-store.myshopify.com/0f1e2d3c-.../a1b2c3d4-....pdf",
      "labelStatus": "generated",
      "printStatus": "printed"
    }
  ]
}
```

| フィールド          | 説明                                                                                                              |
| -------------- | --------------------------------------------------------------------------------------------------------------- |
| `labelStatus`  | `generated`（生成・保存済）/ `skipped`（label 設定なし or 明細未解決）/ `failed`（生成失敗）/ `none`（ラベル非対象の状態）                          |
| `printStatus`  | `printed`（出荷元 print server へ送信成功）/ `skipped`（print 設定なし）/ `failed`（印刷失敗。`last_print_error` に記録）/ `none`（ラベル未生成） |
| `labelPdfPath` | Supabase Storage `shipping-labels` バケット内のパス                                                                     |

***

## エラー

エンドポイント固有:

| Status | 条件                                                                                                                                         | レスポンス例                                                                                                                      |
| :----: | ------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------- |
|  `400` | 注文特定情報なし / status 不正 / `in_transit_to_mfc` で `targetMfcLocationId` 欠落                                                                      | `{ "ok": false, "error": "invalid_input" }`                                                                                 |
|  `422` | `targetMfcLocationId` が MFC ロケーションでない                                                                                                      | `{ "ok": false, "error_kind": "not_an_mfc_location", "error": "targetMfcLocationId is not an MFC location for this shop" }` |
|  `404` | 注文が存在しない                                                                                                                                   | `{ "ok": false, "error_kind": "order_not_found", "error": "routing order not found" }`                                      |
|  `409` | `shipped` 報告のヘッダに出荷可能な unit が無く、注文配下に[倉庫間移動](/lmile-docs/transfer-api/batches.md)（出荷元変更）フロー中の unit がある（刻印の倉庫返送等。旧ヘッダの顧客向けラベルで出荷完了しようとした場合） | `{ "ok": false, "error_kind": "transfer_required", "units": [...] }`                                                        |

共通エラー（`401` / `400` / `403` / `405` / `500` / `503`）は [Error Codes](/lmile-docs/reference/error-codes.md) を参照。

## データモデル

* `sot.lm_fulfillment_shipments` — 出荷元（`UNIQUE shop + routing_order_id + from_location_id`）単位の状態 + 追跡番号 + ラベル PDF パス + 印刷結果（`label_printed_at` / `last_print_error`）+ 各遷移タイムスタンプ。読み取り view: `public.lm_v_fulfillment_shipments`
* `public.lm_v_routing_order_fulfillment` — 注文単位の確保状況集計（`secured` / `partially_secured` / `allocated` / `shipped` / `cancelled`。`cancelled_count` 列あり）
* `sot.lm_location_dispatch_config.action = 'label'` + `response_mapping` — ラベル送信先と応答マッピング、`action = 'print'` — 出荷元 print server（[Dispatch Config](/lmile-docs/configuration/dispatch-config.md)）
* Supabase Storage `shipping-labels`（private バケット）— ラベル PDF 本体


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://lmile.gitbook.io/lmile-docs/fulfillment-api/fulfillment.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
