> 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/ingestion-api/inventory-levels.md).

# Inventory Levels — 在庫

在庫を Last Mile の在庫マスターに取り込みます。用途別に 2 エンドポイントに分かれます: **定期的な全量同期は snapshot、販売・入荷など変動イベントの都度反映は available** を使います（外部倉庫の拠点で販売チャネル側の販売可能数を伝える [channel-available](#post-apiingestchannel-available) もあります）。両方の併用も可能です（[古い読み値の上書き防止](#古い読み値の上書き防止)により、古いバッチ読み値がリアルタイム更新済みの値を上書きすることはありません）。商品は `barcode`、拠点は `location_id` または外部識別子で解決します。

> **Base URL** `https://api.lmile.io` · **認証** `x-ingest-secret` ヘッダー（[詳細](/lmile-docs/getting-started/authentication.md)） · `shop` はリクエストボディに含めます（省略するとキーのアカウント）

## エンドポイント

| Method | Path                              | 用途                                                   | こんなとき                                    |
| ------ | --------------------------------- | ---------------------------------------------------- | ---------------------------------------- |
| `POST` | `/api/ingest/inventory-snapshot`  | 1 拠点の現在庫を絶対値で一括投入（全在庫を上書き）                           | 初回投入 / 1 日 1 回などの定期全量同期 / ズレ補正           |
| `POST` | `/api/ingest/inventory-available` | 販売可能在庫 (`available_qty`) のリアルタイム更新（absolute / delta） | 販売・入荷・返品などの変動をその場で反映                     |
| `POST` | `/api/ingest/channel-available`   | 販売チャネル（Shopify など）での販売可能数を伝える                        | 在庫数を外部倉庫が送ってくる拠点で、チャネルで売っていない商品を売れない数にする |

> 取込により出荷元の合算在庫が変わると [Source Inventory Webhook](/lmile-docs/webhooks/source-inventory.md) が発火します。

> **レート制限はありません**。上限は 1 リクエストあたり `lines` 最大 **10,000 行**です（超過は `400`）。

### 商品（barcode）の指定

両エンドポイント共通。商品は行の `barcode`（JAN コード）で商品マスターと照合します。**SKU や商品名では照合できません**。未登録の `barcode` はリクエスト全体を失敗させず、HTTP `200` のまま該当行だけ反映されず `unresolved[]` に返ります（→ [行単位エラー](#エラー)）。事前に [Products](/lmile-docs/ingestion-api/products.md) で商品（barcode）を登録してください。

### 拠点（location）の指定

両エンドポイント共通。`location_id`（内部 UUID）か `location`（外部識別子）のいずれかを指定します。

```jsonc
"location_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
// または
"location": { "identifier_type": "smaregi_store_id", "identifier_value": "4" }
```

### 古い読み値の上書き防止

両エンドポイント共通。\*\*「古い在庫の読み値で、新しい値を上書きしない」\*\*ための仕組みです。

**いつ関係するか** — 在庫を複数の経路で送っている場合です。典型は「販売のたびに送るリアルタイム更新」と「数時間おきのバッチ全量同期」の併用。バッチは在庫を読み取ってから届くまでに時間差があるため、対策がないとバッチの古い在庫数が直近のリアルタイム更新を巻き戻してしまいます（売り切れた商品が「在庫あり」に戻る事故）。**送信経路が 1 つだけなら、この節は読み飛ばして構いません**（`as_of` 省略のままで正しく動きます）。

**具体例** — 1 時間おきのバッチとリアルタイム更新を併用しているとき:

| 時刻    | 起きること                                                                     |
| ----- | ------------------------------------------------------------------------- |
| 14:00 | バッチが在庫システムから読み取り: barcode `1234567890123` = **5 個**                       |
| 14:10 | 店頭で 5 個売れ、リアルタイム更新が `available_qty: 0` を送信 → 在庫 **0**（読み値の時刻 14:10 として反映） |
| 14:30 | 14:00 に読んだバッチが届き、`available_qty: 5` を `as_of: 14:00` 付きで送信                |

14:30 の行は「14:00 の読み値 < 反映済みの 14:10」なので**適用されず**、在庫は 0 のまま守られます。この仕組みが無ければ在庫が 5 に巻き戻り、実際には無い在庫が売れてしまいます。

**判定ルール** — 各行の `as_of`（省略時はリクエストの `inventory_as_of`、それも省略なら受信時刻）を、反映済みの時刻と比較します。

| 行の時刻 vs 反映済みの時刻      | 結果                                                 |
| -------------------- | -------------------------------------------------- |
| 新しい / 同じ / 初回（既存行なし） | 適用します（同時刻を許すので、同じリクエストの再送は成功します）                   |
| 古い                   | その行だけ適用しません。HTTP `200` のまま `stale_skipped[]` に返ります |

**レスポンスの見方** — 上の 14:30 のリクエストにはこう返ります:

```jsonc
"lines_stale_skipped": 1,
"stale_skipped": [
  { "barcode": "1234567890123",
    "as_of": "2026-06-02T14:00:00+09:00",         // 今回送って弾かれた読み値の時刻
    "current_as_of": "2026-06-02T14:10:00+09:00"  // 反映済みの、より新しい時刻
  }
]
```

**送信側がやること**

* バッチ連携では、各行の `as_of` に**在庫システム側でその値を読み取った時刻**を入れてください（例: スマレジ `/stock` の `updDateTime`）。**送信時刻ではありません**。
* 送信経路が 1 つだけなら `as_of` は省略できます（受信時刻が使われ、古い読み値として弾かれることはありません）。
* `stale_skipped[]` は「より新しい値が反映済み」の合図です。**再送は不要です**。恒常的に大量に返る場合だけ、`as_of` に入れている時刻が正しいか確認してください。

***

## `POST` /api/ingest/inventory-snapshot

「今この拠点にこの商品が何個あるか」を絶対値で送信します。送るたびに現在庫が**送った値で丸ごと置き換わります**（追記や加算ではありません）。当日の日次履歴と変更ログも同時に更新されます。

### リクエスト

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

```json
{
  "shop": "demo-store.myshopify.com",
  "source_system": "smaregi",
  "location": { "identifier_type": "smaregi_store_id", "identifier_value": "4" },
  "inventory_as_of": "2026-06-02T18:00:00+09:00",
  "idempotency_key": "smaregi-2026-06-02-loc4",
  "lines": [
    { "barcode": "1234567890123", "on_hand_qty": 10, "available_qty": 8, "allocated_qty": 2 }
  ]
}
```

### ボディパラメータ

| パラメータ                                                 | 型               |  必須 | 説明                                                                            |
| ----------------------------------------------------- | --------------- | :-: | ----------------------------------------------------------------------------- |
| `shop`                                                | string          |     | 店舗ドメイン（省略するとキーのアカウント）                                                         |
| `source_system`                                       | string          |  ✓  | 取込元。ログの `change_source` に記録                                                   |
| `location_id` / `location`                            | string / object |  ✓  | いずれか必須（上記参照）                                                                  |
| `lines`                                               | array           |  ✓  | 在庫行の配列（最大 10,000 件）                                                           |
| `inventory_as_of`                                     | ISO 8601        |     | 読み取り時刻の既定値。行の `as_of` 省略時に使われます（それも省略なら受信時刻。→ [古い読み値の上書き防止](#古い読み値の上書き防止)）    |
| `idempotency_key`                                     | string          |     | 監査用の任意キー。**このエンドポイントでは重複排除に使いません**（再送の安全性は絶対値の置き換えで担保されます）                    |
| `lines[].barcode`                                     | string          |  ✓  | 商品 barcode                                                                    |
| `lines[].on_hand_qty`                                 | integer (≥0)    |  ✓  | 物理在庫（拠点に実在する数）                                                                |
| `lines[].available_qty`                               | integer         |     | 販売可能在庫（**省略時は `on_hand_qty`**）                                                |
| `lines[].allocated_qty` `reserved_qty` `incoming_qty` | integer         |     | 引当 / 予約 / 入荷予定（default: 0）                                                    |
| `lines[].as_of`                                       | ISO 8601        |     | その行の読み値を在庫システム側で読み取った時刻。省略時は `inventory_as_of`（→ [古い読み値の上書き防止](#古い読み値の上書き防止)） |

### レスポンス

```json
{
  "ok": true,
  "shop": "demo-store.myshopify.com",
  "location_id": "c1cdb7d4-d435-40a6-9c7f-95108f99b35e",
  "lines_processed": 3,
  "lines_upserted": 2,
  "lines_unresolved": 1,
  "lines_stale_skipped": 0,
  "logs_written": 2,
  "unresolved": [ { "barcode": "0000000000000", "reason": "product_not_found" } ],
  "stale_skipped": []
}
```

| フィールド                 | 説明                                            |
| --------------------- | --------------------------------------------- |
| `lines_processed`     | 受け取った行数                                       |
| `lines_upserted`      | 在庫に反映した行数                                     |
| `lines_unresolved`    | 反映しなかった行数（内訳は `unresolved[]`）                 |
| `lines_stale_skipped` | 読み値が古く反映しなかった行数（内訳は `stale_skipped[]`）        |
| `logs_written`        | 変更ログを書いた行数（値が変わった行のみ）                         |
| `unresolved[]`        | 反映しなかった行と理由（→ [行単位エラー](#エラー)）                 |
| `stale_skipped[]`     | 読み値が古く反映しなかった行（→ [古い読み値の上書き防止](#古い読み値の上書き防止)） |

### 挙動・冪等性

* 在庫は**店舗 × 商品 × 拠点ごとに 1 行**で管理されます。送信すると該当行が**送った値で丸ごと置き換わり**、無ければ新規作成されます（追記や加算はされません）。
* 同時に、その日の日次履歴も同じ値に更新されます（1 日 1 行。同じ日に何度送っても増えません）。
* 変更ログは**値が変わった行だけ**記録されます。同じ値の再送でログは増えません。
* **同じリクエストは何度再送しても安全です（冪等）**。タイムアウト等で結果が不明なときは、そのまま再送してください。
* 未登録の `barcode` の行はその行だけ反映されず `unresolved[]` に返ります（→ [行単位エラー](#エラー)）。
* 行の読み値が反映済みより古い場合はその行だけ反映されません（→ [古い読み値の上書き防止](#古い読み値の上書き防止)）。

***

## `POST` /api/ingest/inventory-available

販売可能在庫 (`available_qty`) を即時更新します。1 リクエストで 1〜数件の `(barcode × 拠点)` を更新する用途です。

任意で `committed_qty`（注文済み・未出荷）と `on_hand_qty`（物理在庫）も同時に送れます。**送った行だけ上書きされ、省略した値は現状維持**です（`allocated_qty` / `reserved_qty` はこのエンドポイントでは変わりません）。

> **なぜ `committed_qty` も送るのか** — Shopify では注文が入った瞬間、その分の在庫は `available` から `committed`（注文済み・未出荷）へ移ります。例: 在庫 1 個の商品が売れると `available: 0, committed: 1`。このとき `available_qty: 0` だけを送ると Last Mile からは「在庫なし」に見え、**いま入ったその注文にすら引き当てられません**。`committed_qty: 1` を併せて送ると、引き当て可能数は `available + committed = 1` と判定され、その注文のために確保済みの 1 個へ正しく引き当てられます。

`available_qty` の送り方は `mode` で選びます:

| `mode`     | 送る値                                  | こんなとき                          | 再送したら                                                                        |
| ---------- | ------------------------------------ | ------------------------------ | ---------------------------------------------------------------------------- |
| `absolute` | 在庫数そのもの（`available_qty: 3` = 3 個にする） | その時点の在庫数を知っている場合。**可能ならこちら推奨** | 同じ値で上書きされるだけ。**安全（冪等）**                                                      |
| `delta`    | 増減量（`available_delta: -2` = 2 個減らす）  | 販売・返品などの変動イベントしか取れない場合         | **二重に増減してしまうため、イベントごとに一意な `idempotency_key` を必ず付けてください**（同一キーの 2 回目は適用されません） |

delta の結果が負になる場合は 0 で止まり、`clamped[]` に返ります（エラーにはなりません）。`committed_qty` / `on_hand_qty` は `mode` に関わらず常に「在庫数そのもの」で送ります。

### リクエスト

```json
// absolute
{
  "shop": "demo-store.myshopify.com",
  "source_system": "shopify",
  "mode": "absolute",
  "location_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "lines": [ { "barcode": "1234567890123", "available_qty": 0, "committed_qty": 1, "on_hand_qty": 1 } ]
}
```

```json
// delta
{
  "shop": "demo-store.myshopify.com",
  "source_system": "pos",
  "mode": "delta",
  "idempotency_key": "sale-1234567890",
  "location": { "identifier_type": "smaregi_store_id", "identifier_value": "4" },
  "lines": [ { "barcode": "1234567890123", "available_delta": -2 } ]
}
```

### ボディパラメータ

| パラメータ                      | 型               |      必須      | 説明                                                                            |
| -------------------------- | --------------- | :----------: | ----------------------------------------------------------------------------- |
| `shop`                     | string          |              | 店舗ドメイン（省略するとキーのアカウント）                                                         |
| `source_system`            | string          |       ✓      | 取込元                                                                           |
| `mode`                     | string          |       ✓      | `absolute` または `delta`                                                        |
| `location_id` / `location` | string / object |       ✓      | いずれか必須                                                                        |
| `lines`                    | array           |       ✓      | 更新行の配列（最大 10,000 件）                                                           |
| `inventory_as_of`          | ISO 8601        |              | 読み取り時刻の既定値。行の `as_of` 省略時に使われます（それも省略なら受信時刻。→ [古い読み値の上書き防止](#古い読み値の上書き防止)）    |
| `idempotency_key`          | string          |              | delta では**イベントごとに一意な値を必ず**（同一キーの 2 回目は適用されません）。absolute では不要                  |
| `lines[].barcode`          | string          |       ✓      | 商品 barcode                                                                    |
| `lines[].available_qty`    | integer (≥0)    | absolute 時 ✓ | 上書きする販売可能在庫                                                                   |
| `lines[].available_delta`  | integer         |   delta 時 ✓  | 変動量（負可）                                                                       |
| `lines[].committed_qty`    | integer (≥0)    |              | 注文済み・未出荷の数を上書き（省略時は現状維持）。→ 上の「なぜ `committed_qty` も送るのか」                       |
| `lines[].on_hand_qty`      | integer (≥0)    |              | 物理在庫を上書き（省略時は現状維持）                                                            |
| `lines[].as_of`            | ISO 8601        |              | その行の読み値を在庫システム側で読み取った時刻。省略時は `inventory_as_of`（→ [古い読み値の上書き防止](#古い読み値の上書き防止)） |

### レスポンス

```json
{
  "ok": true,
  "mode": "delta",
  "shop": "demo-store.myshopify.com",
  "location_id": "c1cdb7d4-d435-40a6-9c7f-95108f99b35e",
  "lines_processed": 2,
  "lines_updated": 1,
  "lines_unresolved": 0,
  "lines_clamped": 1,
  "lines_deduped": 0,
  "lines_stale_skipped": 0,
  "unresolved": [],
  "clamped": [ { "barcode": "1234567890123", "computed": -85, "set": 0 } ],
  "stale_skipped": []
}
```

| フィールド                 | 説明                                            |
| --------------------- | --------------------------------------------- |
| `lines_processed`     | 受け取った行数                                       |
| `lines_updated`       | 在庫に反映した行数                                     |
| `lines_unresolved`    | 反映しなかった行数（内訳は `unresolved[]`）                 |
| `lines_clamped`       | delta の結果が負になり `0` に丸めた行数（内訳は `clamped[]`）    |
| `lines_deduped`       | 同一 `idempotency_key` の二重適用として skip した行数       |
| `lines_stale_skipped` | 読み値が古く反映しなかった行数（内訳は `stale_skipped[]`）        |
| `unresolved[]`        | 反映しなかった行と理由（→ [行単位エラー](#エラー)）                 |
| `clamped[]`           | 0 に丸めた行（`{ barcode, computed, set }`）         |
| `stale_skipped[]`     | 読み値が古く反映しなかった行（→ [古い読み値の上書き防止](#古い読み値の上書き防止)） |

### 挙動・冪等性

* 送った行の `available_qty` が更新されます。在庫行が無ければ新規作成されます（送らなかった数量は 0 で作成）。
* `committed_qty` / `on_hand_qty` は**送った行だけ**上書きされ、省略した値は現状維持です（`allocated_qty` / `reserved_qty` はこのエンドポイントでは変わりません）。
* 変更ログは**値が変わった行だけ**記録されます。
* **日次履歴は更新しません**（日次は snapshot エンドポイントの役割です）。
* `absolute` は同じ値の再送で上書きされるだけなので安全です（冪等）。`delta` の重複排除は連続リトライを吸収する best-effort です。**イベントごとに一意な `idempotency_key` を必ず付けてください**。
* 行の読み値が反映済みより古い場合はその行だけ反映されません（→ [古い読み値の上書き防止](#古い読み値の上書き防止)）。

## `POST` /api/ingest/channel-available

販売チャネル（Shopify など）で、ある拠点の商品がいくつ売れる状態かを伝えます。**在庫の数そのものは外部倉庫など別の送り手が送ってくる拠点**（外部倉庫の拠点）のためのエンドポイントです。

送った値が **0 以下の商品は、その拠点の販売可能在庫が 0 になります**。倉庫に現物があってもチャネルで売っていない商品を、Last Mile でも「売れない」として扱うためです。1 以上を送ると、倉庫から届いた在庫数にもとづく通常の計算に戻ります。

例: 倉庫から「在庫 3」が届いている商品について

| 送った `channel_available_qty` | 販売可能在庫                         |
| :-------------------------: | ------------------------------ |
|             未送信             | 倉庫の数にもとづく通常の計算（例: 3）           |
|        `0` または負（売り越し）       | **0**                          |
|            `1` 以上           | 通常の計算に戻る（例: 3。送った数そのものにはなりません） |

* **倉庫から届いた在庫数は書き換えません**。倉庫の数は従来どおり [inventory-available](#post-apiingestinventory-available) で送ってください
* **受注の引き当ては止まりません**。外部倉庫の拠点は在庫数に関わらず受注を引き受けます。0 で変わるのは販売可能在庫の数（お届け予定日の表示・入荷通知など）です
* 外部倉庫の拠点以外に送ると `422`（`location_not_derived`）で拒否します

### リクエスト

```json
{
  "shop": "demo-store.myshopify.com",
  "source_system": "shopify",
  "location_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "inventory_as_of": "2026-09-27T05:00:00Z",
  "lines": [
    { "barcode": "1234567890123", "channel_available_qty": 0 },
    { "barcode": "1234567890124", "channel_available_qty": 5 }
  ]
}
```

### ボディパラメータ

| パラメータ                           | 型             |  必須 | 説明                                              |
| ------------------------------- | ------------- | :-: | ----------------------------------------------- |
| `shop`                          | string        |  ✓  | 店舗ドメイン                                          |
| `source_system`                 | string        |  ✓  | 送り元（変更ログに残ります）                                  |
| `location_id`                   | string (UUID) |  ✓  | 外部倉庫の拠点の内部 UUID（外部識別子での指定はできません）                |
| `lines`                         | array         |  ✓  | 更新行の配列（最大 10,000 件）                             |
| `inventory_as_of`               | ISO 8601      |     | 読み取り時刻の既定値。行の `as_of` 省略時に使われます（それも省略なら受信時刻）    |
| `lines[].barcode`               | string        |  ✓  | 商品 barcode                                      |
| `lines[].channel_available_qty` | integer       |  ✓  | チャネルでの販売可能数。**負の値もそのまま送ってください**（0 以下はすべて「売れない」） |
| `lines[].as_of`                 | ISO 8601      |     | その行の値を読み取った時刻                                   |

### レスポンス

```json
{
  "ok": true,
  "location_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "lines_processed": 2,
  "lines_updated": 1,
  "unresolved": [],
  "stale_skipped": [],
  "changed": [ { "locationId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "barcode": "1234567890123", "qtyBefore": 3, "qtyAfter": 0 } ]
}
```

| フィールド             | 説明                                                                |
| ----------------- | ----------------------------------------------------------------- |
| `lines_processed` | 受け取った行数                                                           |
| `lines_updated`   | チャネルの販売可能数が前回から変わった行数                                             |
| `unresolved[]`    | 反映しなかった行と理由（→ [行単位エラー](#エラー)）                                     |
| `stale_skipped[]` | 読み値が古く反映しなかった行（`{ barcode, as_of, current_as_of }`）               |
| `changed[]`       | その結果、販売可能在庫が変わった行（`{ locationId, barcode, qtyBefore, qtyAfter }`） |

### 挙動・冪等性

* 同じ値を再送しても結果は変わりません（冪等）。そのまま再送して構いません。
* 受け取った時刻より新しい値がすでに届いている行は反映しません（`stale_skipped[]`）。順序が入れ替わって届いても、新しい値が勝ちます。
* 在庫行がまだ無い商品（倉庫から一度も在庫数が届いていない商品）は、在庫 0 の行を作ってから反映します。例: 新商品に `channel_available_qty: 0` を送ると、その拠点の販売可能在庫が 0 になります。あとから倉庫が在庫数を送ると、その数で通常どおり計算されます。
* 販売可能在庫が変わると、[Source Inventory Webhook](/lmile-docs/webhooks/source-inventory.md) の対象になります（取込と同じ扱い）。

***

## エラー

エラーは 2 種類あります: **リクエスト全体のエラー**（HTTP 4xx で全行不採用）と、**行単位エラー**（HTTP `200` のまま該当行だけ不採用）。

### リクエスト全体のエラー

エンドポイント固有:

| Status | 条件                          | レスポンス例                                                                                                     |
| :----: | --------------------------- | ---------------------------------------------------------------------------------------------------------- |
|  `422` | `ok:false`（`error_kind` 付き） | `{ "ok": false, "error_kind": "location_unresolved", "error": "no location for smaregi_store_id=999999" }` |
|  `400` | `lines` が 10,000 行を超過       | `{ "ok": false, "error": "max 10000 lines per request" }`                                                  |

`error_kind`: `invalid_payload` / `location_unresolved` / `location_ambiguous`。channel-available では `location_not_found`（`shop` にその拠点が無い）/ `location_not_derived`（外部倉庫の拠点ではない）も返ります。共通エラー（`401` / `400` / `403` / `405` / `500` / `503`）は [Error Codes](/lmile-docs/reference/error-codes.md) を参照。

### 行単位エラー（HTTP `200`）

解決できない行があっても**リクエスト全体はエラーになりません**。HTTP `200`・`ok: true` のまま該当行だけ在庫に反映されず、レスポンスの配列に理由付きで返ります（silent skip はしません）。**「`200` が返るのに在庫が変わらない」場合は、まず `unresolved[]` / `stale_skipped[]` を確認してください。接続テスト時はこれらが空であることの確認を推奨します。**

| 配列                | `reason`                                            | 意味                                                                                    |
| ----------------- | --------------------------------------------------- | ------------------------------------------------------------------------------------- |
| `unresolved[]`    | `product_not_found`                                 | `barcode` が商品マスター未登録（最頻出。先に [Products](/lmile-docs/ingestion-api/products.md) で登録）    |
| `unresolved[]`    | `missing_barcode`                                   | 行に `barcode` が無い                                                                      |
| `unresolved[]`    | `missing_on_hand_qty`                               | snapshot: 行に `on_hand_qty` が無い                                                        |
| `unresolved[]`    | `missing_available_qty` / `missing_available_delta` | available: `mode` に対応する値（absolute → `available_qty` / delta → `available_delta`）が行に無い |
| `unresolved[]`    | `invalid_as_of`                                     | 行の `as_of` が日時として解釈できない                                                               |
| `unresolved[]`    | `invalid_channel_available_qty`                     | channel-available: `channel_available_qty` が整数でない                                     |
| `stale_skipped[]` | —（`{ barcode, as_of, current_as_of }` を返却）          | 反映済みより古い読み値のため適用せず。再送不要（→ [古い読み値の上書き防止](#古い読み値の上書き防止)）                                |

## データモデル

* `sot.inventory_levels` — 現在庫マスター（`shop + product_id + location_id` で一意）。channel-available の値は `channel_available_qty` / `channel_available_as_of`
* `sot.inventory_update_logs` — 変更監査ログ（`change_type`: `snapshot` / `available_set` / `available_delta` / `committed_set` / `on_hand_set` / `channel_available_set`）
* read は `agent_read.inventory_levels` / `inventory_update_logs`（safe view）経由


---

# 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/ingestion-api/inventory-levels.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.
