> 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/operator-api/secure-by-tracking.md).

# Secure by Tracking — 追跡番号で確保

店舗スタッフが**先行印刷された配送ラベルの追跡番号**をスキャンして、その shipment（出荷元単位の梱包）配下の確保可能ユニットを一括確保する API です。案 A（MFC 配送ラベル先行印刷）では、ラベルが `allocated` 段階で先行生成されるため、スタッフは「先行印刷ラベルの追跡番号をスキャン → 棚番号が表示される → 棚で商品を取りラベルを貼付 → 確保」という動線になり、本 API はその「確保」ステップを担います。追跡番号から shipment を解決し、配下の `status=allocated` ユニットを全件確保します。確保で出荷元の全ユニットが確保済になると shipment ヘッダを `secured` に遷移させます（先行生成済みラベルは再生成しません）。

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

> **ユニットQR で 1 件ずつ確保する** [Secure Scan](/lmile-docs/operator-api/secure-scan.md)（`/api/operator/secure-scan`）との違い: Secure Scan はユニットQR（`<barcode>\|<shipmentId>`）から「`status=allocated` かつ 未 picked」を 1 ユニットずつ確保します。本 API は配送ラベルの**追跡番号**（shipment 単位）を解決キーにして、その shipment 配下の確保可能ユニットを**一括**確保します。案 A では「ピック（棚スキャン）→ ラベル貼付 → 確保」の順のため、確保時点でユニットが既に picked のことがあり、本 API は **picked 済も含めて確保**します（1 ラベル = 1 shipment の確保確定）。確保前の「追跡番号 → 棚表示」は [`GET /api/operator/shipments/by-tracking`](/lmile-docs/operator-api/lookup.md)（棚番号付き）を使います。

## エンドポイント

| Method | Path                               | 用途                                                                  | テーブル                                                                                                                          |
| ------ | ---------------------------------- | ------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| `POST` | `/api/operator/secure-by-tracking` | 追跡番号 → shipment 配下の `status=allocated` ユニットを一括確保（全確保でヘッダ `secured`） | `lm_fulfillment_units` / `lm_fulfillment_shipments` / `lm_routing_orders` / `lm_shipping_instructions` / `lm_shelf_inventory` |

***

## `POST` /api/operator/secure-by-tracking

追跡番号から shipment（同一追跡番号が複数 shipment に当たりうるため全件）を解決し、各 shipment 配下の `status=allocated` ユニットを確保（`status=secured` + `secured=true`）します。確保で shipment 配下の全ユニットが確保済になると、ヘッダを `secured` に遷移させます（先行生成済みラベルは再生成しません）。各 shipment について、ユニットの引き当て先 × barcode から解決した棚番号（`shelves[]`）と確保結果を返します。

### リクエスト

```http
POST https://api.lmile.io/api/operator/secure-by-tracking
Authorization: Bearer {OPERATOR_JWT}
Content-Type: application/json
```

```json
{
  "shop": "demo-store.myshopify.com",
  "trackingNumber": "499999999999"
}
```

### ボディパラメータ

| パラメータ            | 型      |  必須 | 説明                         |
| ---------------- | ------ | :-: | -------------------------- |
| `shop`           | string |  ✓  | 店舗ドメイン（API キーで呼ぶ場合は省略できます） |
| `trackingNumber` | string |  ✓  | 配送ラベルの追跡番号（最大 100 文字）      |

### レスポンス

```json
{
  "ok": true,
  "trackingNumber": "499999999999",
  "secured": 2,
  "alreadySecured": 0,
  "shipments": [
    {
      "shipmentId": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
      "routingOrderId": "7b1f08a3-1234-4abc-9def-0123456789ab",
      "secured": 2,
      "alreadySecured": 0,
      "shelves": [
        { "barcode": "4912345678901", "lineInstanceNo": 1, "shelfCode": "A-01-01" },
        { "barcode": "4912345678901", "lineInstanceNo": 2, "shelfCode": "A-01-01" }
      ],
      "header": {
        "fromLocationId": "b2c3d4e5-f6a7-8901-bcde-f23456789012",
        "status": "secured",
        "trackingNumber": "499999999999",
        "labelPdfPath": "labels/demo-store.myshopify.com/....pdf",
        "labelStatus": "generated"
      },
      "orderFulfillmentStatus": "secured"
    }
  ]
}
```

| フィールド                                     | 説明                                                                                                                                                                                                                                                                                                                        |
| ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `trackingNumber`                          | 解決に使った追跡番号                                                                                                                                                                                                                                                                                                                |
| `secured`                                 | 今回確保したユニット数（全 shipment 合計）                                                                                                                                                                                                                                                                                                |
| `alreadySecured`                          | 確保可能ユニットが無く既確保だったユニット数（全 shipment 合計）                                                                                                                                                                                                                                                                                     |
| `shipments[]`                             | 該当 shipment ごとの結果（追跡番号で解決した shipment 全件）                                                                                                                                                                                                                                                                                  |
| `shipments[].secured` / `.alreadySecured` | 当該 shipment で確保したユニット数 / 既確保だったユニット数                                                                                                                                                                                                                                                                                      |
| `shipments[].shelves[]`                   | 当該 shipment 配下ユニットの棚番号（`barcode` / `lineInstanceNo` / `shelfCode`）。棚未管理は `shelfCode: null`                                                                                                                                                                                                                                |
| `shipments[].header`                      | 出荷元ヘッダの結果（`fromLocationId` / `status` / `trackingNumber` / `labelPdfPath` / `labelStatus`）。全ユニット確保で `secured` 遷移（`status`）。案 A（MFC 先行印刷）では確保時点で既にラベルがあり、再生成せず `secured` 遷移のみのため `labelStatus: "generated"`（先行ラベルの追跡番号 / PDF を据え置き）。既確保のみの冪等応答では `labelStatus: "none"`。まだ未確保ユニットが残る場合はヘッダ未遷移（`secureHeaderIfComplete` の結果） |
| `shipments[].orderFulfillmentStatus`      | 注文全体の集約状態（`allocated` / `partially_secured` / `secured` / `oversell` / `shipped`）                                                                                                                                                                                                                                         |

### 棚番号（shelves）

各ユニットの引き当て先（`allocated_location_id`）× `barcode` から、[Shelf Lookup](/lmile-docs/shelf-api/lookup.md) / [Secure Scan](/lmile-docs/operator-api/secure-scan.md) と同一規則で棚を解決します（同一 `(location, barcode)` で `qty>0` 優先・同点は `shelf_code` 昇順の 1 棚）。`(location|barcode)` 単位でキャッシュして重複解決を避けます。棚を持たない店舗 / 同期拠点のユニットは `shelfCode: null` です。確保前の「追跡番号 → 棚表示」は [`GET /api/operator/shipments/by-tracking`](/lmile-docs/operator-api/lookup.md)（`shelfCode` 付き）でも引けます。

### 挙動・冪等性

* **解決キー**: `trackingNumber`（`sot.lm_fulfillment_shipments.tracking_number`、shipment 単位）。同一追跡番号が複数 shipment（別注文 / 再発行）に当たりうるため、該当 shipment を全件処理します。0 件は `404 shipment_not_found` で表面化します（silent skip しません）。
* **確保対象**: 各 shipment 配下の `status=allocated` ユニットを全件確保します。案 A は pick→secure の順のため **picked 済（`picked_at` セット）も含めて確保**します（Secure Scan の「未 picked のみ」と異なります）。
* **ヘッダ遷移**: 確保で shipment 配下の全ユニットが確保済になると、ヘッダを `secured` に遷移させます。案 A（MFC 先行印刷）では確保時点で既にラベルがあるため、再生成せず `secured` 遷移のみを行い、先行ラベルの追跡番号 / PDF を据え置きます（`labelStatus: "generated"`）。
* **冪等**: 確保対象（`allocated`）が無く既確保ユニットが居る再スキャンは `200` + 当該 shipment の `secured: 0` / `alreadySecured: N`（二重確保しません）。
* **operator 記録**: operator JWT 経由の確保は `secured_by_staff_user_id` に操作者（`auth.users.id`）を記録します。
* 確保可能でも既確保でもないユニット（取消済 / 売越しのみ等）しか無い shipment は `409 unit_not_securable` で表面化します（`unitStatuses[]` に現状を同梱・fallback しません）。

## エラー

エンドポイント固有:

| Status | 条件                                                                                                    | レスポンス例                                                                                                                                  |
| :----: | ----------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
|  `404` | 追跡番号に該当 shipment なし                                                                                   | `{ "ok": false, "error_kind": "shipment_not_found", "error": "shipment not found for tracking number" }`                                |
|  `409` | 確保可能なユニットが無い（取消済 / 売越しのみ等。`unitStatuses[]` に現状を同梱）                                                    | `{ "ok": false, "error_kind": "unit_not_securable", "error": "no securable unit (status=allocated) for tracking ... in shipment ..." }` |
|  `409` | shipment 内が[倉庫間移動](/lmile-docs/transfer-api/batches.md)（出荷元変更）フロー中のユニットのみ（行き先 / バルク所属を `units[]` に同梱） | `{ "ok": false, "error_kind": "transfer_required", "units": [...] }`                                                                    |
|  `500` | shipment が指す注文の欠落（データ異常）                                                                              | `{ "ok": false, "error_kind": "data_inconsistency", "error": "routing_order not found for shipment ..." }`                              |

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

## データモデル

* `sot.lm_fulfillment_units` — [Units](/lmile-docs/fulfillment-api/units.md) の単位明細。本 API が `status` / `secured` / `secured_at` / `secured_by_staff_user_id` を更新します。
* `sot.lm_fulfillment_shipments` — 出荷元ヘッダ（梱包単位）。全ユニット確保で `secured` 遷移（先行生成済みラベルは再生成しません）。
* `sot.lm_routing_orders` — 注文ヘッダ。集約状態（`orderFulfillmentStatus`）の算出元。
* `sot.lm_shipping_instructions` — 保存済み出荷指示（ヘッダ遷移時の明細 / 配送先の出所）。
* `sot.lm_shelf_inventory` — 棚在庫。棚番号（`shelves[]`）の解決元（`qty>0` 優先・同点 `shelf_code` 昇順）。


---

# 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/operator-api/secure-by-tracking.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.
