For the complete documentation index, see llms.txt. This page is also available as Markdown.

Orders — 受注ルーティング

任意のカートシステム(Shopify / BASE / 自社 EC 等)から受注と 出荷元(fulfillment source)ロケーションID を送ると、その出荷元に紐づく 在庫ロケーション(member)内だけ で引き当て先を判定し、拠点ごとに分割した canonical 出荷指示 を生成します。外部 fulfillment(WMS / 3PL)への push と同期レスポンスでの返却を同時に行います。Shopify orders webhook に依存しない cart-agnostic な汎用エンドポイントです。

出荷元 (fulfillment source) = 実際に出荷する拠点(例: MFCセンター東京)。在庫ロケーション (inventory location) = 在庫を持つ倉庫・店舗。1つの出荷元に複数の在庫ロケーションが紐づき(1出荷元 : N在庫)、出荷元の販売可能在庫はメンバー在庫の合算です。紐付けは sot.lm_fulfillment_source_members で管理します。

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

エンドポイント

Method
Path
用途

POST

/api/routing/orders

受注を受け取り出荷元を判定 → 出荷指示を生成・dispatch

POST

/api/routing/orders/shipped

取込元で引き渡しが終わっている注文(店頭販売など)を、その拠点から出荷済みで登録

入力フィールドは camelCase(sourceSystem / externalOrderRef / fulfillmentSourceLocationId / shipTo / idempotencyKey)です。ingest 系の snake_case とは異なる点に注意してください。


POST /api/routing/orders

受注 1 件を受け取り、明細を unit(数量 1 個)単位で拠点へ配分し、出荷元ごとにまとめた出荷指示を返します。

リクエスト

POST https://api.lmile.io/api/routing/orders
x-ingest-secret: {INGEST_SECRET}
Content-Type: application/json
{
  "shop": "demo-store.myshopify.com",
  "sourceSystem": "shopify",
  "externalOrderRef": "1001",
  "fulfillmentSourceLocationId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "channel": "online_store",
  "idempotencyKey": "shopify:1001",
  "tag": "express",
  "shipTo": {
    "name": "山田 太郎",
    "company": null,
    "phone": "+819012345678",
    "email": "taro@example.com",
    "country": "JP",
    "postalCode": "150-0001",
    "prefecture": "東京都",
    "city": "渋谷区",
    "address1": "道玄坂1-2-3",
    "address2": "○○ビル 4F"
  },
  "lines": [
    { "barcode": "1234567890123", "quantity": 2 },
    { "barcode": "1234567890456", "quantity": 1, "properties": { "刻印": "T.Y", "ギフト包装": "あり" } }
  ]
}

ボディパラメータ

パラメータ
型
必須
説明

shop

string

店舗ドメイン(省略するとキーのアカウント)

sourceSystem

string

✓

カートの種別(shopify / base / self_ec 等、任意の識別子)。注文 identity・冪等キーの一部

externalOrderRef

string

✓

カート側の注文番号。注文 identity の一部

orderName

string

カート側の表示用注文番号(例 BJP999711)。倉庫間移動の内容物リスト(出荷ID配載 = W+数値部)・入荷予定 order_no の元値

referenceUrl

string (url)

カート側の注文参照 URL(例 Shopify admin の注文ページ https://admin.shopify.com/store/{handle}/orders/{id})。管理 UI が注文番号からカート管理画面へ遷移するリンクに使う。http(s) のみ

fulfillmentSourceLocationId

string (uuid)

✓

出荷元 location の id。この出荷元に紐づく在庫ロケーション内だけで引き当てる

inventoryLocationId

string (uuid)

引き当て先 在庫ロケーションの明示指定(任意)。指定時はこの location のみに引き当て(他メンバーへは振らない)。出荷元にマッピングされていなければ 422

suppressCustomerMail

boolean

true にすると、この注文では購入者にお届け状況メールを送りません(全段階とキャンセルのお知らせ)。一度指定すると取り消せません。省略時は店舗の通知設定どおり

suppressStorePrint

boolean

true にすると、この振り分けでは引き当て先の店舗で商品ラベル(統合QR)を自動印刷しません。引き当ての通知(Routing Allocation Webhook)は通常どおり送ります。省略時は印刷します

lines

array

✓

受注明細(1〜1,000 件)

channel

string

販売チャネル(channel_code または channel_id の UUID)。未解決でも在庫・拠点優先度で続行

shipTo

object

配送先(prefecture を region 判定に使用)

idempotencyKey

string

冪等キー。省略時は {sourceSystem}:{externalOrderRef} を自動採用

tag

string

ディスパッチ先(WMS)選択の条件 tag(任意・単一)。Dispatch Config の tag 一致設定を優先、無ければ既定。引き当て(routing)自体には影響しない

desiredDeliveryDate

string | null

配達希望日(ISO YYYY-MM-DD)。カート側が Shopify メタフィールド custom.pickup_date から取得。ラベル生成時に Ship&Co setup.date(配達指定日)へ載って佐川送り状へ印字。指定なしは未指定/null。後から手で設定する場合は Shipment Delivery

desiredDeliveryTime

string | null

配達希望時間帯(元表記。例 "午前中" / "12:00-14:00")。custom.pickup_time 由来。ラベル生成時に佐川コード(before-noon / 12-14 等)へ変換し setup.time へ載せる。佐川が認識しない表記は時間指定なし扱い

shipTo オブジェクト

Shopify MailingAddress / ship&co 準拠。全フィールド任意。出荷指示・WMS ディスパッチのテンプレート変数として使えます。

パラメータ
型
必須
説明

name

string

受取人氏名(ship&co full_name / Shopify name)

company

string

会社名

phone

string

電話番号(E.164 推奨)

email

string

メールアドレス

country

string

国コード(ISO-3166-1 alpha-2、例 JP)

postalCode

string

郵便番号(zip)

prefecture

string

都道府県(→ region に解決し地域一致スコアに使用。日本語都道府県名)

city

string

市区町村

address1

string

番地・町名

address2

string

建物名・部屋番号

lines[] オブジェクト

パラメータ
型
必須
説明

barcode

string

✓

商品識別子(sot.products との結合キー)

quantity

number

✓

数量(整数 1〜10,000)。unit 単位で拠点へ配分

properties

object

明細単位の任意キー/値(刻印テキスト・名入れ・ギフト指定等。Shopify line item property 相当)。最大 20 キー、キーは 1〜100 文字・値は 500 文字以内の文字列。省略 / null / 空 object は「なし」扱い。同一 barcode でも properties が異なる明細は別行のまま出荷指示・ピッキングリスト・dispatch payload へ透過されます

レスポンス

フィールド
説明

ok

通常 true。外部 dispatch が failed のときのみ false(HTTP は 200)

routingOrderId

routing order ヘッダの id(sot.lm_routing_orders.id)

status

received / routed / dispatched / failed / no_stock

shippingInstruction

拠点別に分割した canonical 出荷指示(下記)

dispatches

引き当て先ロケーションごとの送信結果配列(各 locationId / status: sent/failed/skipped / httpStatus / attempts / error)。送信先は Dispatch Config で登録

idempotent

既に dispatched 済の注文を再 POST した場合のみ true(再ルーティングせず既存結果を返却)

customerMailSuppressed / storePrintSuppressed

suppressCustomerMail / suppressStorePrint を受け付けたか。送った指定が false で返ってきたら、止まっていません

shippingInstruction

フィールド
説明

shipments[]

出荷元拠点ごとの出荷単位。fromLocationId / fromLocationLabel と lines[](barcode / quantity / properties。同一 barcode でも properties が異なれば別行。なしは null)

unroutableLines[]

引き当て不能だった分。barcode / quantity / reason(no_stock_anywhere 等)/ properties

serviceLines[]

非在庫サービス品(刻印サービス等、sot.products.is_non_inventory = true)の明細。barcode / quantity / properties。在庫引き当ての対象外(unroutableLines には含まれない)

decidedAt

判定時刻(ISO 8601, UTC)

ルーティング判定ロジック

各明細を unit 単位に展開し、指定された出荷元のメンバー在庫ロケーションを候補に順位付けして、在庫の続く限り上位拠点から greedy に配分します。

  • 候補拠点: 指定された出荷元に紐づく 有効な在庫ロケーション(member)のみ(sot.lm_fulfillment_source_members の is_active = true)。出荷元の外の拠点や ec_fulfillable フラグは判定に使いません(出荷元が EC 出荷の主体、member は在庫源)。

  • 在庫除外: 当該 barcode の routable = available_qty + committed_qty が 0 以下、または在庫レコード無しの member は除外(out_of_stock)。在庫の無い拠点には引き当てません。committed_qty の送り方は Inventory Levels を参照。

  • 非在庫サービス品の除外: sot.products.is_non_inventory = true の商品(刻印サービス等、物理在庫を持たないサービス/カスタム明細)は在庫引き当ての対象外です。該当 unit は unroutableLines ではなく serviceLines に分類され、判定根拠には reason: non_inventory_service が記録されます(フラグの設定は ops の明示操作のみ。SKU や品名による自動判定はしません)。

  • SKU 拠点オーバーライド(sot.lm_sku_location_overrides):

    • force_only — その拠点のみを候補にする

    • avoid — その拠点を除外する

    • force_first — その拠点を常に最優先で引き当てる

  • 引き当て順: 在庫のある候補を次の順で並べます — ① force_first 指定拠点 ② 出荷元自身の在庫(自己在庫を使い切ってから店舗メンバーへ)③ 販売可能在庫(available_qty)の多い順 ④ 配送先 region と拠点 region の一致 ⑤ member の priorityRank 昇順(未設定は最後)。committed_qty は順位には使わず、引き当て可否(routable > 0)と配分数の上限にのみ使います。スコア内訳(拠点優先度・地域一致・在庫量スコア等)は判定根拠として保存されますが、順位の決定には使いません。

  • 配分: 順位の上位から数量を unit 単位で greedy 配分。在庫が尽きて余った unit は unroutableLines(no_stock_anywhere)になります。

  • 明細のグルーピング: 同一 barcode の複数明細(properties 違い等)は合算して 1 回で引き当てます(別々に引き当てると在庫を二重参照するため)。引き当て後、unit(lineInstanceNo = 注文内 barcode 単位の連番)へ元明細の順に properties を配り戻し、出荷指示・ピッキングリストでは barcode × properties 単位で行を分けて集計します。

  • 引き当て先の明示指定: inventoryLocationId を指定すると候補をその location のみに限定します(出荷元の他メンバーへは振らない)。指定 location が出荷元にマッピングされていなければ 422 location_not_member_of_source。在庫不足分は unroutableLines。

出荷後に在庫が実際には無かった(売越し)場合は、/api/routing/oversell で該当結果に売越しフラグを立て、/api/routing/reallocate で同一出荷元の別メンバーへ再引き当てできます(Oversell / Reallocate)。

判定の根拠(拠点別スコア内訳・除外理由・採用理由)は sot.lm_routing_decisions / sot.lm_routing_candidates に監査ログとして保存されます。

挙動・冪等性

  • 入口冪等: (shop, sourceSystem, externalOrderRef) で routing order 1 行に収束します。status = dispatched の注文を再 POST すると、再ルーティングせず既存の出荷指示を idempotent: true で返します。

  • 再ルーティング: まだ dispatch されていない既存注文の再 POST は、前回の decision を破棄して再計算します。

  • 出口冪等: 出荷指示は (shop, idempotencyKey) で upsert され、外部への二重送信を防ぎます。

  • 外部 dispatch(per-location): 引き当て先の在庫ロケーションごとに登録された WMS 設定(Dispatch Config)でテンプレート描画して送信します(5xx は指数バックオフで最大 2 回再試行)。設定の無いロケーションは skip。結果は dispatches[] で返し、sot.lm_location_dispatch_log に記録します(ルーティング結果は常に保存・返却)。

  • 在庫無し: 引き当てられた unit が 1 つも無ければ status = no_stock、dispatch は skip(非在庫サービス品のみの注文も引き当て対象 unit が無いため no_stock になります)。

  • dispatch 失敗時: HTTP は 200 のまま ok: false / status: failed を返します(ルーティングは成功・保存済、外部送信のみ失敗)。

  • ルーティング完了直後の引き当て結果は Routing Allocation Webhook で外部へ通知されます(設定時のみ。引き当て不能明細・no_stock も unallocated イベントとして通知)。

  • 出荷元の確認待ち: 出荷元を引き当ての前に確認するアプリを登録したストアでは、送った fulfillmentSourceLocationId と別の出荷元で引き当てることがあります。確認が取れないときは引き当てずに HTTP 202 で status = received / pending: "source_decision" / routingOrderId: null を返し、確認が取れた時点でサーバー側が自動で引き当てます。再送は不要です(再送しても二重には引き当たりません)。アプリを登録していないストアでは起きません。

  • 通知・印刷を止める: 誤出荷の再手配など、購入者に知らせずに引き当てたいときは suppressCustomerMail: true を付けます。店舗での商品ラベルの印刷も要らないときは、あわせて suppressStorePrint: true を付けます。印刷を止めた注文を後から印刷したいときは、コンソールの出荷詳細から再印刷できます。


POST /api/routing/orders/shipped

取込元で既に引き渡しが終わっている注文(店頭販売など)を、受注と その拠点から出荷済みの出荷 として登録します。引き当て・在庫・配送ラベル・購入者への通知は動きません。

リクエスト

ボディパラメータ

パラメータ
型
必須
説明

shop

string

✓

店舗ドメイン

sourceSystem

string

✓

取込元の識別子(例 smaregi)

externalOrderRef

string

✓

取込元の注文 ID(例 スマレジの取引 ID)。sourceSystem との組で 1 注文

orderName

string

人が読む注文番号(例 BJP1000001)

referenceUrl

string

取込元の注文ページ URL(http(s) のみ)

locationId

uuid

△

出荷した拠点(= 引き当て拠点 = 出荷元)。location とどちらか一方

location

object

△

取込元の識別子で拠点を指す { "identifier_type", "identifier_value" }(例 smaregi_store_id)。locationId とどちらか一方

shippedAt

string

✓

引き渡した日時(ISO 8601。オフセット付き可)

orderedAt

string

注文の日時(ISO 8601)。受注の作成日時になります。省略すると shippedAt

channel

string

販売チャネル(channel_code か UUID。例 store)

shipTo

object

宛先(任意。項目は /api/routing/orders と同じ)

lines[]

array

✓

明細(1〜1000 行)。barcode / quantity(1 以上)と、任意の title / variantTitle

idempotencyKey

string

省略時 {sourceSystem}:{externalOrderRef}

dryRun

boolean

true で下見: 拠点の解決と判定だけ行い、何も書きません。{ "ok": true, "dryRun": true, "decision": "create" | "exists" | "cancelled" | "leg_cancelled" | "order_has_units", "units": 作る単位の数, "skippedLines": [...] } を返します(exists のときは既にある出荷の shipmentId / status も)

レスポンス

フィールド
説明

routingOrderId

受注の ID

shipmentId

作られた(または既にあった)出荷の ID

idempotent

true = その拠点の出荷が既にあり、何も変更していない(このときは skippedLines を返しません)

skippedLines[]

単位を作らなかった明細。non_inventory_service = 現物の無い同梱品(商品マスターで非在庫かつ付帯サービス。刻印サービスなど)

挙動・冪等性

  • 送ると、受注 1 件とその拠点からの出荷 1 件(明細は数量ぶんの単位)が 出荷済み で作られます。お届け状況は「発送済み」になります。受注の作成日時は orderedAt(省略時 shippedAt)、出荷の作成日時は shippedAt です(過去の注文を後から登録しても、一覧の「直近」には並びません)。

  • channel が店舗のチャネル(チャネルの種別が store。スマレジの取引など)なら、購入者がその場で受け取っているので、お届け状況は 配達完了(配達完了日時 = shippedAt)になります。それ以外のチャネルや channel 省略時は「発送済み」のままです。

  • 現物の無い同梱品(商品マスターで非在庫かつ付帯サービス。刻印サービスなど)の明細は単位を作らず skippedLines[] で返します。紙袋のように現物のある非在庫品は単位になります(引き当てと同じ扱い)。

  • 引き当て・在庫の予約・棚・配送ラベル・出荷指示の送信・引き当て通知・出荷ステータスの通知(Fulfillment Status Webhook)・購入者へのメールはどれも動きません。拠点の販売可能在庫は変わりません(店頭の在庫は取込元が正)。

  • 出荷元の設定(出荷元とそのメンバー)は見ません。指定した拠点がそのまま出荷元になります。

  • 冪等: 同じ注文にその拠点から出る出荷が既にあれば、作らずに idempotent: true と実際の status を返します。そのまま再送してよいです。「同じ注文」は externalOrderRef が同じもの、または {externalOrderRef}-… の形(拠点・刻印・別の荷物・海外再発送で分けた注文)を含みます。この受け口が作った出荷なら、途中で失敗して欠けた単位を埋め直します。他の経路の出荷(引き当て済み・出荷元変更後など)には触りません。

  • 同じ注文で別の拠点を送ると、その拠点の出荷が追加されます(複数の店舗から渡した注文)。ただし、その注文に別の拠点の生きた単位があるときは 409 order_has_units で作りません。

  • 同じ注文・同じ拠点に取消済みの出荷があるときは作り直しません(409 leg_cancelled)。

  • 商品マスターに無い barcode も登録します(SKU は空のまま)。

  • 取消済みの注文には登録しません(409 order_cancelled)。


エラー

エンドポイント固有:

Status
条件
レスポンス例

400

バリデーション失敗(fulfillmentSourceLocationId 欠落・非 UUID 含む)

{ "ok": false, "error": "invalid_input", "details": [{ "path": "fulfillmentSourceLocationId", "message": "..." }] }

422

出荷元が shop 内に存在しない

{ "ok": false, "error_kind": "fulfillment_source_unresolved", "error": "fulfillment source location not found for shop" }

422

出荷元に有効メンバーが無い

{ "ok": false, "error_kind": "fulfillment_source_no_members", "error": "fulfillment source has no active inventory-location members" }

422

指定 inventoryLocationId が出荷元のメンバーでない

{ "ok": false, "error_kind": "location_not_member_of_source", "error": "specified inventory location is not mapped to the fulfillment source" }

400

/orders/shipped: locationId と location の両方、またはどちらも無い

{ "ok": false, "error": "invalid_input", "details": [{ "path": "locationId", "message": "..." }] }

422

/orders/shipped: 拠点が解決できない(locationId が shop に無い / 識別子が未登録)

{ "ok": false, "error_kind": "location_unresolved", "error": "no location for smaregi_store_id=35" }

422

/orders/shipped: 識別子に複数の拠点が登録されている

{ "ok": false, "error_kind": "location_ambiguous", "error": "multiple locations for smaregi_store_id=35" }

409

/orders/shipped: 注文が取消済み

{ "ok": false, "error_kind": "order_cancelled", "error": "routing order is cancelled; not registering shipped leg" }

409

/orders/shipped: 同じ注文・同じ拠点に取消済みの出荷がある

{ "ok": false, "error_kind": "leg_cancelled", "error": "a cancelled leg already exists for this order at this location; not recreating", "shipmentId": "..." }

409

/orders/shipped: 注文に別の拠点の生きた単位がある

{ "ok": false, "error_kind": "order_has_units", "error": "routing order already has active units at another location; not adding a shipped leg" }

引き当て不能の明細はエラーではなく、レスポンス shippingInstruction.unroutableLines[] に reason 付きで返ります(正常処理を止めません)。非在庫サービス品(is_non_inventory = true)の明細は unroutableLines ではなく serviceLines[] に分類されます。共通エラー(401 / 400 / 403 / 405 / 500 / 503)は Error Codes を参照。

データモデル

  • sot.lm_fulfillment_source_members — 出荷元 → 在庫ロケーション 紐付け(1出荷元 : N在庫。UNIQUE shop + inventory_location_id)

  • sot.lm_routing_orders — routing-native の注文ヘッダ(入口冪等。UNIQUE shop + source_system + external_order_ref)。status: received / routed / dispatched / failed / no_stock

  • sot.lm_routing_decisions — unit 単位の判定結果(routing_order_id / barcode / line_instance_no / line_properties(= lines[].properties。名入れ等は顧客 PII になり得るため agent_read 非公開)、fulfillment_source_location_id = 指定出荷元、selected_location_id = 引き当て先在庫ロケーション、decision_status = applied。売越し時は oversold / superseded_by_decision_id)

  • sot.lm_routing_candidates — 判定時の候補スコア snapshot(拠点別スコア内訳・除外理由・rank)

  • sot.lm_shipping_instructions — 出荷指示 dispatch ログ(delivery_status: pending / sent / failed / skipped。UNIQUE shop + idempotency_key)

  • sot.lm_fulfillment_shipments / sot.lm_fulfillment_units — /orders/shipped が直接作る出荷と単位(status = shipped・decision 無し・在庫中立マーカー shelf_released_at 付き)。sot.location_identifiers で location の識別子を拠点に解決

  • 参照(read): sot.locations / sot.lm_location_priorities / sot.lm_sku_location_overrides / sot.lm_region_mappings / sot.channels / sot.products / sot.inventory_levels

受注の 販売実績 SoT(sot.order_line_master)とは分離した routing-native の identity(source_system + external_order_ref + shipTo)を持ちます。ルーティングは販売実績の取込とは独立して動作します。

Last updated

Was this helpful?