交易推送¶
POST /trade-records
交易批次推送。同一門市同一營業日可分多批送出,每批使用不同的 batch_id,batch_seq 依序遞增。
權限¶
API 金鑰(x-functions-key)
Request¶
| Header | 必填 | 說明 |
|---|---|---|
| x-functions-key | Y | {api_key} |
| Content-Type | Y | application/json |
Body
| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
| batch_id | UUID | Y | 冪等鍵 |
| store_id | string | Y | 門市代碼;須為總部登記給合作夥伴的門市 |
| business_date | date | Y | 營業日 |
| batch_seq | integer | Y | 該門市該營業日的批次序號,從 1 開始 |
| trade_records | array of TradeRecord | Y | 1~500 筆;每筆的 store_id、business_date 須與外層相同 |
TradeRecord¶
| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
| trade_record_id | string | Y | 交易代碼,合作夥伴內唯一 |
| version | integer | Y | 正整數,同一筆交易每次異動 +1 |
| store_id | string | Y | 須與外層相同 |
| business_date | date | Y | 原交易營業日,須與外層相同 |
| source_transaction_type | string | Y | 合作夥伴原始交易代碼,須已在對照表中(未對照仍收,但補上對照前不計入報表) |
| order_type | enum | Y | 訂單類型(取餐方式),見代碼表 |
| order_source | string | N | 下單管道。建議使用代碼表的值,但允許自由字串(最長 50 字元) |
| order_source_detail | string | N | 管道細項,例平台名稱 UBER_EATS、DOORDASH、FOODPANDA;自由字串,最長 50 字元 |
| status | enum | Y | OPEN / COMPLETED / VOIDED / REFUNDED / PARTIALLY_REFUNDED |
| opened_at | timestamp | Y | 開單時間 |
| closed_at | timestamp | null | N | 結帳時間;OPEN 時為 null |
| currency | string | Y | ISO 4217,須與門市幣別相同 |
| prices_include_tax | boolean | Y | 本筆金額是否含稅 |
| subtotal_amount | decimal string | Y | 品項金額小計(未扣折扣) |
| discount_amount | decimal string | Y | 整單折扣(正數表示折抵金額) |
| tax_amount | decimal string | Y | 稅額 |
| service_charge_amount | decimal string | Y | 服務費 |
| tip_amount | decimal string | Y | 小費 |
| rounding_amount | decimal string | Y | 尾數調整(可為負) |
| total_amount | decimal string | Y | 總額,見金額恆等式 |
| original_trade_record_id | string | null | N | 退貨/退款/換貨時,指向原交易 |
| fiscal_document_no | string | null | N | 發票/稅務單據號碼(依各國法規) |
| employee_id | string | N | 員工代碼(不得含姓名) |
| guest_count | integer | N | 來客數 |
| member_id | string | null | N | 會員代碼(合作夥伴會員系統的 ID),非會員時為 null 或省略;最長 50 字元。見會員規則 |
| last_modified_at | timestamp | Y | 最後異動時間 |
| items | array of TradeItem | Y | 至少 1 筆 |
| payments | array of Payment | Y | 可為空陣列(例作廢、開錢櫃未交易) |
| tax_lines | array of TaxLine | N | 稅額明細 |
TradeItem¶
| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
| line_no | integer | Y | 行號,交易內唯一,從 1 開始 |
| parent_line_no | integer | null | N | 套餐子品項指向套餐列的 line_no;一般品項為 null |
| product_id | string | Y | 商品代碼;套餐子品項記實際選到的商品 |
| product_name | string | Y | 交易當下的商品名稱(POS 顯示語系) |
| product_type | enum | Y | SINGLE / COMBO / SIDE / DRINK / MODIFIER |
| quantity | decimal string | Y | 數量;退貨/退款交易與換貨的退回列填負數(見記錄規則) |
| unit_price | decimal string | Y | 單價,已含 modifiers 加價;套餐子品項為 "0.00" |
| discount_amount | decimal string | Y | 品項折扣 |
| line_amount | decimal string | Y | quantity × unit_price − discount_amount |
| tax_category | enum | N | STANDARD / REDUCED / ZERO / EXEMPT |
| modifiers | array of TradeModifier | Y | 可為空陣列 |
| is_voided | boolean | Y | 是否已刪除(結帳前刪除的品項) |
TradeModifier¶
| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
| group_id | string | Y | 選項群組代碼 |
| option_id | string | Y | 選項代碼 |
| option_name | string | N | 交易當下的選項名稱 |
| quantity | decimal string | Y | 數量 |
| price_delta | decimal string | Y | 加價 |
Payment¶
| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
| payment_id | string | Y | 付款代碼,合作夥伴內唯一 |
| payment_type | string | Y | 收付款性質。建議使用代碼表的值,但允許自由字串(最長 50 字元);SALE、REFUND 為必須支援的基本值 |
| payment_method | enum | Y | 付款工具,見代碼表(點數、禮物卡等屬於付款工具,記在這裡) |
| payment_method_detail | string | N | 細項,例 VISA、APPLE_PAY |
| card_last4 | string | N | 卡號末四碼,僅限 4 碼數字 |
| amount | decimal string | Y | 付款金額(含小費),一律填正數,收付方向由 payment_type 決定;現金付款填找零後的實收金額 |
| tip_amount | decimal string | N | 其中小費金額 |
| paid_at | timestamp | Y | 付款時間 |
| original_payment_id | string | null | N | 退款/作廢時指向原付款 |
TaxLine¶
| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
| tax_code | string | Y | 稅別代碼(合作夥伴/各國定義),例 US_SALES |
| tax_rate | decimal string | Y | 稅率,小數表示,例 "0.09" |
| taxable_amount | decimal string | Y | 課稅基礎 |
| tax_amount | decimal string | Y | 稅額 |
| is_inclusive | boolean | Y | 是否為內含稅 |
範例¶
一筆 Jimbo 套餐選麻辣口味+單點薯條加起司粉,外加稅 9%、小費 3.00:
{
"batch_id": "0b8d6c1e-1111-4a2b-9c3d-222233334444",
"store_id": "US001",
"business_date": "2026-10-14",
"batch_seq": 1,
"trade_records": [
{
"trade_record_id": "A100231",
"version": 1,
"store_id": "US001",
"business_date": "2026-10-14",
"source_transaction_type": "Sale",
"order_type": "DINE_IN",
"order_source": "POS",
"status": "COMPLETED",
"opened_at": "2026-10-14T18:05:12-07:00",
"closed_at": "2026-10-14T19:02:40-07:00",
"currency": "USD",
"prices_include_tax": false,
"subtotal_amount": "19.73",
"discount_amount": "0.00",
"tax_amount": "1.78",
"service_charge_amount": "0.00",
"tip_amount": "3.00",
"rounding_amount": "0.00",
"total_amount": "24.51",
"original_trade_record_id": null,
"fiscal_document_no": null,
"employee_id": "E017",
"guest_count": 1,
"member_id": "M00012345",
"last_modified_at": "2026-10-14T19:02:40-07:00",
"items": [
{ "line_no": 1, "parent_line_no": null, "product_id": "COMBO-02", "product_name": "Master Jimbo Combo", "product_type": "COMBO",
"quantity": "1", "unit_price": "14.49", "discount_amount": "0.00", "line_amount": "14.49", "tax_category": "STANDARD",
"modifiers": [ { "group_id": "FLAVOR_JIMBO", "option_id": "MALA", "option_name": "Mala Hot Sauce", "quantity": "1", "price_delta": "0.00" } ],
"is_voided": false },
{ "line_no": 2, "parent_line_no": 1, "product_id": "SGL-JIMBO", "product_name": "Master Jimbo", "product_type": "SINGLE",
"quantity": "1", "unit_price": "0.00", "discount_amount": "0.00", "line_amount": "0.00", "tax_category": "STANDARD",
"modifiers": [], "is_voided": false },
{ "line_no": 3, "parent_line_no": 1, "product_id": "SIDE-FRIES", "product_name": "Fries", "product_type": "SIDE",
"quantity": "1", "unit_price": "0.00", "discount_amount": "0.00", "line_amount": "0.00", "tax_category": "STANDARD",
"modifiers": [], "is_voided": false },
{ "line_no": 4, "parent_line_no": 1, "product_id": "DRK-FOUNTAIN", "product_name": "Fountain Drinks", "product_type": "DRINK",
"quantity": "1", "unit_price": "0.00", "discount_amount": "0.00", "line_amount": "0.00", "tax_category": "STANDARD",
"modifiers": [], "is_voided": false },
{ "line_no": 5, "parent_line_no": null, "product_id": "SIDE-FRIES", "product_name": "Fries", "product_type": "SIDE",
"quantity": "1", "unit_price": "5.24", "discount_amount": "0.00", "line_amount": "5.24", "tax_category": "STANDARD",
"modifiers": [ { "group_id": "FRIES_EXTRA_FLAVOR", "option_id": "CHEESE_POWDER", "option_name": "Cheese Powder", "quantity": "1", "price_delta": "0.75" } ],
"is_voided": false }
],
"payments": [
{ "payment_id": "P500881", "payment_type": "SALE", "payment_method": "CREDIT_CARD", "payment_method_detail": "VISA",
"card_last4": "4242", "amount": "24.51", "tip_amount": "3.00", "paid_at": "2026-10-14T19:02:40-07:00", "original_payment_id": null }
],
"tax_lines": [
{ "tax_code": "US_SALES", "tax_rate": "0.09", "taxable_amount": "19.73", "tax_amount": "1.78", "is_inclusive": false }
]
}
]
}
驗算:subtotal 14.49 + 5.24 = 19.73;total = 19.73 − 0.00 + 1.78 + 0.00 + 3.00 + 0.00 = 24.51。
Response¶
202 Accepted
{
"batch_id": "0b8d6c1e-1111-4a2b-9c3d-222233334444",
"status": "ACCEPTED",
"record_count": 1,
"warnings": []
}
金額恆等式不符時仍會收下,並在 warnings 列出:
{
"batch_id": "0b8d6c1e-1111-4a2b-9c3d-222233334444",
"status": "ACCEPTED",
"record_count": 200,
"warnings": [
{ "code": "AMOUNT_MISMATCH", "path": "trade_records[17]", "message": "total_amount 24.51 != computed 24.50" }
]
}
| warnings 欄位 | 說明 |
|---|---|
| code | 警告代碼,例 AMOUNT_MISMATCH |
| path | 發生位置 |
| message | 英文說明 |
同一 batch_id 重送回 200 ALREADY_RECEIVED。
伺服器端驗證¶
| 檢查 | 不通過時 |
|---|---|
| 型別、必填、enum、金額字串格式、小數位數符合幣別 | 400 INVALID_PAYLOAD |
每筆 store_id、business_date 與外層一致 |
400 INVALID_PAYLOAD |
store_id 為總部登記給合作夥伴的門市 |
403 STORE_NOT_ALLOWED |
| 筆數不超過上限 | 400 BATCH_TOO_LARGE |
| 金額恆等式 | 不拒收,回應 warnings 列出 |
未知 product_id、未對照的 source_transaction_type |
不拒收,總部待主檔/對照表到齊後重新對應 |
錯誤¶
| HTTP | code | 情況 |
|---|---|---|
| 400 | INVALID_PAYLOAD | 格式、必填、代碼、小數位數錯誤,或 store_id/business_date 與外層不一致 |
| 400 | BATCH_TOO_LARGE | 筆數超過上限 |
| 401 | UNAUTHORIZED | 未帶 API 金鑰或金鑰錯誤 |
| 403 | STORE_NOT_ALLOWED | store_id 不屬於該合作夥伴 |
| 413 | PAYLOAD_TOO_LARGE | 請求本文超過 5 MB |
| 429 | RATE_LIMITED | 超過呼叫頻率上限 |