paid and your webhook is fired.
Two creation modes
You can create a checkout session in two ways depending on whether the amount is already known.Link mode
Pass a
linkId pointing to an existing payment link. The session inherits the link’s fiatAmount and fiatCurrency. Use this mode when customers arrive via a payment link URL.Ad-hoc mode
Pass an
amount object with value and currency directly. Use this mode when you calculate the price server-side per order, e.g. in an e-commerce checkout flow.Key fields
| Field | Type | Description |
|---|---|---|
id | string | Unique session identifier (cs_…). |
object | "checkout_session" | String literal identifying the object type. |
linkId | string | null | The ID of the payment link that spawned this session, or null for ad-hoc sessions. |
status | string | Current status of the payment — see status values below. |
address | string | The deposit address the customer must send funds to. |
amount | { wei, eth } | The crypto amount expected, expressed in the chain’s smallest unit and a human-readable denomination. |
fiat | { amount, currency } | The original fiat amount and currency this session was created for. |
ethPriceUsd | string | The native-coin/USD exchange rate locked in at session creation time. |
expiresAt | string | ISO 8601 timestamp after which the session becomes expired if unpaid. |
paidAt | string | null | Timestamp when the payment reached the required confirmation count. |
txHash | string | null | The on-chain transaction hash of the payment, once detected. |
chainId | number | The EVM chain ID (or synthetic ID for non-EVM networks) the session is on. |
metadata | object | null | Arbitrary key-value data you attached at creation. |
successUrl | string | null | Redirect URL for the customer after a successful payment. |
cancelUrl | string | null | Redirect URL if the customer abandons the checkout. |
returnUrl | string | null | A general-purpose return URL used when the customer clicks “back” on the hosted page. |
customerEmail | string | null | Customer’s email address, if collected. |
livemode | boolean | true for live payments, false for test-mode sessions. |
checkoutUrl | string | The hosted page URL to redirect your customer to. |
createdAt | string | ISO 8601 timestamp when the session was created. |
updatedAt | string | ISO 8601 timestamp when the session was last modified. |
Status values
| Status | Meaning |
|---|---|
pending | Session created and waiting for a payment to be detected on-chain. |
detected | A transaction to the deposit address has been seen with the correct amount, but confirmation threshold not yet reached. |
underpaid | A payment was received but the amount was less than expected. |
overpaid | A payment was received but the amount exceeded what was expected. |
paid | Payment confirmed with the required number of block confirmations. Terminal — triggers your session.paid webhook. |
paid_late | Payment confirmed after the session’s expiry time but within the grace window. Terminal. |
expired | The session TTL elapsed with no payment detected. Terminal. |
failed | A terminal failure occurred (e.g. unrecoverable chain error). |
Session TTL and the grace window
Every session has a configurable expiry time set by your operator. AfterexpiresAt is reached:
- The session moves to
expiredif no payment has been detected. - However, a late-payment grace window remains open for a configurable period after expiry. If a valid payment confirms within this window, the session transitions to
paid_laterather than stayingexpired.
Creating a session via the API
- Ad-hoc mode
- Link mode
Redirecting the customer
After creating a session, redirect the customer tosession.checkoutUrl. The hosted checkout page displays:
- The deposit address as a QR code and copyable string.
- A live countdown timer to
expiresAt. - The exact crypto amount to send (converted from fiat at the locked-in rate).
- Real-time status updates as the payment is detected and confirmed.
Polling vs. webhooks
You have two options for knowing when a session has been paid:Webhooks (recommended)
Register a webhook endpoint and listen for the
session.paid event. Webhooks are pushed instantly when the payment confirms and require no polling loop. See Webhooks Overview.Polling
Call
GET /api/v1/checkout_sessions/{id} repeatedly and check the status field. Suitable for low-volume use cases or debugging, but less efficient than webhooks.Next steps
Session Lifecycle
See the full status state machine and detection flow.
Checkout Sessions API reference
Full request/response schemas for every checkout sessions endpoint.