gateway_response_code — to drive your own logic.
Statuses
pending→processing— the shopper submits payment; a second submission while the first is in flight is rejected.processing→completed/failed— the charge resolves.pending→expired— the TTL elapses before the shopper pays.pending→cancelled— you cancel the session while it’s still pending.processing→pending— the payment service was briefly unreachable; nothing was charged, and the shopper can retry on the same session.- Same
order_reference, same amount and currency, within the session TTL returns this same session as long as it can still be paid (pending,processing, orcompleted) — see Replay and retries below for the full rule, including what happens on a terminal session or a changed amount.
Expiry (TTL)
Setttl_minutes on create (an integer from 5–60). If you omit it, the session uses your environment’s default: 10 minutes in production, 25 minutes in sandbox — sandbox is shorter than production so a session can’t outlive the card token it binds. Since this also bounds how long order_reference deduplicates a retry (see Replay and retries below), set ttl_minutes explicitly rather than relying on the default, especially in production.
A session that reaches its TTL without a completed payment moves to expired. An expired session can’t be paid — create a new session (with a new or the same order_reference, see Replay below) if the shopper wants to try again. See Handle expired checkout sessions for the exact redirect signal and recovery steps.
Retention: a session record exists for its TTL plus a short grace buffer, then is no longer retrievable by
GET. Your own order records — and the gateway’s transaction record, once a charge happens — are the durable source of truth, not the checkout session itself.Merchant cancellation
Cancel a session from your server (for example, if the shopper abandons your cart) with your secret key, via the cancel endpoint:pending — and calling it again on an already-cancelled session is also idempotent. If the session has already moved to processing or another terminal status, the cancel request returns a 409 — you can’t cancel a session that’s already been submitted for payment or already reached a final state. See Resolve checkout cancellation conflicts for the full decision table.
A shopper closing the tab or clicking their browser’s back button does not cancel the session — it stays
pending until it expires. If you need it cancelled immediately, call the cancel endpoint from your own server.Replay and retries
SendingPOST /api/v1/checkout/sessions again with the same order_reference (for the same merchant, within the original session’s TTL) either returns the existing session, rejects the retry, or creates a fresh one — depending on whether the original session can still be paid, and whether the amount and currency match. The table below covers every situation you’ll actually hit:
See Prevent duplicate sessions and double payments for the full walkthrough.
Retrying after a decline, cancellation, or expiry is different: those sessions are terminal, so the reference is released automatically and the next create with the same
order_reference starts a genuinely new session — you don’t need to mint a new order_reference for it to work, though using one keeps your own tracking cleaner. Either way, the shopper can’t retry a card on the old session itself.
Next steps
Verify the payment result
Confirm the outcome server-side before fulfilling.
Customize checkout
Line items, shopper details, branding, and more.
Brand the payment page
Colours, fonts, logo, and light/dark mode.
Handle failures
Ten common failure scenarios and what to do for each.