Tab Docs

Checkout states

Every state the embedded checkout can show, and the real event that drives each transition.

The checkout is a 16-stage state machine (checkout-state.ts in the SDK). Transitions fire on real events — API responses, on-chain reads, settlement reports — never on timers pretending to be progress.

The happy path

Idle → intent loading

The trigger button shows your amount. Clicking it loads the signed intent from your server and opens the payment.

Email → one-time code

The buyer enters an email and receives a 6-digit code. Codes auto-submit on the 6th digit. Returning buyers with a live session skip this entirely (silent resume).

Device approval (conditional)

A new device may require an email approval link. The checkout waits and continues automatically — this is a real state, not a failure.

Balance

The buyer's balance is read for real — Base Sepolia USDC in test mode, the Universal Account total in live mode — and compared to the amount.

Confirming → success

On confirmation the payment executes (test: simulated settlement on the test tenant; live: gated until the money-mover spike is verified). Success shows a receipt with a reference code and a stamped 402 → 200.

The honest edges

StateWhenWhat the buyer sees
insufficientBalance below amountExact shortfall; in test mode, an in-flow test funds grant
add-fundsBuyer opts to top upTheir real deposit address + balance recheck
device-approvalNew device"Approve from your inbox" — continues automatically
stuckConfirming exceeded 20s"Still working — money may be in flight." Never claims failure while a transaction may exist
errorKnown pre-broadcast failure"Nothing has been charged" — only promised when provably true

The checkout only says "Nothing has been charged" for failures known to happen before broadcast. After broadcast, it says what it knows and keeps reconciling — an honest "in flight" beats a comforting lie.

On this page