How money flows
- 1Your backend POSTs usage events as they happen — one per metered action.
- 2Monthly cron groups events by (customer, contract) and locks an FX snapshot.
- 3The cron emits an invoice — subtotal in pricing currency, collection amount in CNY.
- 4Merchant or end-customer hits the checkout endpoint; we mint a payment order against WeChat / Alipay.
- 5Consumer pays. Channel webhook arrives. We post the CNY collection + FX conversion to the append-only ledger.
- 6End of month, finance closes a settlement batch — two-admin approval, FX-cleared payout in your settlement currency.
Object glossary
Usage event
One metered action — tokens, agent run, image, GB-day. Carries metric, quantity, customerExternalId, idempotencyKey, occurredAt.
Customer
Your end-user. We don't process their identity — just hold the externalId you reference.
Product + rate card
Product is the thing you sell. Rate card binds metrics → unit size → unit price minor. Versioned + locked into invoices.
Contract
Binds (customer, product, rate card) with a billing cycle. Usage events attach automatically via the customer.
FX snapshot
Locked exchange rate at invoice generation time. Same snapshot is used to compute CNY collection + USD net settlement.
Invoice
Subtotal in pricing currency, collection in CNY, fee, net settlement. Transitions: draft → finalized → paid (or void / refunded).
Payment order
One per checkout attempt. Lives on WeChat or Alipay side. Channel webhook flips status to paid / failed / refunded.
Ledger entry
Append-only double-entry record. Each transaction (collection, fee, FX, payout) has matched debit + credit rows.
Settlement batch
Monthly close per settlement currency. Two-admin approval, then FX-cleared transfer to your bank.
Invariants
- Every business row carries merchantId — multi-tenant isolation at the data layer.
- All monetary amounts are bigint serialized as strings in minor units.
- FX rates are decimal strings; never JS floats.
- Ledger entries are append-only; balance is SUM(credit) − SUM(debit), never patched.
- Idempotency keys dedupe usage events; (merchantId, idempotencyKey) is unique.