thru

Go-live checklist

Keys and workspaces

  • Production uses its own workspace. Staging uses a different one, with its own key and webhook endpoints.
  • The production API key, webhook secret and checkout secret live only in your server's secret store: not in a browser bundle, a mobile app or a repository.
  • Someone other than the developer knows how to revoke and replace the key (Console → Developers → API keys).

Money checks in your code

  • Every fulfilment path checks network === "mainnet" (or livemode === true).
  • You grant only after an authenticated read (GET /v1/payments/:id or GET /v1/checkout/sessions/:id), never from the browser, a public endpoint or metadata alone.
  • You check status: confirmed or overpaid for a payment (plus underpaid if you credit partial payments), completed for a session.
  • For variable amounts, you credit receivedAmount with decimal arithmetic, as a high-water mark (credit-topups).
  • For direct payments you validate amounts yourself (minimum, maximum, positive). For a custom-amount product, minAmount and maxAmount are set on the product, and your create path shows the user the minAmount from the 400 body instead of a generic error.
  • Every payment or session create sends an idempotencyKey tied to your own order, and a key is never reused for a different amount.

Chains

  • Every chain and token you offer is marked live in supported-chains, and your allow-list is on the server.
  • You offer stablecoins for dollar prices, not native coins.
  • Your payment screen shows the exact amount, the token and the chain, and warns that the address takes one transfer only.

Webhooks

  • The endpoint is HTTPS and verifies x-thru-signature over the raw body.
  • It records event ids and tolerates duplicates and out-of-order delivery.
  • It answers 2xx only after committing, and 5xx on failure.
  • Its filter matches the events you handle: checkout.* for fixed-price sessions, payment.* for custom-amount sessions and direct payments. If you subscribe to both families, a sale cannot be granted twice.
  • It ignores deliveries with data.test === true.
  • Someone watches for failed and undeliverable events in Developers → Events.

Checkout sessions (if you use them)

  • Your production return origins are registered (Developers → Checkout), using https.
  • Your return page awaits verifyThruReturn and then retrieves the session before granting.
  • You do not create sessions for invoices; the hosted page cannot show them yet.
  • For a custom-amount product, your crediting code reads checkoutSession on the payment, credits receivedAmount as a high-water mark per session, and alerts on a payment that carries no checkoutSession (credit-topups).

Settlement and reconciliation

  • A settlement address is set for every chain and network you accept (Treasury → Settlement). If you accept native SUI, someone withdraws it from Treasury, because it is not forwarded automatically.
  • You receive settlement.* events, or check Treasury, so an address change you did not make is noticed during its cool-down.
  • A reconciliation job re-reads recent unfinished orders every few minutes.
  • Support knows what to do when a customer pays late, pays twice, or pays on the wrong chain (credit-topups, "What happens when…").

A final test

  • One small real payment on each chain you offer, end to end: create, pay, webhook, grant, and funds arriving at your settlement address.