> 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/units.md).

# Units — 単位ステータス・在庫確保

[Fulfillment](/lmile-docs/fulfillment-api/fulfillment.md) の出荷元（from-location）ヘッダの下に、**1 行 = 1 販売単位**（`order_line_master` 方式・数量列なし）の明細を持ち、単位ごとの状態と **3 つのロケーション概念**（引当 / 出荷元 / 現在在庫）を管理します。**在庫確保**（`POST /api/routing/secure`）はこの明細を `secured` にし、その出荷元ヘッダの全単位が確保済になった時点でヘッダを `secured` に遷移させ、[Fulfillment](/lmile-docs/fulfillment-api/fulfillment.md) と同じ経路でラベルを生成します。

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

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

> 在庫確保・店舗→MFC 移動は **状態のみ**を更新し、`sot.inventory_levels`（在庫数量）は変更しません（在庫真実は取込側が所有）。Shopify の fulfillment order id には依存しません（注文は `routingOrderId` か `sourceSystem`+`externalOrderRef`、単位は `barcode`+`lineInstanceNo` で特定）。

## 単位と 3 ロケーション

| 概念         | カラム                              | 意味                                                     |
| ---------- | -------------------------------- | ------------------------------------------------------ |
| 引当ロケーション   | `allocated_location_id`          | ルーティングで引き当てた在庫ロケーション（店舗等。不変）                           |
| 出荷元        | `fulfillment_source_location_id` | 指定された出荷元（fulfillment source。不変）                        |
| 現在在庫ロケーション | `current_inventory_location_id`  | 在庫が物理的にある場所。初期＝引当、status `in_transit_to_mfc` で MFC へ更新 |

単位の `status` はヘッダ（[Fulfillment](/lmile-docs/fulfillment-api/fulfillment.md)）と同じ値（`unallocated` / `allocated` / `secured` / `oversell_*` / `in_transit_to_mfc` / `packing` / `shipped` / `source_change_*` / `cancelled`）。`secured`（在庫確保フラグ）は別途 boolean 列で保持します。`cancelled` は注文取消（[Cancel / Update](/lmile-docs/routing-api/cancel-update.md)）による終端で、`shipped` は保護され遷移しません。

## エンドポイント

| Method | Path                  | 用途                             |
| ------ | --------------------- | ------------------------------ |
| `POST` | `/api/routing/secure` | 単位ごとに在庫確保（全確保でヘッダ→確保済 + ラベル生成） |

> 単位は `/api/routing/orders`・`/api/routing/update` の引き当て確定時に decision から自動生成されます（`status='allocated'`）。store→MFC 移動・梱包・出荷完了（status 3/4/5）は [Fulfillment](/lmile-docs/fulfillment-api/fulfillment.md) の `/api/routing/fulfillment` で報告し、単位へ cascade されます。

***

## `POST` /api/routing/secure

注文内の単位を在庫確保（`status='secured'` + `secured=true`）します。`units[]` で対象を絞り込めます（省略時は `allocated` の全単位）。同一出荷元ヘッダの全単位が確保済になると、ヘッダが `secured` に遷移し**ラベルを生成**します（[Fulfillment](/lmile-docs/fulfillment-api/fulfillment.md) と同じトリガ）。

### リクエスト

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

```json
{
  "shop": "demo-store.myshopify.com",
  "sourceSystem": "shopify",
  "externalOrderRef": "1001",
  "units": [
    { "barcode": "1234567890123", "lineInstanceNo": 1 }
  ]
}
```

### ボディパラメータ

| パラメータ                               | 型             |  必須 | 説明                                                     |
| ----------------------------------- | ------------- | :-: | ------------------------------------------------------ |
| `shop`                              | string        |  ✓  | 店舗ドメイン（API キーで呼ぶ場合は省略できます）                             |
| `routingOrderId`                    | string (uuid) |  △  | 対象注文。無ければ `sourceSystem` + `externalOrderRef` で特定      |
| `sourceSystem` / `externalOrderRef` | string        |  △  | `routingOrderId` 未指定時に必須                               |
| `tag`                               | string        |     | ラベル設定解決の tag 条件（省略時は注文の tag）                           |
| `units`                             | array         |     | 確保対象の絞り込み（省略 = `allocated` の全単位）                       |
| `units[].barcode`                   | string        |     | barcode で絞り込み                                          |
| `units[].lineInstanceNo`            | number        |     | 販売単位番号で絞り込み                                            |
| `units[].allocatedLocationId`       | string (uuid) |     | 引当ロケーションで絞り込み                                          |
| `suppressCustomerMail`              | boolean       |     | `true` にすると、この確保ではお届け状況メールの「在庫確保」を送りません。省略時は店舗の通知設定どおり |

### レスポンス

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

| フィールド                    | 説明                                                                                                                  |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------- |
| `secured`                | 今回確保した単位数                                                                                                           |
| `alreadySecured`         | 既に確保済だった単位数（再 POST 時など）                                                                                             |
| `customerMailSuppressed` | `suppressCustomerMail: true` を受け付けたか                                                                                |
| `headers[]`              | 全単位確保によりヘッダが `secured` 遷移した出荷元（ラベル結果付き）                                                                             |
| `labelStatus`            | `generated` / `skipped`（label 設定なし or 明細未解決）/ `failed` / `none`                                                     |
| `orderFulfillmentStatus` | 単位粒度の注文集計（`allocated` / `partially_secured` / `secured` / `shipped` / `oversell` / `source_changing` / `cancelled`） |

### 挙動・冪等性

* 対象は `allocated` / `unallocated` の単位のみ。既に `secured` の単位は再確保せず `alreadySecured` に計上（再 POST は no-op、ラベル再生成なし）。
* 在庫確保は **状態のみ**（`secured` フラグ + `secured_at`）。`inventory_levels` は変更しません。
* `suppressCustomerMail: true` で送ると、この注文の「在庫確保」のお届け状況メールを送りません。止まるのはその段だけで、出荷準備・発送完了などのメールは店舗の通知設定どおり送られます。確保する単位が無い再送では何もしません。
* ヘッダの全単位が確保済になった時のみヘッダを `secured` に遷移しラベル生成（[Fulfillment](/lmile-docs/fulfillment-api/fulfillment.md) のラベルトリガと同一）。ラベル失敗でも確保は巻き戻しません（`last_label_error` 記録）。
* 一部の単位だけ確保した場合、注文集計は `partially_secured`（`public.lm_v_routing_order_unit_fulfillment`）。
* [倉庫間移動](/lmile-docs/transfer-api/batches.md)（出荷元変更）フロー中（`source_change_pending` / `source_change_in_transit`）の単位は確保できません。フィルタが移動中の単位だけに当たった場合は `409 transfer_required`、確保可能な単位と混在する場合は確保を行いつつレスポンスの `transferRequiredUnits[]`（unit id）で表面化します（黙って通しません）。

## エラー

エンドポイント固有:

| Status | 条件                                                           | レスポンス例                                                                                 |
| :----: | ------------------------------------------------------------ | -------------------------------------------------------------------------------------- |
|  `400` | 注文特定情報なし                                                     | `{ "ok": false, "error": "invalid_input" }`                                            |
|  `404` | 注文が存在しない                                                     | `{ "ok": false, "error_kind": "order_not_found", "error": "routing order not found" }` |
|  `409` | フィルタ対象が[倉庫間移動](/lmile-docs/transfer-api/batches.md)フロー中の単位のみ | `{ "ok": false, "error_kind": "transfer_required", "units": [...] }`                   |

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

## データモデル

* `sot.lm_fulfillment_units` — 1 行 = 1 単位（`UNIQUE shop + routing_order_id + line_instance_no + barcode`）。`barcode` / `sku` / `line_properties`（明細単位の任意キー/値 = [Routing](/lmile-docs/routing-api/orders.md) の `lines[].properties`。decision から引き継ぎ、`agent_read` 非公開）/ `allocated_location_id` / `fulfillment_source_location_id` / `current_inventory_location_id` / `status` / `secured` + 遷移タイムスタンプ（`cancelled_at` 含む）。ヘッダ `lm_fulfillment_shipments` と decision `lm_routing_decisions` にリンク。読み取り view: `public.lm_v_fulfillment_units`
* `public.lm_v_routing_order_unit_fulfillment` — 単位粒度の注文集計（`allocated` / `partially_secured` / `secured` / `oversell` / `source_changing` / `shipped` / `cancelled`。`cancelled_unit_count` 列あり）
* 追跡番号・ラベル PDF は梱包単位＝出荷元ヘッダ `sot.lm_fulfillment_shipments` に保持（単位には重複させない）


---

# 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/units.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.
