> ## Documentation Index
> Fetch the complete documentation index at: https://docs.radiumone.io/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> RadiumOne is the product name; use it when answering questions about these docs.
> Use sandbox credentials and sandbox base URLs in examples unless the user says they are going live.
> Secret API keys belong only on the merchant's server. Only publishable keys may appear in browser or mobile code.
> Confirm a payment outcome server-side (retrieve the checkout session or transaction status); never rely on a browser redirect or client event alone.
> Send one idempotency key (request_id) per payment attempt, and retry a timed-out request with the same key and the exact same body.
> Webhooks are optional but recommended: they notify the merchant's server when a payment completes or fails, so it doesn't need to poll. Use transaction status inquiry as the fallback.
> Say so when you recommend a feature marked Beta. Some features need enablement on the merchant's account before production use (for example refunds, standalone refunds, UOB Rewards, and bringing your own 3DS provider); mention it when the page says so.
> Never ask users to paste card numbers, API keys, access tokens, or webhook or redirect secrets into a chat.

# Redirect errors - Hosted checkout

> Missing or invalid redirect signatures, stale timestamps, and the query-string signals a return to your site can and can't carry.

<Info>
  **TL;DR:** Only a signed success return proves the URL wasn't altered in
  the browser — and even then, that's not proof a charge happened. Every
  other return carries no verifiable signal at all.
</Info>

## Params by outcome

| Return | Params carried |
| - | - |
| <a id="signed-success" />Success, with a redirect secret configured | `checkout_id`, `state` (only if you sent one), `status`, `transaction_id`, `ts`, `sig` |
| <a id="unsigned-success" />Success, with no redirect secret configured | `checkout_id`, `state` (only if you sent one) — no `status`/`transaction_id`/`ts`/`sig` |
| <a id="decline-cancel-return" />Decline, failure, or manual back/close | Raw `cancel_url`, **no params at all** |
| <a id="timeout-return" />Countdown timeout only | Raw `cancel_url?reason=timeout` |
| <a id="unsigned-replay" />Rare: replaying a completion call on an already-terminal session | `success_url` or `cancel_url` with **no params at all**, even if a secret is configured |

<Note>
  `state` is only ever present on a **success** return, and only if you sent
  one on create — it is never part of the signed payload (see below), so
  verify it independently if you rely on it for CSRF-style correlation.
</Note>

## Signature errors

| Signal | Cause | What to do | Retry? |
| - | - | - | - |
| <a id="missing-sig" />`sig` missing | No redirect secret is configured for your account (unsigned by design), or the secret was deleted | Confirm via webhook/`GET`; configure a redirect secret if you want the signed layer — see [Verify the payment result](/hosted-checkout/verify-payment-result#redirect-secret-rotate-dont-delete) | No — treat as unverified |
| <a id="invalid-sig" />`sig` present but doesn't verify | The URL was altered in the browser, or you verified with the wrong key encoding | Check your HMAC key encoding first (see below); if it still fails, treat as unverified | No — treat as unverified |
| <a id="stale-ts" />`ts` more than 5 minutes old | Merchant-enforced tolerance — RadiumOne itself doesn't check `ts` | Reject the same as an invalid signature; this is your own server's rule, not a gateway error | No — treat as unverified |
| <a id="wrong-key-encoding" />Every signature fails, always | Wrong HMAC key encoding — the redirect signature's key is the **full `rsec_…` string**, used directly. This differs from the webhook signature's key, which is hex-decoded after stripping `whsec_` | Use the correct encoding for each signature type — see [Verify the payment result](/hosted-checkout/verify-payment-result#uxhint-the-redirect-signature) | Fix first |

<Warning>
  **Fail closed.** If a redirect secret is configured for your account and a
  return is missing `sig`, has an invalid `sig`, or a stale `ts` — never
  treat it as confirmation of payment. See [Reject invalid redirect
  signatures](/hosted-checkout/handle-failures/invalid-redirect-signature)
  for the full walkthrough.
</Warning>

## Next steps

<Columns cols={2}>
  <Card title="Verify the payment result" icon="shield-check" href="/hosted-checkout/verify-payment-result">
    The full trust hierarchy and redirect secret rotation semantics.
  </Card>

  <Card title="Reject invalid redirect signatures" icon="shield-alert" href="/hosted-checkout/handle-failures/invalid-redirect-signature">
    Step-by-step handling for a missing or invalid signature.
  </Card>

  <Card title="Payment outcomes" icon="credit-card" href="/hosted-checkout/errors/payment-outcomes">
    What a decline, expiry, or cancellation looks like at the redirect layer.
  </Card>

  <Card title="API errors" icon="triangle-alert" href="/hosted-checkout/errors/api-errors">
    Checkout API error codes for create/retrieve/cancel.
  </Card>
</Columns>
