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

# Create a session - Hosted checkout

> Create a hosted checkout session and get the URL to redirect the shopper to or embed. Safe to retry with the same order reference.



## OpenAPI

````yaml /openapi/radiumone-checkout-api.yaml post /api/v1/checkout/sessions
openapi: 3.1.0
info:
  title: RadiumOne Checkout API
  version: 0.5.2
  description: >-
    The Checkout API creates and manages hosted-checkout sessions. It is
    hand-authored against the HPP team's current merchant contract — the
    shopper's browser is redirected to (or embeds) a RadiumOne-hosted payment
    page, and your server creates, retrieves, and cancels the session behind it.
    See [Hosted checkout](/hosted-checkout/overview).

    Responses use a simple envelope: `{status, data}` (no `request_id`, unlike
    the Payments API). Errors mirror the Payments API's RFC 9457 shape, plus a
    deprecated top-level `error` field kept for backward compatibility — read
    `type`/`detail`, not `error`.
servers:
  - url: https://checkout-sandbox.radiumone.io
    description: Sandbox
  - url: https://checkout.radiumone.io
    description: Production
security:
  - apiKeyAuth: []
tags:
  - name: Checkout sessions
    description: Create, retrieve, and cancel hosted-checkout sessions.
paths:
  /api/v1/checkout/sessions:
    post:
      tags:
        - Checkout sessions
      summary: Create a checkout session
      description: >-
        Create a hosted-checkout session and get a URL to redirect the shopper
        to (or embed). Idempotent on `order_reference`: a replay with the same
        `order_reference` and body within the session's TTL returns the original
        `201` response; a genuinely concurrent create with the same
        `order_reference` returns `409 session:idempotency_conflict`. See
        [Redirect to hosted checkout](/hosted-checkout/redirect-integration).
      operationId: createCheckoutSession
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                amount:
                  type: integer
                  minimum: 50
                  description: >-
                    Amount in the currency's minor units. Minimum 50. No
                    enforced maximum — the payment gateway rejects an
                    excessively large amount with `422
                    gateway:request_rejected`.
                currency:
                  type: string
                  minLength: 3
                  maxLength: 3
                  enum:
                    - SGD
                    - USD
                    - EUR
                    - GBP
                    - JPY
                    - AUD
                    - HKD
                    - CNY
                    - MYR
                    - THB
                    - IDR
                    - PHP
                    - VND
                    - KRW
                    - INR
                    - TWD
                    - CAD
                    - NZD
                  description: >-
                    ISO 4217 currency code, one of the 18 listed here.
                    Case-insensitive on input (upper-cased before
                    storage/comparison); also must be enabled for your merchant
                    account.
                order_reference:
                  type: string
                  minLength: 1
                  maxLength: 128
                  description: >-
                    Your idempotency key for this session, trimmed of
                    leading/trailing whitespace before the 1–128 length check
                    applies.
                success_url:
                  type: string
                  maxLength: 2048
                  description: >-
                    Redirect target on success. Must be an absolute `https://`
                    URL, or plain `http://localhost` for local development — any
                    other scheme, or a URL that doesn't parse, is rejected with
                    `400 validation:invalid_input`. The host is also checked
                    against `allowed_domains` (exact match or a subdomain of a
                    configured domain); any host is accepted when you haven't
                    configured an allow-list. Use `{CHECKOUT_ID}` as a literal
                    placeholder if you want the session ID back in the URL —
                    only the first occurrence is substituted. Up to 2048
                    characters.
                cancel_url:
                  type: string
                  maxLength: 2048
                  description: >-
                    Redirect target on cancel/decline. Same URL and host-check
                    rules as `success_url`. `{CHECKOUT_ID}` is **not**
                    substituted in this URL. Up to 2048 characters.
                description:
                  type: string
                  maxLength: 256
                mode:
                  type: string
                  enum:
                    - redirect
                    - embed
                  description: >-
                    How the shopper pays. `redirect` (default): send the shopper
                    to `checkout_url`. `embed`: load `checkout_url` in an iframe
                    — see [Embed hosted
                    checkout](/hosted-checkout/embedded-integration).
                ttl_minutes:
                  type: integer
                  minimum: 5
                  maximum: 60
                  description: >-
                    Session TTL in minutes (5–60). Omit to use your
                    environment's default — 10 minutes in production, 25 minutes
                    in sandbox; always set this explicitly rather than relying
                    on the default, since it also bounds the `order_reference`
                    idempotency window.
                locale:
                  type: string
                  enum:
                    - en
                    - zh
                    - ja
                    - ko
                    - th
                    - id
                    - ms
                    - vi
                    - fil
                  description: >-
                    Preferred shopper locale, one of the 9 accepted codes
                    (case-sensitive, lowercase). Only `en` and `zh` currently
                    render a fully localized page; other accepted codes fall
                    back to English unless the shopper's browser language is
                    `en`/`zh`. An unrecognized value is rejected; a non-string
                    value defaults to `en`.
                metadata:
                  type: object
                  description: >-
                    Your own key/value data, as a JSON object. Serialized as
                    compact JSON, it can be at most 4096 UTF-16 code units,
                    limit included — most characters (including Chinese and
                    Thai) count as 1 unit, emoji as 2. A larger object is
                    rejected with `400
                    urn:radiumone:checkout:validation-invalid-input`.
                branding_profile_id:
                  type: string
                  maxLength: 64
                  pattern: ^[A-Za-z0-9_-]+$
                  description: >-
                    Id of a branding profile set up for your merchant, to style
                    this payment page. Letters, digits, `_`, and `-`, up to 64
                    characters (profile IDs are UUIDs, and differ between
                    sandbox and production). An ID that doesn't exist, was
                    deleted, or belongs to another merchant falls back to your
                    default profile; with no default profile, the standard
                    RadiumOne look applies. See
                    [Branding](/hosted-checkout/branding).
                branding:
                  type: object
                  additionalProperties: false
                  description: >-
                    Per-session branding override. Each field you send replaces
                    that field of the resolved branding profile
                    (`branding_profile_id`, or your default profile) for this
                    checkout only. Fields you omit keep the profile value, and
                    an empty object is the same as omitting `branding`. Same
                    validation rules as a saved profile. An unknown field or an
                    invalid value returns `400 validation:invalid_input` naming
                    the field. See [Branding](/hosted-checkout/branding).
                  properties:
                    display_name:
                      type: string
                      minLength: 1
                      maxLength: 100
                      description: >-
                        Merchant name shown in the payment page header and used
                        as the logo's alternative text, 1-100 Unicode code
                        points after trimming leading/trailing spaces (a code
                        point isn't always one visible character: a plain
                        thumbs-up emoji counts as 1, a thumbs-up with a
                        skin-tone modifier as 2, a family emoji as up to 7).
                        Character rules are checked before trimming: no control,
                        bidirectional, or zero-width formatting characters
                        anywhere in the value, including at the start or end,
                        except the zero-width joiner and non-joiner. Without
                        one, your merchant name is shown.
                    logo_url:
                      type: string
                      format: uri
                      pattern: ^https://
                      maxLength: 2048
                      description: >-
                        Absolute https:// URL of your logo with a hostname, no
                        whitespace or control characters, up to 2048 characters.
                        The shopper's browser loads it directly from this URL —
                        RadiumOne doesn't host, cache, or proxy it. Shown 40px
                        tall, up to 180px wide, keeping its proportions. Falls
                        back to the merchant name if missing or it fails to
                        load.
                    primary_color:
                      type: string
                      pattern: ^#[0-9A-Fa-f]{6}$
                      description: >-
                        Main accent colour, #RRGGBB: the selected payment
                        method, links, checkboxes, tabs, sliders, focus rings,
                        and icons on the processing and success screens.
                    accent_color:
                      type: string
                      pattern: ^#[0-9A-Fa-f]{6}$
                      description: >-
                        Highlight colour for the selected bank in instalment
                        options, #RRGGBB (instalments are coming soon — see
                        /payments-api/payment-methods/upcoming-payment-methods).
                    button_color:
                      type: string
                      pattern: ^#[0-9A-Fa-f]{6}$
                      description: >-
                        Background of the Pay button and other primary buttons,
                        #RRGGBB.
                    button_text_color:
                      type: string
                      pattern: ^#[0-9A-Fa-f]{6}$
                      description: >-
                        Label colour on primary buttons, badges, checkbox ticks,
                        and loading spinners, #RRGGBB.
                    focus_color:
                      type: string
                      pattern: ^#[0-9A-Fa-f]{6}$
                      description: >-
                        Border and glow of the focused text or card field,
                        #RRGGBB. Without one, primary_color is used.
                    background_color:
                      type: string
                      pattern: ^#[0-9A-Fa-f]{6}$
                      description: >-
                        Page background in light mode, #RRGGBB. Dark mode uses a
                        fixed dark palette instead; body text automatically
                        switches between near-black and white to stay readable
                        against this colour.
                    success_color:
                      type: string
                      pattern: ^#[0-9A-Fa-f]{6}$
                      description: >-
                        Success colour, #RRGGBB: the success screen,
                        completed-field ticks, redeemed rewards, and
                        interest-free instalment labels (instalments coming
                        soon). Used unchanged in light and dark mode.
                    warning_color:
                      type: string
                      pattern: ^#[0-9A-Fa-f]{6}$
                      description: >-
                        Warning colour, #RRGGBB: the test-mode banner and
                        interest-bearing instalment labels (instalments coming
                        soon). Used unchanged in light and dark mode.
                    error_color:
                      type: string
                      pattern: ^#[0-9A-Fa-f]{6}$
                      description: >-
                        Error colour, #RRGGBB: alerts, field errors, and the
                        countdown when time is nearly up. Used unchanged in
                        light and dark mode.
                    border_radius:
                      type: string
                      enum:
                        - square
                        - rounded
                        - pill
                      description: >-
                        Corner style of fields, card fields, and buttons: square
                        (4px), rounded (12px, the default), or pill (24px).
                    font_family:
                      type: string
                      enum:
                        - system-ui
                        - '-apple-system'
                        - sans-serif
                        - serif
                        - monospace
                        - Inter
                        - Roboto
                        - Open Sans
                        - Lato
                        - Montserrat
                        - Poppins
                        - Source Sans Pro
                        - Noto Sans
                        - Raleway
                        - PT Sans
                        - Noto Sans SC
                        - Noto Sans TC
                        - Noto Sans JP
                        - Noto Sans KR
                        - Noto Sans Thai
                      description: >-
                        Font for the payment page text, matched exactly
                        (case-sensitive). The first five use the shopper's
                        device fonts; the rest are Latin or Asian-script web
                        fonts served by RadiumOne, loaded only when a page uses
                        them. Card number, expiry, and security code fields
                        always use a monospace font.
                    color_scheme:
                      type: string
                      enum:
                        - light
                        - dark
                        - auto
                      description: >-
                        light, dark, or auto to follow the shopper's device
                        setting. A theme query parameter on the payment page URL
                        overrides it, for previews only.
                    button_text:
                      type: string
                      minLength: 1
                      maxLength: 30
                      description: >-
                        Pay button label, 1-30 Unicode code points after
                        trimming (same character rules as display_name), shown
                        before the amount (for example "Place order S$49.99").
                        Shown exactly as sent in every locale. Omit it to use
                        the page's own translated label.
                state:
                  type: string
                  maxLength: 512
                  description: >-
                    Opaque value round-tripped on the redirect back to you. Not
                    included in the redirect signature — verify it separately
                    from `sig`.
                billing_details:
                  type: object
                  description: >-
                    Cardholder name, email, phone, and billing address — shown
                    to the shopper on the pay page and used for 3-D Secure.
                    Every field is optional; an invalid sub-field is dropped
                    rather than rejected, so omit a field entirely rather than
                    sending an empty string. See [Customize
                    checkout](/hosted-checkout/customize-checkout#shopper-and-billing-details).
                  properties:
                    name:
                      type: string
                      maxLength: 128
                      description: >-
                        Cardholder name exactly as on the card — not an account
                        or shipping name.
                    email:
                      type: string
                      maxLength: 254
                    phone:
                      type: string
                      maxLength: 32
                    address:
                      $ref: '#/components/schemas/CheckoutBillingAddress'
                customer:
                  deprecated: true
                  description: >-
                    Removed. Sending this field, with any value, including
                    `null`, returns `400 validation:invalid_input`. Use
                    `billing_details` instead.
                outlet_id:
                  type: string
                  format: uuid
                  description: >-
                    Outlet to charge under — only for multi-outlet merchants.
                    Omit to use your key's bound outlet, or your account
                    default. A malformed value returns `400
                    validation:invalid_input`; a well-formed value that isn't
                    your outlet, or isn't bound to your key, returns `422`.
                line_items:
                  type: array
                  description: >-
                    Itemized breakdown shown to the shopper. When sent,
                    `Σ(quantity × unit_amount) + Σ(adjustments[].amount)` must
                    equal `amount`, or the request is rejected.
                  items:
                    type: object
                    required:
                      - name
                      - quantity
                      - unit_amount
                    properties:
                      name:
                        type: string
                        minLength: 1
                        maxLength: 100
                        description: Item name shown to the shopper.
                      quantity:
                        type: integer
                        minimum: 1
                        description: Number of units.
                      unit_amount:
                        type: integer
                        minimum: 0
                        description: Price per unit, in the currency's minor units.
                      description:
                        type: string
                        maxLength: 255
                        description: Optional subtitle shown under the item name.
                adjustments:
                  type: array
                  description: >-
                    Tax, shipping, discount, and fee rows applied on top of the
                    line-item subtotal. Requires a non-empty `line_items` — an
                    adjustments-only payload is rejected.
                  items:
                    type: object
                    required:
                      - kind
                      - label
                      - amount
                    properties:
                      kind:
                        type: string
                        enum:
                          - tax
                          - shipping
                          - discount
                          - fee
                        description: Adjustment type.
                      label:
                        type: string
                        minLength: 1
                        maxLength: 100
                        description: >-
                          Label shown to the shopper, for example "GST 9%" or
                          "Standard shipping".
                      amount:
                        type: integer
                        description: >-
                          Signed amount in minor units. `discount` must be ≤ 0;
                          `tax`/`shipping`/`fee` must be ≥ 0.
              required:
                - amount
                - currency
                - order_reference
                - success_url
                - cancel_url
            example:
              amount: 5000
              currency: SGD
              order_reference: ORD-1001
              success_url: https://shop.example.com/pay/success?cid={CHECKOUT_ID}
              cancel_url: https://shop.example.com/pay/cancel?order=ORD-1001
              billing_details:
                email: ada@example.com
                name: Ada Lovelace
      responses:
        '201':
          description: Session created.
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  data:
                    type: object
                    properties:
                      checkout_id:
                        type: string
                      checkout_url:
                        type: string
                      expires_at:
                        type: string
                        format: date-time
                        description: >-
                          ISO 8601 string. Contrast with the GET response below,
                          which reports this as epoch milliseconds.
                      status:
                        type: string
              example:
                status: ok
                data:
                  checkout_id: chk_3f9a1c2e5b7d4a608e1f2c3b4d5e6f70
                  checkout_url: >-
                    https://checkout-sandbox.radiumone.io/pay/chk_3f9a1c2e5b7d4a608e1f2c3b4d5e6f70
                  expires_at: '2026-09-14T10:30:00.000Z'
                  status: pending
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '409':
          description: >-
            `session:idempotency_conflict`: the `order_reference` is in use by a
            payable session with a different amount or currency, or another
            request for it is still being created. `session_create_failed`: the
            session could not be stored — retry with the same `order_reference`.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
              examples:
                differentAmount:
                  summary: Same reference, different money
                  value:
                    type: urn:radiumone:checkout:session-idempotency-conflict
                    title: Duplicate order reference
                    status: 409
                    detail: >-
                      order_reference is already in use for a different amount
                      or currency
                    code: session:idempotency_conflict
                    error:
                      code: session:idempotency_conflict
                      message: >-
                        order_reference is already in use for a different amount
                        or currency
                inProgress:
                  summary: Still being created
                  value:
                    type: urn:radiumone:checkout:session-idempotency-conflict
                    title: Duplicate order reference
                    status: 409
                    detail: >-
                      A session for this order_reference is still being created;
                      retry shortly
                    code: session:idempotency_conflict
                    error:
                      code: session:idempotency_conflict
                      message: >-
                        A session for this order_reference is still being
                        created; retry shortly
        '412':
          $ref: '#/components/responses/PreconditionFailed'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
        '429':
          $ref: '#/components/responses/TooManyRequests'
      x-codeSamples:
        - lang: bash
          label: cURL
          source: >
            #!/usr/bin/env bash

            # Create a hosted-checkout session (Live: `billing_details` field).
            Redirect

            # the shopper to checkout_url. Same order_reference within the TTL
            replays

            # the existing session (201) instead of creating a duplicate — safe
            to retry.

            set -euo pipefail


            CHECKOUT_BASE="${RADIUMONE_CHECKOUT_BASE:-https://checkout-sandbox.radiumone.io}"

            : "${RADIUMONE_SECRET_KEY:?set RADIUMONE_SECRET_KEY to your r1sk_*
            secret key}"


            curl -sS -X POST "$CHECKOUT_BASE/api/v1/checkout/sessions" \
              -H "Content-Type: application/json" \
              -H "X-Api-Key: $RADIUMONE_SECRET_KEY" \
              -d @request.json
        - lang: javascript
          label: Node.js
          source: >
            #!/usr/bin/env node

            // Create a hosted-checkout session (Live: `billing_details` field).
            Redirect

            // the shopper to checkout_url. Node 18+ ESM fetch.

            // Env: RADIUMONE_SECRET_KEY, RADIUMONE_CHECKOUT_BASE (optional
            override).

            //

            // Same order_reference within the TTL replays the existing session
            (201)

            // instead of creating a duplicate — safe to retry with the same
            body.

            import { readFileSync } from "node:fs";


            const CHECKOUT_BASE = process.env.RADIUMONE_CHECKOUT_BASE ||
            "https://checkout-sandbox.radiumone.io";

            const secretKey = process.env.RADIUMONE_SECRET_KEY;

            const body = JSON.parse(readFileSync(new URL("./request.json",
            import.meta.url)));


            // Exponential backoff with jitter: attempt 1 waits ~250-500ms,
            doubling each

            // attempt, capped at 4s -- avoids hammering the gateway in a tight
            retry loop.

            function backoffMs(attempt) {
              const base = Math.min(250 * 2 ** (attempt - 1), 4000);
              return base + Math.random() * base;
            }


            async function createCheckoutSession(maxAttempts = 3) {
              for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
                let res;
                try {
                  res = await fetch(`${CHECKOUT_BASE}/api/v1/checkout/sessions`, {
                    method: "POST",
                    headers: {
                      "Content-Type": "application/json",
                      "X-Api-Key": secretKey,
                    },
                    body: JSON.stringify(body), // same order_reference every attempt
                  });
                } catch (networkErr) {
                  if (attempt === maxAttempts) throw networkErr;
                  await new Promise((r) => setTimeout(r, backoffMs(attempt)));
                  continue;
                }

                if (res.status >= 500) {
                  if (attempt === maxAttempts) throw new Error(`server error ${res.status} after ${attempt} attempts`);
                  await new Promise((r) => setTimeout(r, backoffMs(attempt)));
                  continue;
                }

                const payload = await res.json();
                if (!res.ok) {
                  throw new Error(`checkout session create failed: ${payload.code ?? payload.type} (${res.status})`);
                }
                return payload; // redirect the shopper to payload.data.checkout_url
              }
              throw new Error("unreachable");
            }


            createCheckoutSession().then((r) => console.log(JSON.stringify(r,
            null, 2)));
        - lang: python
          label: Python
          source: >
            #!/usr/bin/env python3

            """Create a hosted-checkout session (Live: ``billing_details``
            field).

            Redirect the shopper to checkout_url.


            Same order_reference within the TTL replays the existing session
            (201)

            instead of creating a duplicate — safe to retry with the same body.

            """

            import json

            import os

            import random

            import time

            from pathlib import Path


            import requests


            CHECKOUT_BASE = os.environ.get("RADIUMONE_CHECKOUT_BASE",
            "https://checkout-sandbox.radiumone.io")



            def backoff_seconds(attempt: int) -> float:
                """Exponential backoff with jitter: attempt 1 waits ~0.25-0.5s, doubling
                each attempt, capped at 4s -- avoids hammering the gateway in a loop."""
                base = min(0.25 * 2 ** (attempt - 1), 4.0)
                return base + random.random() * base


            def create_checkout_session(max_attempts: int = 3) -> dict:
                body = json.loads((Path(__file__).parent / "request.json").read_text())
                headers = {"X-Api-Key": os.environ.get("RADIUMONE_SECRET_KEY", "")}

                for attempt in range(1, max_attempts + 1):
                    try:
                        resp = requests.post(f"{CHECKOUT_BASE}/api/v1/checkout/sessions", json=body, headers=headers, timeout=30)
                    except requests.exceptions.Timeout:
                        if attempt == max_attempts:
                            raise
                        time.sleep(backoff_seconds(attempt))
                        continue

                    if resp.status_code >= 500:
                        if attempt == max_attempts:
                            raise RuntimeError(f"server error {resp.status_code} after {attempt} attempts")
                        time.sleep(backoff_seconds(attempt))
                        continue

                    payload = resp.json()
                    if not resp.ok:
                        code = payload.get("code") or payload.get("type")
                        raise RuntimeError(f"checkout session create failed: {code} ({resp.status_code})")
                    return payload  # redirect the shopper to payload["data"]["checkout_url"]

                raise RuntimeError("unreachable")


            if __name__ == "__main__":
                print(json.dumps(create_checkout_session(), indent=2))
components:
  schemas:
    CheckoutBillingAddress:
      type: object
      description: >-
        The cardholder's billing address (not the shipping address). Used for
        3-D Secure; recommended but optional. Each field is trimmed, and a value
        that's empty, too long, or malformed is dropped rather than rejected.
      properties:
        line1:
          type: string
          maxLength: 200
          description: First address line, such as street and number.
        line2:
          type: string
          maxLength: 200
          description: Second address line, such as unit or floor.
        city:
          type: string
          maxLength: 100
        postal_code:
          type: string
          maxLength: 20
        country:
          type: string
          pattern: ^[A-Za-z]{2}$
          description: >-
            Two-letter ISO 3166-1 alpha-2 country code, returned upper-case.
            Other formats (such as `SGP`) are dropped.
        state:
          type: string
          maxLength: 64
          description: >-
            State or province, for addresses in the United States or Canada
            only. Omit it everywhere else — sending a value for other countries
            can cause a 3-D Secure downgrade.
    Problem:
      type: object
      description: >-
        RFC 9457 problem details, `application/problem+json`. `type` is
        auto-derived from `code` as `urn:radiumone:checkout:<code, `:`/`_`
        replaced with `-`>` — branch on `type` (or the equivalent `code`), never
        on `title`, which is a short label and not guaranteed stable across
        error paths for the same `code`.
      properties:
        type:
          type: string
          format: uri
          description: Stable tag URI. Branch on this.
        title:
          type: string
          description: >-
            Short label. Don't branch on it — many error paths share the generic
            title "RadiumOne error".
        status:
          type: integer
        detail:
          type: string
          description: >-
            Human-readable detail; may echo submitted input. Can change — don't
            parse it.
        instance:
          type: string
          description: Request path that produced the error, no query string.
        code:
          type: string
          description: >-
            Stable dotted code, same meaning as `type`, kept for backward
            compatibility.
        details:
          type: object
          description: >-
            Typed extras for some errors, for example `retry_after` (seconds) on
            a 429.
        error:
          type: object
          deprecated: true
          description: >-
            Legacy mirror of `code`/`detail`, kept for backward compatibility.
            Prefer `type`/`detail`.
          properties:
            code:
              type: string
            message:
              type: string
      required:
        - type
        - title
        - status
        - detail
        - code
        - error
  responses:
    BadRequest:
      description: >-
        The request body failed validation, or a publishable key was used where
        a secret key is required.
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'
    Unauthorized:
      description: '`X-Api-Key` is missing, malformed, or not recognized by the gateway.'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'
          example:
            type: urn:radiumone:checkout:missing-credentials
            title: RadiumOne error
            status: 401
            detail: X-Api-Key header is required.
            code: urn:radiumone:checkout:missing-credentials
            error:
              code: urn:radiumone:checkout:missing-credentials
              message: X-Api-Key header is required.
    Forbidden:
      description: The `success_url`/`cancel_url` host is not in your allowed domains.
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'
          example:
            type: urn:radiumone:checkout:security-domain-not-allowed
            title: Domain not allowed
            status: 403
            detail: URL domain not in merchant allowed_domains
            code: security:domain_not_allowed
            error:
              code: security:domain_not_allowed
              message: URL domain not in merchant allowed_domains
    PreconditionFailed:
      description: Your account has no publishable key provisioned.
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'
          example:
            type: urn:radiumone:checkout:merchant-missing-publishable-key
            title: Missing Publishable Key
            status: 412
            detail: >-
              Your account has no active publishable key. Contact support to
              provision one.
    UnprocessableEntity:
      description: >-
        The request is well-formed but cannot be served. `outlet:not_found`:
        `outlet_id` is not an outlet of your merchant.
        `outlet:binding_violation` (type
        `urn:radiumone:auth:outlet-binding-violation`): `outlet_id` conflicts
        with the outlet your key is bound to. `embed:origins_not_configured`:
        `mode` is `embed` but none of your `allowed_domains` can be used as a
        framing origin. `gateway:request_rejected`: the payments gateway
        rejected the request for another reason. `gateway:unavailable`: payments
        are temporarily unavailable; retry after `details.retry_after_ms`.
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'
    TooManyRequests:
      description: Rate limit exceeded. Retry after the given number of seconds.
      headers:
        Retry-After:
          schema:
            type: integer
          description: Seconds to wait before retrying.
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'
  securitySchemes:
    apiKeyAuth:
      type: apiKey
      in: header
      name: X-Api-Key
      description: >-
        Your secret key (`r1sk_...`). A publishable key is rejected with `400
        urn:radiumone:checkout:wrong-key-type`.

````