TL;DR: None of these are Checkout API errors — they’re terminal session outcomes. The redirect alone can’t tell them apart; confirm with a webhook or authenticated
GET.completed terminal states.
Each looks similar (or identical) at the redirect layer, which is why you
always confirm the outcome server-side rather than branching on the return
URL. See Session lifecycle for the
full state model and Verify the payment result
for the trust hierarchy behind this page.
Outcomes
Why a decline isn’t an error
The Checkout API — like the Payments API underneath it — treats a decline as a normal, successful response: the gateway reached the issuer and got a “no.” For the acquirer response code behind a decline, how to branch on it safely, and what to tell the shopper, see Decline codes (Payments API — the single source for decline codes, since hosted checkout uses the same gateway underneath). For the full set of gateway transaction statuses (CAPTURED,
FAILED, VOIDED, and so on) that a webhook or GET can report, see
Payment lifecycle.
Starting a new attempt
Every outcome on this page is terminal for that session — none can be retried in place.- Declined or failed: create a new session with a new
order_referenceto let the shopper try again. Reusing the sameorder_referencereturns the same terminal session, not a new attempt. - Expired: you can reuse the same
order_reference— an expired session’s key is no longer idempotency-active, so it creates a genuinely new session. See Session lifecycle § Replay. - Cancelled: same as expired — create a new session when the shopper is ready.
Next steps
API errors
Actual Checkout API error codes — a decline isn’t one of these.
Decline codes
Interpret the issuer’s response code.
Verify the payment result
Confirm the outcome server-side before fulfilling.
Handle failures
Ten common failure scenarios, each with the exact signal and what to do.