> ## 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.

# Problem format and retries - Payments API

> The problem+json error shape, HTTP status guide, retry rules, and rate limits shared by the Payments API and Checkout API.

Every error response from either API — Payments or Checkout — uses this
same shape and these same retry rules. Read this page first, then go to
[Payment operation errors](/payments-api/errors/payment-operation-errors)
or [Payment method errors](/payments-api/errors/payment-method-errors) for
the URN catalog itself. For the response envelope and money shapes, see [Request conventions](/get-started/api-basics/request-conventions).

## Problem format

Both the Payments API and the Checkout API return errors as
[RFC 9457](https://www.rfc-editor.org/rfc/rfc9457) `application/problem+json`
bodies:

```json theme={null}
{
  "type": "urn:radiumone:gateway:validation-error",
  "title": "Validation Error",
  "status": 400,
  "detail": "amount.value must match ^\\d{1,12}$",
  "instance": "/v1/transactions/purchase",
  "request_id": "req_a1b2c3d4e5f6"
}
```

`type` is the URN to match against in code — never parse `detail`, which is
a human-readable string that can change. Some errors add extension members
to the body:

| Field | Meaning |
| - | - |
| `code` | An optional short machine-readable code, distinct from `type` |
| `retry_allowed` | Whether retrying with the *same* idempotency key is safe. When explicitly `false`, don't blindly retry |
| `resolution` | On a subset of `409`s: `operator` (needs an operator/support action) or `transient` (clears on its own) |

`retry_after` is **not** a body field — when RadiumOne wants you to wait
before retrying, it's the `Retry-After` HTTP response header (seconds),
most commonly on `429`.

### Validation error details

Most `400 urn:radiumone:gateway:validation-error` responses add an `errors`
array alongside `detail` — one entry per invalid field:

```json theme={null}
{
  "type": "urn:radiumone:gateway:validation-error",
  "title": "Validation Error",
  "status": 400,
  "detail": "body -> amount -> currency: Field required",
  "errors": [
    { "pointer": "/amount/currency", "detail": "Field required", "code": "missing" }
  ]
}
```

| Field | Meaning |
| - | - |
| `pointer` | JSON Pointer to the invalid field in the request body, e.g. `/amount/currency` or `/items/0/name`. An empty string (`""`) means the error concerns the whole request body rather than one field — for example, the body isn't valid JSON |
| `parameter` | Set instead of `pointer` when an invalid query or path parameter caused the failure |
| `code` | Machine-readable error type for this field, e.g. `missing`, `string_too_long`, `value_error` |
| `detail` | Human-readable explanation for this field |

Rely on `pointer`/`parameter` and `code` to drive logic — not the wording of
either `detail` (the top-level one or a field's own), which can change.

**`errors` is present only when the request failed schema validation —
absent on other `400`s.** It's present when the request itself doesn't match
the endpoint's schema: a missing or wrongly typed body field, a value that
breaks a format or length rule, or an invalid query or path parameter. It's
absent when the `400` comes from a business check that runs *after* schema
validation passed — same URN, same status, no `errors` array. Always handle
`errors` being absent rather than assuming every `400
gateway:validation-error` carries one.

## HTTP status guide

| Status | Meaning here | Retry with the same key? |
| - | - | - |
| `200` / `201` | Success — including a **replayed** create-type request, which returns the original result at the same status code | <Badge color="gray">N/A</Badge> already succeeded |
| `400` | `gateway:validation-error` — body failed schema validation | <Badge color="red">No</Badge> fix the body first |
| `401` | Your access token expired or failed verification | <Badge color="green">Yes</Badge> once, after you re-exchange or refresh the token |
| `403` | Your key lacks the scope or outlet binding for this call (or, on the Checkout API, a domain not on your allow-list) | <Badge color="red">No</Badge> fix the key's scope, outlet, or allow-list first |
| `404` | No such resource for your account | <Badge color="red">No</Badge> |
| `409` | Idempotency body mismatch, a duplicate-operation conflict, a batch-state conflict (void/refund), or a Checkout API session race | <Badge color="orange">Depends</Badge> see [Retry rules](#retry-rules) |
| `410` | A token or 3DS ref expired | <Badge color="red">No</Badge> obtain a new one |
| `412` | Checkout API: your account has no active publishable key | <Badge color="red">No</Badge> provision one first |
| `422` | A business rule was violated (capture window, loyalty leg, 3DS ref state, and similar) | <Badge color="red">No</Badge> resolve the condition first |
| `429` | Rate limited | <Badge color="green">Yes</Badge> after `Retry-After` |
| `503` | A dependency (e.g. your 3DS provider) is unreachable | <Badge color="green">Yes</Badge> after a delay |

## Retry rules

**Any 2xx response is a result you must branch on `status`** — never on `response_code` (that's the verbatim host/acquirer code; useful for support tickets, not for your app logic).

| Status | Meaning | What to do |
| - | - | - |
| `AUTHORIZED` | Funds reserved (authorize only) | Capture within the capture window, or void to release |
| `CAPTURED` | Funds captured (purchase, capture, or refund) | Fulfil the order (or process the refund) |
| `VOIDED` | Authorization released | No funds moved |
| `DECLINED` | Issuer or acquirer declined | Final for this attempt — don't retry the same card without a new attempt from the shopper |
| `FAILED` | The transaction didn't complete — the acquirer returned a non-decline error code, or the gateway couldn't place the request. **Not a guarantee that no funds moved** — `VOIDED` and `REVERSED` are the only statuses that positively assert that. | Confirm via `GET /v1/transactions/{id}/status` before retrying, then retry (a genuinely new attempt, not a replay of the same `request_id`) with a **new** `request_id` |
| `PENDING` | Outcome not yet known (async) | Wait for a webhook, or poll `GET /v1/transactions/{id}/status` |
| `AUTH_EXPIRED` | Authorization lapsed before capture | Create a new authorization |
| `REVERSAL_PENDING` / `REVERSED` | Automatic compensating reversal after an upstream timeout left the outcome genuinely unknown (never left `FAILED` in this case) | No merchant action; webhook confirms the final state |

In short: **timeouts, `5xx`, and `PENDING` are retried with the same key**;
a **decline** or a **validation/business error** is not retried with the
same key — fix the input, or start a genuinely new attempt with a new key.
A `409 urn:radiumone:transaction:idempotency-body-mismatch` means the key was
reused with a different body — it is never safe to retry as-is.

See [Handle timeouts and unknown outcomes](/payments-api/handle-failures/timeouts-and-unknown-outcomes)
and [Retry when the service is unavailable](/payments-api/handle-failures/service-unavailable)
for the full walkthroughs.

## Errors from other products

### 3D Secure errors

3D Secure statuses, SDK errors, and gateway errors have their own full
tables — see [Authentication results](/elements/three-d-secure/authentication-results),
the single reference for that family. This page doesn't duplicate them. If
you're bringing your own 3DS provider's evidence, see
[Handle 3DS failures with your own provider](/payments-api/handle-failures/own-three-ds-provider-failures).

### Checkout API errors

The Checkout API (Hosted checkout) has its own error pages — see [Checkout API errors](/hosted-checkout/errors/api-errors) for the full `checkout:*`/`session:*`/`security:*` URN catalog, or the [Hosted checkout Errors section](/hosted-checkout/errors/payment-outcomes) for outcomes and redirect/embedded signals.

## Rate limits

&#x20;<a id="rate-limit-exceeded" />RadiumOne doesn't publish
specific rate-limit numbers. If you're consistently hitting `429
urn:radiumone:rate-limit-exceeded`, retry after the response's
`Retry-After` header, then [contact support](/resources/support) to discuss
your integration's traffic pattern.

## Next steps

<Columns cols={2}>
  <Card title="Payment operation errors" icon="triangle-alert" href="/payments-api/errors/payment-operation-errors">
    Auth, validation, idempotency, transaction-state, and reversal errors.
  </Card>

  <Card title="Payment method errors" icon="triangle-alert" href="/payments-api/errors/payment-method-errors">
    Loyalty, discovery, routing, and token errors.
  </Card>

  <Card title="Decline codes" icon="credit-card" href="/payments-api/errors/decline-codes">
    How a declined payment appears, and how to handle it — that's not an error.
  </Card>

  <Card title="Handle failures" icon="life-buoy" href="/payments-api/handle-failures/overview">
    Find the right recovery page by symptom.
  </Card>
</Columns>
