Accounting Export
The accounting export API provides a reconciliation-ready view of orders, payments, settlements, and refunds — designed for automated bookkeeping against payment-provider (e.g. Airwallex) bank settlements.
Endpoints
Section titled “Endpoints”GET /api/v1/accounting/ordersPOST /api/v1/accounting/sync-settlementsAuth: API key (not JWT). The export requires scope exports:read (or
the read wildcard); the settlement sync requires exports:write (or
write/admin). See API keys for how scopes work.
GET /accounting/orders
Section titled “GET /accounting/orders”Query parameters:
| Parameter | Description |
|---|---|
since | ISO-8601; inclusive lower bound on updated_at. Incremental pulls re-emit status changes (pending→settled, new refunds). |
until | ISO-8601 inclusive upper bound on updated_at |
cursor | Opaque pagination cursor from next_cursor (keyset on (updated_at, id)) |
test | all (default) / only / exclude — test-mode orders |
payment_status | Filter payment attempts: pending / succeeded / failed / cancelled / refunded |
limit | Page size (default 200, max 1000) |
Response shape — data[] with next_cursor:
Each order includes:
order_id— stable store-prefixed reference (SHOP-1001,SHOP-1002), taken from the order’sinvoice_number. It matches the Xero invoice number and theorder_idembedded in payment-provider metadata.store— store name from[accounting] store_name(falls back to the configured branding name).test— boolean; test-mode transactions (these can still move real money and must be bookable).items[]— SKU, name, qty, unit price.payments[]— one entry per payment attempt: provider IDs (intent_id= thepi_…intent,attempt_id= theftx_…attempt), status (pending|succeeded|failed|cancelled), grossamount, itemisedfee.components[],net, and — once settled —settlement_id,settled_at,settlement_currency, andfx_rate.refunds[]— each linked to its parentattempt_id, with status andsettled_at.
Reconciliation invariant
Section titled “Reconciliation invariant”Payment providers settle charges in batches. The join key is
settlement_id:
The sum of
netover all succeeded payments sharing asettlement_idequals one deposit on the provider statement, to the cent.
If a charge has settlement_id: null, it has not settled yet — exclude it
from deposit matching and re-pull after settled_at advances.
POST /accounting/sync-settlements
Section titled “POST /accounting/sync-settlements”Backfills fees and settlement batch IDs onto payments (and settled_at
onto refunds) by pulling Airwallex pa/settlement_records.
{ "limit": 500 }limit— maximum number of unsettled payment intents to query (0or omitted = all). Use a bounded limit if you have a large backlog.- Returns
{ queried, payments_updated, refunds_updated, not_settled, unmatched }.
Requires Airwallex to be configured; otherwise returns
400 {"error": "Airwallex is not configured"}.
Configuration
Section titled “Configuration”[accounting]store_code = "SHOP" # short code in invoice/order references and provider metadatastore_name = "My Shop" # store label in accounting exportssite_url = "https://shop.example.com" # embedded in payment-provider metadataExample
Section titled “Example”curl -H "Authorization: Bearer ak_1a2b3c4d.x9y8..." \ "https://api.shop.example.com/api/v1/accounting/orders?since=2026-10-01T00:00:00Z&test=exclude"Create a key for the automation (secret shown once):
rcommerce api-key create --name "accounting-export" --scopes "exports:read,exports:write"