> 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/routing-api/inventory-adjustments.md).

# Inventory Adjustments — 外部システムへの在庫調整

店舗（外部システムが在庫の正の拠点）の[棚卸](/lmile-docs/operator-api/stocktake.md)を承認すると、商品ごとの差分（数えた良品の数 − 帳簿数）が「外部システムへ当てる調整」として貯まります。スマレジや Shopify に在庫数を書くコネクタは、この API で自分の分を取りに来て（`claim`）、外部システムの在庫数に**相対値**で当て、結果を返します（`result`）。サーバーは外部システムの API も様式も知りません。

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

## エンドポイント

| Method | Path                                        | 用途                                         | テーブル                                |
| ------ | ------------------------------------------- | ------------------------------------------ | ----------------------------------- |
| `POST` | `/api/routing/inventory-adjustments/claim`  | 未処理の調整を取りに来る（取った行は `claimed`）              | `lm_inventory_external_adjustments` |
| `POST` | `/api/routing/inventory-adjustments/result` | 当てた結果を返す（`applied` / `failed` / `unknown`） | `lm_inventory_external_adjustments` |

読み取りは `agent_read.inventory_external_adjustments` です。

### 状態

| `status`  | 意味                                                         |
| --------- | ---------------------------------------------------------- |
| `pending` | 承認で作られた。まだ誰も取っていない                                         |
| `claimed` | コネクタが取った。一定時間（既定 30 分）結果が返らなければ、次の `claim` が取り直します         |
| `applied` | 外部システムに当てた                                                 |
| `failed`  | 当てられなかった（商品が外部に無い・4xx など）。自動では再送しません                       |
| `unknown` | 送ったが結果が分からない（タイムアウトなど）。自動では再送しません。人が外部システムを確認して、必要なら手で直します |

> 相対値（`+1` / `-2`）を当てるので、**同じ調整を 2 回当てると二重**になります。結果が分からないときは `applied` と推測せず `unknown` で返してください。

***

## `POST` /api/routing/inventory-adjustments/claim

自分のコネクタ宛の未処理の調整を、古い順にまとめて取ります。取った行は `claimed` になり、他の呼び出しには出なくなります。

### リクエスト

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

```json
{ "shop": "demo-store.myshopify.com", "connector": "smaregi", "limit": 50 }
```

### ボディパラメータ

| パラメータ                 | 型            |  必須 | 説明                                                                  |
| --------------------- | ------------ | :-: | ------------------------------------------------------------------- |
| `shop`                | string       |  ✓  | 店舗ドメイン                                                              |
| `connector`           | string       |  ✓  | `smaregi` または `shopify`。拠点の識別子（スマレジ店舗 ID / Shopify ロケーション ID）で決まります |
| `limit`               | number (int) |     | 1 回で取る件数（1〜200。既定 50）                                               |
| `reclaimAfterMinutes` | number (int) |     | `claimed` のまま結果が返らない行を取り直すまでの分数（5〜1440。既定 30）                       |

### レスポンス

```json
{
  "ok": true,
  "connector": "smaregi",
  "adjustments": [
    {
      "adjustmentId": "3f1c…",
      "sessionId": "9a2b…",
      "locationId": "b2c3d4e5-f6a7-8901-bcde-f23456789012",
      "externalLocationId": "12",
      "barcode": "4912345678901",
      "delta": -1,
      "attempts": 1,
      "createdAt": "2026-10-08T03:00:00Z"
    }
  ]
}
```

| フィールド                | 説明                                                                                  |
| -------------------- | ----------------------------------------------------------------------------------- |
| `externalLocationId` | 拠点の外部システム側の ID（`smaregi` ならスマレジの店舗 ID、`shopify` なら Shopify のロケーション ID）。未登録なら `null` |
| `delta`              | 外部システムの在庫数に当てる差（0 以外。`+` は増やす、`-` は減らす）                                             |
| `attempts`           | 取られた回数。2 以上は取り直された行です                                                               |

### 挙動・冪等性

* 取った行はこの呼び出しの中で `claimed` になります。同時に 2 つのワーカーが呼んでも同じ行は 1 つにしか渡りません。
* `claimed` のまま `reclaimAfterMinutes` を過ぎた行は、次の `claim` で取り直します（`attempts` が増えます）。結果を返せなかったワーカーの分を拾うためです。**取り直した行を当てる前に、前回が外部システムに届いていないことを確認してください**（届いていたなら `applied` で返す）。
* `failed` / `unknown` / `applied` の行は返しません。
* 未処理が無ければ `adjustments: []` です。

***

## `POST` /api/routing/inventory-adjustments/result

当てた結果を返します。

### リクエスト

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

```json
{ "shop": "demo-store.myshopify.com", "adjustmentId": "3f1c…", "status": "applied", "externalRef": "smaregi stock history 8812" }
```

### ボディパラメータ

| パラメータ          | 型             |  必須 | 説明                                                   |
| -------------- | ------------- | :-: | ---------------------------------------------------- |
| `shop`         | string        |  ✓  | 店舗ドメイン                                               |
| `adjustmentId` | string (uuid) |  ✓  | `claim` で受け取った id                                    |
| `status`       | string        |  ✓  | `applied`（当てた）/ `failed`（当てられなかった）/ `unknown`（分からない） |
| `errorKind`    | string        |     | 失敗の種類（最大 64 文字。例: `http_4xx` / `product_not_found`）  |
| `message`      | string        |     | 失敗の説明（最大 500 文字）                                     |
| `externalRef`  | string        |     | 外部システム側の参照（在庫履歴 ID など。最大 200 文字）                     |

### レスポンス

```json
{ "ok": true, "recorded": true, "status": "applied" }
```

| フィールド      | 説明                                                        |
| ---------- | --------------------------------------------------------- |
| `recorded` | この呼び出しで状態が変わった。`false` なら既に確定していて何もしていません（`status` に今の状態） |

### 挙動・冪等性

* `claimed` と `unknown` の行だけ確定します。`applied` / `failed` の行への再報告は `recorded: false` で何もしません（結果を上書きしません）。
* `unknown` の行は、人が外部システムを確認したあと `applied` か `failed` で確定できます。

## エラー

エンドポイント固有:

| Status | 条件                                  | レスポンス例                                                                        |
| :----: | ----------------------------------- | ----------------------------------------------------------------------------- |
|  `404` | `adjustmentId` が shop に無い（`result`） | `{ "ok": false, "error_kind": "not_found", "error": "adjustment not found" }` |

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

## データモデル

* `sot.lm_inventory_external_adjustments` — 外部システムへ当てる差分。`UNIQUE (session_id, product_id)`。`connector` / `delta`（0 以外）/ `status` / `attempts` / `claimed_at` / `result_at` / `error_kind` / `error_message` / `external_ref`。読み取り view: `agent_read.inventory_external_adjustments`
* 作る側は [棚卸の承認](/lmile-docs/operator-api/stocktake.md#post-apioperatorstocktakecommit)（拠点全体の棚卸・在庫同期の向きが双方向の拠点だけ）


---

# 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/routing-api/inventory-adjustments.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.
