商品¶
PUT /products
商品主檔與選項群組批次 upsert。只送有異動的商品,且須在當日交易推送之前送出。
權限¶
API 金鑰(x-functions-key)
Request¶
| Header | 必填 | 說明 |
|---|---|---|
| x-functions-key | Y | {api_key} |
| Content-Type | Y | application/json |
Body
| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
| batch_id | UUID | Y | 冪等鍵 |
| products | array of Product | Y | 0~500 筆(只更新選項群組時可為空陣列) |
| modifier_groups | array of ModifierGroup | N | 選項群組;有異動才送,依 group_id upsert |
Product¶
| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
| product_id | string | Y | 合作夥伴的商品代碼 |
| store_id | string | null | N | 門市專屬商品;null 或省略表示全門市共用 |
| sku | string | N | 條碼或 SKU |
| name | localized text | Y | 多語系名稱,至少一個語系 |
| category_id | string | N | 分類代碼 |
| category_name | localized text | N | 多語系分類名稱 |
| unit_price | decimal string | Y | 售價(是否含稅依門市 prices_include_tax) |
| currency | string | Y | ISO 4217 |
| tax_category | enum | N | STANDARD / REDUCED / ZERO / EXEMPT |
| status | enum | Y | ACTIVE / INACTIVE |
| effective_from | timestamp | N | 價格生效時間 |
| version | integer | Y | 每次異動 +1 |
| last_modified_at | timestamp | Y | 最後異動時間 |
| product_type | enum | Y | SINGLE(單點)/ COMBO(套餐)/ SIDE(附餐)/ DRINK(飲料)/ MODIFIER(加購選項) |
| modifier_group_ids | array of string | N | 可用的選項群組 group_id |
| combo_components | array of ComboComponent | N | 僅 COMBO 使用 |
ComboComponent¶
| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
| product_id | string | Y | 內含品項的 product_id |
| quantity | decimal string | Y | 數量 |
| is_substitutable | boolean | Y | 是否可替換 |
| substitute_group_id | string | 條件 | is_substitutable = true 時必填,指向可替換選項的 group_id |
ModifierGroup¶
| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
| group_id | string | Y | 選項群組代碼 |
| name | localized text | Y | 群組名稱 |
| min_select | integer | Y | 最少選幾個(0 = 選填) |
| max_select | integer | Y | 最多選幾個(≥ min_select) |
| options | array of ModifierOption | Y | 至少 1 個 |
ModifierOption¶
| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
| option_id | string | Y | 選項代碼;若等於某個 product_id(例飲料升級 DRK-BOBA),表示選了該商品 |
| name | localized text | Y | 選項名稱 |
| price_delta | decimal string | Y | 加價(可為 "0.00") |
| is_default | boolean | N | 是否為預設選項,預設 false |
範例¶
{
"batch_id": "9c4b2a77-0d1e-4f3a-b5c6-7d8e9f0a1b2c",
"products": [
{
"product_id": "COMBO-02",
"store_id": null,
"name": { "en-US": "Master Jimbo Combo" },
"category_id": "COMBO",
"unit_price": "14.49",
"currency": "USD",
"tax_category": "STANDARD",
"status": "ACTIVE",
"product_type": "COMBO",
"modifier_group_ids": ["FLAVOR_JIMBO", "COMBO_DRINK"],
"combo_components": [
{ "product_id": "SGL-JIMBO", "quantity": "1", "is_substitutable": false },
{ "product_id": "SIDE-FRIES", "quantity": "1", "is_substitutable": false },
{ "product_id": "DRK-FOUNTAIN", "quantity": "1", "is_substitutable": true, "substitute_group_id": "COMBO_DRINK" }
],
"version": 1,
"last_modified_at": "2026-10-14T10:00:00-07:00"
},
{
"product_id": "SIDE-FRIES",
"name": { "en-US": "Fries" },
"unit_price": "4.49",
"currency": "USD",
"tax_category": "STANDARD",
"status": "ACTIVE",
"product_type": "SIDE",
"modifier_group_ids": ["FRIES_EXTRA_FLAVOR"],
"version": 1,
"last_modified_at": "2026-10-14T10:00:00-07:00"
}
],
"modifier_groups": [
{
"group_id": "FRIES_EXTRA_FLAVOR",
"name": { "en-US": "Add Extra Flavor" },
"min_select": 0,
"max_select": 2,
"options": [
{ "option_id": "SEAWEED", "name": { "en-US": "Seaweed" }, "price_delta": "0.75" },
{ "option_id": "CHEESE_POWDER", "name": { "en-US": "Cheese Powder" }, "price_delta": "0.75" }
]
},
{
"group_id": "COMBO_DRINK",
"name": { "en-US": "Combo Drink" },
"min_select": 1,
"max_select": 1,
"options": [
{ "option_id": "DRK-FOUNTAIN", "name": { "en-US": "Fountain Drinks" }, "price_delta": "0.00", "is_default": true },
{ "option_id": "DRK-TW-LEMONADE", "name": { "en-US": "Taiwan Signature Lemonade" }, "price_delta": "2.50" },
{ "option_id": "DRK-KUMQUAT-LEMONADE", "name": { "en-US": "Kumquat Lemonade" }, "price_delta": "2.50" },
{ "option_id": "DRK-BOBA", "name": { "en-US": "Taiwan Boba Tea" }, "price_delta": "3.50" }
]
}
]
}
Response¶
202 Accepted(record_count 為 products 筆數)
{ "batch_id": "9c4b2a77-0d1e-4f3a-b5c6-7d8e9f0a1b2c", "status": "ACCEPTED", "record_count": 2, "warnings": [] }
同一 batch_id 重送回 200 ALREADY_RECEIVED。
錯誤¶
| HTTP | code | 情況 |
|---|---|---|
| 400 | INVALID_PAYLOAD | 格式、必填、代碼錯誤 |
| 400 | BATCH_TOO_LARGE | 筆數超過上限 |
| 401 | UNAUTHORIZED | 未帶 API 金鑰或金鑰錯誤 |
| 403 | STORE_NOT_ALLOWED | 門市專屬商品的 store_id 不屬於該合作夥伴 |
| 413 | PAYLOAD_TOO_LARGE | 請求本文超過 5 MB |
注意事項¶
Note
- 只送有異動的商品;每次異動請將
version+1。 - 套餐的內含品項(
combo_components)與選項(options)中引用的product_id也應以商品資料送出。 - 交易中套餐與選項的記法見記錄規則。