Trade Records¶
POST /trade-records
Pushes a batch of transactions for one store and one business date. A business date may be split into several batches, each with its own batch_id.
Authentication: API key (x-functions-key)
Request¶
Request body¶
| Field | Type | Required | Description |
|---|---|---|---|
| batch_id | UUID | Yes | Idempotency key |
| store_id | string | Yes | Store code; must be registered for your account |
| business_date | date | Yes | Business date |
| batch_seq | integer | Yes | Batch sequence number for this store and business date, starting at 1 |
| trade_records | array of TradeRecord | Yes | 1–500 records. Each record's store_id and business_date must match the outer values. |
TradeRecord object¶
| Field | Type | Required | Description |
|---|---|---|---|
| trade_record_id | string | Yes | Transaction ID, unique within your account |
| version | integer | Yes | Positive integer; increase by 1 on every change to this transaction |
| store_id | string | Yes | Must match the outer store_id |
| business_date | date | Yes | Business date of the original transaction; must match the outer value |
| source_transaction_type | string | Yes | Your POS transaction code. Should be in your mapping; unmapped codes are accepted but excluded from reports until mapped. |
| order_type | enum | Yes | How the order is fulfilled. See order types. |
| order_source | string | No | Where the order was placed. Use a suggested code when possible; free strings up to 50 characters are accepted. |
| order_source_detail | string | No | Channel detail, e.g. the platform name UBER_EATS, DOORDASH, FOODPANDA. Free string, up to 50 characters. |
| status | enum | Yes | OPEN / COMPLETED / VOIDED / REFUNDED / PARTIALLY_REFUNDED |
| opened_at | timestamp | Yes | Order opened |
| closed_at | timestamp | null | No | Order closed; null while OPEN |
| currency | string | Yes | ISO 4217; must match the store currency |
| prices_include_tax | boolean | Yes | Whether amounts in this record include tax |
| subtotal_amount | decimal string | Yes | Sum of item amounts before order-level discount |
| discount_amount | decimal string | Yes | Order-level discount (positive = amount taken off) |
| tax_amount | decimal string | Yes | Tax |
| service_charge_amount | decimal string | Yes | Service charge |
| tip_amount | decimal string | Yes | Tip |
| rounding_amount | decimal string | Yes | Rounding adjustment (may be negative) |
| total_amount | decimal string | Yes | Total |
| original_trade_record_id | string | null | No | For returns, refunds and exchanges: the original transaction |
| fiscal_document_no | string | null | No | Invoice / fiscal receipt number, where required by local law |
| employee_id | string | No | Employee code (no names) |
| guest_count | integer | No | Number of guests |
| member_id | string | null | No | Loyalty member ID from your member system; null or omitted for non-members. Up to 50 characters. Must not be a phone number, email or other directly identifying value — see Personal data. |
| last_modified_at | timestamp | Yes | Last change time |
| items | array of TradeItem | Yes | At least 1 item |
| payments | array of Payment | Yes | May be empty (e.g. VOID, NO_SALE) |
| tax_lines | array of TaxLine | No | Tax breakdown |
TradeItem object¶
| Field | Type | Required | Description |
|---|---|---|---|
| line_no | integer | Yes | Line number, unique within the transaction, starting at 1 |
| parent_line_no | integer | null | No | For combo child lines: the combo line's line_no. null for normal lines. |
| product_id | string | Yes | Product code. Combo child lines carry the product actually served. |
| product_name | string | Yes | Product name at the time of sale (POS display language) |
| product_type | enum | Yes | Same values as Product |
| quantity | decimal string | Yes | Quantity. Negative in RETURN/REFUND transactions and for returned lines in an EXCHANGE (rules) |
| unit_price | decimal string | Yes | Unit price including modifier price deltas. "0.00" for combo child lines. |
| discount_amount | decimal string | Yes | Line discount |
| line_amount | decimal string | Yes | quantity × unit_price − discount_amount |
| tax_category | enum | No | See tax categories |
| modifiers | array of TradeModifier | Yes | May be empty |
| is_voided | boolean | Yes | Whether the line was deleted before checkout |
TradeModifier object¶
| Field | Type | Required | Description |
|---|---|---|---|
| group_id | string | Yes | Modifier group code |
| option_id | string | Yes | Option code |
| option_name | string | No | Option name at the time of sale |
| quantity | decimal string | Yes | Quantity |
| price_delta | decimal string | Yes | Extra charge |
Payment object¶
| Field | Type | Required | Description |
|---|---|---|---|
| payment_id | string | Yes | Payment ID, unique within your account |
| payment_type | string | Yes | Nature of the money movement. Use a suggested code; free strings up to 50 characters are accepted. SALE and REFUND must be supported by every partner. |
| payment_method | enum | Yes | Payment instrument. See payment methods. Points and gift cards are instruments and belong here, not in payment_type. |
| payment_method_detail | string | No | Detail, e.g. VISA, APPLE_PAY |
| card_last4 | string | No | Last four card digits — exactly 4 digits |
| amount | decimal string | Yes | Amount including tip. Always positive; the direction comes from payment_type (only ADJUSTMENT may be negative). For cash, send the amount kept after change. |
| tip_amount | decimal string | No | Tip portion of amount |
| paid_at | timestamp | Yes | Payment time |
| original_payment_id | string | null | No | For refunds and voids: the original payment |
TaxLine object¶
| Field | Type | Required | Description |
|---|---|---|---|
| tax_code | string | Yes | Tax code defined by you / local law, e.g. US_SALES |
| tax_rate | decimal string | Yes | Rate as a fraction, e.g. "0.09" |
| taxable_amount | decimal string | Yes | Taxable base |
| tax_amount | decimal string | Yes | Tax |
| is_inclusive | boolean | Yes | Whether the tax is included in prices |
Example¶
One Master Jimbo Combo with Mala flavor, plus Fries with Cheese Powder; 9% sales tax added on top; $3.00 tip.
{
"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 }
]
}
]
}
Check: subtotal 14.49 + 5.24 = 19.73; total = 19.73 − 0.00 + 1.78 + 0.00 + 3.00 + 0.00 = 24.51.
Validation¶
| Check | If it fails |
|---|---|
| Types, required fields, enums, decimal-string format, decimal places matching the currency | 400 INVALID_PAYLOAD |
Every record's store_id and business_date match the outer values |
400 INVALID_PAYLOAD |
store_id is registered for your account |
403 STORE_NOT_ALLOWED |
| Record count within your batch limit | 400 BATCH_TOO_LARGE |
| Amount identity | Not rejected — listed in warnings |
Unknown product_id or unmapped source_transaction_type |
Not rejected — re-mapped by HQ once master data / mapping arrives |
Response¶
202 Accepted
{
"batch_id": "0b8d6c1e-1111-4a2b-9c3d-222233334444",
"status": "ACCEPTED",
"record_count": 1,
"warnings": []
}
With an amount-identity warning:
{
"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" }
]
}
| Warning field | Description |
|---|---|
| code | Warning code, e.g. AMOUNT_MISMATCH |
| path | Location of the record in the request |
| message | Human-readable detail (may change; do not parse) |
Resending the same batch_id returns 200 with "status": "ALREADY_RECEIVED".
Errors¶
| HTTP | code | When |
|---|---|---|
| 400 | INVALID_PAYLOAD | Validation failed |
| 400 | BATCH_TOO_LARGE | Too many records |
| 401 | UNAUTHORIZED | Missing or invalid API key |
| 403 | STORE_NOT_ALLOWED | Store not registered for your account |
| 413 | PAYLOAD_TOO_LARGE | Body larger than 5 MB |
| 429 | RATE_LIMITED | Too many requests |
Notes¶
202 is not reconciliation
202 Accepted means the batch was received and passed validation. Whether the day is complete and correct is confirmed only by the reconciliation result.
- See Recording Rules for combos, modifiers, exchanges, refunds and corrections.
- After the last batch of the day, send
POST /daily-close.