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

# Invalid publishable key - Elements SDK

> Common publishable key mistakes that stop Elements from initializing, such as passing a secret key or a key from the wrong environment.

`RadiumOne.init()` and `loadRadiumOne()` validate the publishable key **synchronously**, before any network request. A bad key throws immediately in your own code — it's never a silent failure.

<Info>
  TL;DR: init throws an `ElementsError` right away → confirm you passed a publishable key (`r1pk_…`) that matches your CDN/npm build's channel.
</Info>

## When this happens

* No key was passed, or it isn't a string.
* A secret key (`r1sk_prod_…` / `r1sk_test_…`) was passed instead of a publishable key.
* The key's prefix isn't `r1pk_prod_`, `r1pk_test_`, or `r1pk_mock_`.
* The key's channel doesn't match the loaded bundle: a test/mock key with a production CDN or npm build, or a production key with a staging/sandbox build.

## What you see

| Signal | Value |
| - | - |
| Thrown error | Synchronous `ElementsError` — the SDK call throws before it does anything else |
| Code | One of `api:invalid_key`, `api:secret_key_used`, `api:invalid_key_format`, `api:test_key_in_prod_build`, `api:prod_key_in_staging_build`, `loader:integrity_unset` |

## What to do

<Steps>
  <Step title="Check the key prefix">
    Confirm you're passing a publishable key (`r1pk_…`), never a secret key (`r1sk_…`). Secret keys must only ever be used server-side.
  </Step>

  <Step title="Match the key to the bundle">
    A test/mock key (`r1pk_test_…` / `r1pk_mock_…`) needs the sandbox CDN or a `@beta` npm build; a production key (`r1pk_prod_…`) needs the production CDN or the `@latest` npm build from a production release. `loadRadiumOne()` already routes the CDN choice for you based on the key prefix — the mismatch case is mainly an npm channel/key mismatch (`loader:integrity_unset`).
  </Step>

  <Step title="Wrap init in a try/catch during setup">
    Since the throw is synchronous, catch it at the same call site as `RadiumOne.init()` / `loadRadiumOne()`, not inside your payment-submit handler.

    ```js theme={null}
    try {
      const radiumone = await loadRadiumOne("r1pk_test_YOUR_KEY");
    } catch (err) {
      console.error(err.code, err.message); // developer-facing; fix the integration
    }
    ```
  </Step>
</Steps>

## Prevent it

* Keep sandbox and production keys in separate environment configs so a build can't accidentally ship the wrong one.
* Never hardcode a key in a shared snippet or template that's reused across environments.

## Related

<Columns cols={2}>
  <Card title="Install and load Elements" icon="download" href="/elements/install-and-load#key-validation-errors">
    The full key-validation error table.
  </Card>

  <Card title="Sandbox and API keys" icon="key" href="/get-started/sandbox-and-api-keys">
    Where to find your publishable and secret keys.
  </Card>
</Columns>
