pending and ends in one of four terminal states: paid, paid_late, expired, or failed. Between those bookends, a status machine driven by on-chain events and a configurable confirmation threshold governs exactly how and when the session advances. Understanding this lifecycle helps you build reliable integrations and handle edge cases like underpayments, block reorgs, and late payments.
Status reference
| Status | Terminal? | Description |
|---|---|---|
pending | No | Session created. Waiting for a transaction to be detected on the deposit address. |
detected | No | A transaction with the correct amount has appeared on-chain. Waiting for the confirmation threshold to be reached. |
underpaid | No | A transaction was received, but the amount sent was less than expected. Merchant review required. |
overpaid | No | A transaction was received, but the amount sent was more than expected. Merchant review required. |
paid | Yes | The exact (or overpaid) amount has been confirmed with the required number of block confirmations. Triggers the session.paid webhook. |
paid_late | Yes | Payment confirmed after the session’s expiresAt timestamp but within the late-payment grace window. |
expired | Yes | The session TTL elapsed with no payment detected. |
failed | Yes | A terminal, unrecoverable error occurred. |
An
underpaid session does not automatically expire or become paid. It stays in underpaid until you take action in the dashboard. No automatic refund or top-up is attempted.The detection flow
When a customer sends crypto to the deposit address, here is what happens internally:Session created — unique deposit address derived
When the session is created, a deterministic deposit address is derived for it. EVM chains share the same address space (the same derived key works across all EVM networks), so the address is the same regardless of which EVM chain the customer uses — detection is scoped by
chainId and asset.Customer sends crypto to the address
The customer scans the QR code or copies the address from the hosted checkout page and broadcasts a transaction from their wallet.
On-chain activity detected in real time
Crypto Checkout subscribes to address-activity notifications for the deposit address. As soon as the transaction appears in the mempool or in a new block, a notification is pushed to the server in real time — no polling required.
Payment verified and amount classified
The server reads the received amount and compares it to the session’s expected
amount.wei. The result is one of:- Exact → status advances to
detected - Underpaid → status advances to
underpaid - Overpaid → status advances to
overpaid
Confirmations reach threshold — session finalized
Once the transaction accumulates the required number of block confirmations (configured by your operator), the session is finalized:
detectedoroverpaid→paid(orpaid_lateifexpiresAthas passed)underpaid→ remainsunderpaid(requires merchant action)
session.paid (or session.paid_late) webhook is dispatched to your registered endpoint.State machine rules
The following table summarizes every valid transition. Any event applied to a status not listed in the “From” column is a no-op — the status does not change.| From | Event | To |
|---|---|---|
pending | Payment detected — exact amount | detected |
pending | Payment detected — underpaid | underpaid |
pending | Payment detected — overpaid | overpaid |
pending | TTL elapsed | expired |
expired | Payment detected (within grace window) — exact | detected |
expired | Payment detected (within grace window) — underpaid | underpaid |
expired | Payment detected (within grace window) — overpaid | overpaid |
detected | Confirmations reached — before expiresAt | paid |
detected | Confirmations reached — after expiresAt | paid_late |
overpaid | Confirmations reached — before expiresAt | paid |
overpaid | Confirmations reached — after expiresAt | paid_late |
detected / overpaid / underpaid | Block reorg detected | pending |
Confirmations
The required confirmation count is configurable per deployment. A higher threshold increases security against double-spend attacks but increases the time customers wait forpaid status. Lower-value transactions can safely use fewer confirmations; high-value transactions should use more.
You can see the confirmation count progress in real time on the hosted checkout page. The session stays in detected (or overpaid) until the threshold is reached.
Late payments and the grace window
After a session’sexpiresAt timestamp passes, the hosted checkout page shows an expiry message. However, the server continues monitoring the deposit address for a configurable grace window. If a payment arrives and confirms within this grace window, the session moves to paid_late instead of remaining expired.
Underpaid and overpaid sessions
Sessions inunderpaid or overpaid require your attention:
- Underpaid: the customer did not send enough. The dashboard shows the shortfall. You can contact the customer to request the difference, or cancel the order and arrange a refund.
- Overpaid: the customer sent too much. The payment is still treated as successful once confirmations are reached (
paidorpaid_late), but you should consider issuing a partial refund for the excess.
underpaid / overpaid.
Manual payment check
If you believe a payment has been made but the session has not advanced (e.g. a notification was delayed), you can trigger an on-chain scan manually:- Open the session in Dashboard → Sessions.
- Click the Check payment button.
Next steps
Webhooks Overview
Set up webhook endpoints to receive real-time
session.paid notifications.Webhook Event Types
Full reference for every event type Crypto Checkout can deliver.