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

# Authentication

> How a partner calls Rheon from their own backend with an API key.

There are two ways to reach the same endpoints.

|             | Path              | Who calls it                    | How it is authorised             |
| ----------- | ----------------- | ------------------------------- | -------------------------------- |
| **Widget**  | `/deposit/...`    | A browser, from a page we allow | Origin allowlist, limited per IP |
| **Partner** | `/v1/deposit/...` | Your backend                    | API key, limited per client      |

If you are building your own UI on your own server, you want the second one. The
request and response bodies are identical - only the path and the header differ.

## Sending the key

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST $RHEON_API/v1/deposit/quote \
    -H "Authorization: Bearer $RHEON_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{ "source": { ... }, "destination": { ... }, "amount": "5000000", "method": "crypto" }'
  ```

  ```ts TypeScript theme={null}
  const res = await fetch(`${process.env.RHEON_API}/v1/deposit/quote`, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.RHEON_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify(quoteRequest),
  });
  ```
</CodeGroup>

<Warning>
  The key belongs on your server. It is not scoped to a browser origin, so anything
  that can read it can spend your rate limit and quote as you.
</Warning>

## Getting a key

We issue it. **The key is shown once, at creation** - we keep only a fingerprint of
it, so a lost key cannot be recovered, only replaced. Tell us and we will issue a
new one; the old one stops working the moment the new one is in place.

## What your key is configured for

Each key carries the setup we agreed with you:

* **Source chains** - where your users pay from.
* **Destination chains** - where you settle.
* **Rate** - requests per second for the whole key.

Source and destination are set separately on purpose: taking payment from a
chain and settling on it are different things, and you rarely want both
everywhere.

<Note>
  These corridors describe **your account setup, not a security boundary**. They
  keep your integration inside what we agreed and give you a clear error when a
  request falls outside it. If you need something locked down, lock it down on
  your side too - we will happily match it here, but do not rely on this as your
  only control.
</Note>

## Rate limits are yours to pass on

Your key gets a ceiling, and that ceiling is what stops one integration
affecting another. It is not a per-user limit and cannot be: every request from
you reaches us from your servers, so we see one caller, not your users.

**Limiting your own users is yours to do.** You know who they are - they are
logged in to your product - and we do not. If one of them hammers your
integration, they will spend your ceiling and your other users will feel it.

<Note>
  Leaving `destination` out of a request means Arbitrum. That is a real choice, not
  a blank - if your key is not enabled for Arbitrum, an omitted destination is
  refused like any other.
</Note>

## Errors

| Status | Code                | What happened                                              |
| ------ | ------------------- | ---------------------------------------------------------- |
| `401`  | `unauthorized`      | Missing, malformed, or unknown key. We do not say which.   |
| `403`  | `chain_not_allowed` | Valid key, but not enabled for that chain on that side.    |
| `429`  | `rate_limited`      | Over your key's requests per second. Retry after a moment. |
| `400`  | `invalid_request`   | The body did not validate. The message says what.          |
| `400`  | `no_route`          | No provider could route that pair right now.               |

All errors use the same envelope:

```json theme={null}
{ "error": { "code": "chain_not_allowed", "message": "..." } }
```

## If you are onboarding in bursts

Tell us and we will raise your ceiling, rather than let you discover it in
production.
