Skip to main content
Redirect is the default hosted-checkout mode: your server creates a session, sends the shopper’s browser to a RadiumOne-hosted page, and RadiumOne redirects back to your site when the checkout reaches a final state.

How it works

  1. The shopper clicks Pay on your site.
  2. Your server calls POST /api/v1/checkout/sessions with your secret key.
  3. RadiumOne Checkout returns checkout_url.
  4. Your server redirects the shopper’s browser to checkout_url.
  5. The shopper enters their card on the hosted page.
  6. RadiumOne Checkout charges the card via the Payments API.
  7. RadiumOne sends your webhook endpoint a payment.captured (or decline/failure) event — confirm the result from here, not from the redirect alone.

Before you begin

You need a secret key (r1sk_…) and a success_url/cancel_url pair on a domain you control. See Sandbox and API keys and Checkout API authentication for how the X-Api-Key header works.
Never use a secret key (r1sk_…) in browser code, mobile apps, or anywhere a shopper can inspect it. Secret keys belong on your server only.

Return URL requirements

success_url and cancel_url must be absolute https:// URLs, up to 2048 characters each — http://localhost is also accepted, for local development. Anything else, including a URL that doesn’t parse at all, is rejected at create with 400 validation:invalid_input. The host is also checked against your account’s allowed_domains — an exact match, or a subdomain of a configured domain; any host is accepted if you haven’t configured an allow-list, and a host outside the list returns 403 security:domain_not_allowed.
If you configure allowed_domains, wildcard entries (for example *.example.com) are accepted when you set them but are never matched against a request — they don’t grant access to any subdomain. List every exact host you use explicitly.

Steps

1

Create a checkout session

Call the create-session endpoint from your server with the order amount, currency, your own order_reference, and the pages to return to.
Sending the same order_reference again within the session’s TTL returns the existing session instead of creating a duplicate — safe to retry on a network error.
The replay match is on order_reference alone. If the amount and currency match the original session — and that session is still payable (pending and not yet expired, processing, or completed) — you get the same session back; other changed fields (line items, metadata, URLs) are silently ignored. If the amount or currency is different while that session is still payable, the retry is rejected instead with 409 session:idempotency_conflict — it never silently applies the new total. Either way, this protection only lasts the session’s TTL (5–60 minutes): once it expires, the same order_reference creates a new session, which can mean a second charge if the shopper’s order already paid. Always check your own order state before creating a session — see Prevent duplicate payments.
See Prevent duplicate sessions and double payments for the race case and for retrying after a decline.
2

Redirect the shopper

Redirect the shopper’s browser (HTTP redirect or a client-side navigation) to data.checkout_url from the response. Don’t fetch or embed this URL — it’s a full page for the shopper to visit directly.
3

Handle the success return

When the payment completes, RadiumOne redirects the shopper to your success_url with checkout_id (and state, if you sent one). If you’ve configured a redirect secret, the URL also carries status, transaction_id, ts, and sig — see Verify the payment result before treating this as anything more than a UX signal.
Serve success_url with Referrer-Policy: no-referrer, and avoid loading third-party scripts on it. The query string can carry transaction_id and sig — anything that reads the URL or receives a Referer header from this page can see them.
Treat any client-side redirect or callback as a hint only. Always confirm the final payment status from your server, using an authenticated GET request or a webhook — never from a query parameter or browser postMessage alone.
4

Handle the cancel return

Three different outcomes all return the shopper to your raw cancel_url — none of them carry checkout_id or state, so you can’t tell them apart from the query string alone:Put your own order reference in the cancel_url itself (for example cancel_url=https://shop.example.com/pay/cancel?order=ORD-1024) so you can correlate the return without relying on query params RadiumOne doesn’t send on this path.Always re-check the session status from your server before deciding an order failed — see the next step.

Handle the result

Never fulfil an order from the redirect URL alone. Confirm the outcome with an authenticated GET request or a webhook — see Verify the payment result for the full decision table.

Test your integration

See Test your integration for sandbox scenarios covering approvals, declines, timeouts, and cancellations.

Go-live notes

  • Register your production success_url/cancel_url domains if you’ve set allowed_domains.
  • Configure a redirect secret so success returns are signed — see Verify the payment result.
  • Set up your webhook endpoint before going live; it’s the authoritative source of truth, not the redirect.
See the full go-live checklist.

Next steps

Verify the payment result

Confirm the outcome server-side before fulfilling.

Session lifecycle

Statuses, TTL, cancellation, and retries.

Handle failures

Ten common failure scenarios and what to do for each.
Last modified on September 15, 2026