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

# Authentication

> API keys, their environments, and keeping them safe.

Your server authenticates with an API key that belongs to one of your applications. The SDK sends
it for you:

```ts theme={null}
const useroutr = new Useroutr({ apiKey: process.env.USEROUTR_API_KEY });
```

Over HTTP, send it as a bearer token:

```bash theme={null}
curl https://api.sandbox.useroutr.com/v1/applications/me \
  -H "Authorization: Bearer $USEROUTR_API_KEY"
```

## Keys and environments

| Key | Environment | API |
| - | - | - |
| `ur_test_...` | Sandbox, Stellar testnet | `https://api.sandbox.useroutr.com` |
| `ur_live_...` | Production, Stellar mainnet | `https://api.useroutr.com` |

Each environment refuses the other's keys with `INVALID_CREDENTIALS` and a message naming the
mistake, so a test key can never move real funds.

## Creating and rotating keys

Create keys in the dashboard under **Developers → API keys**. A key's secret is shown once, when
it is created; Useroutr stores only a digest of it. Give each key a name, such as "Production
server", so you can tell them apart.

To rotate without downtime, create a new key, deploy it, then revoke the old one. Revoking takes
effect immediately.

```ts theme={null}
const key = await useroutr.applications.createApiKey(applicationId, {
  idempotencyKey: "rotate-2026-09",
});
// deploy key.secret, then:
await useroutr.applications.revokeApiKey(applicationId, oldKeyId);
```

## Keep keys secret

<Warning>
  An API key can create funding intents and read everything about your application. Keep it on your
  server, in an environment variable or secret manager. Never put it in browser code, a mobile app
  or a public repository.
</Warning>

Browsers never need a key: the [checkout](/payments/embedded-checkout) uses the funding token of
one intent, which grants nothing else.

## Scope

A key acts for exactly one application. Anything that belongs to another application answers
`404 NOT_FOUND`, never `403`, so ids cannot be probed. A suspended application answers
`403 APPLICATION_INACTIVE`.

## Rate limits

By default each key can make 600 requests a minute. Above that, requests answer `429 RATE_LIMITED` with a
`Retry-After` header and `x-ratelimit-limit`, `x-ratelimit-remaining` and `x-ratelimit-reset`.
The SDK waits and retries for you.

## Request ids

Every response carries an `X-Request-ID`, and every error repeats it as `requestId`. Send your own
`X-Request-ID` (up to 128 characters of letters, digits and `. _ : -`) to trace a call through your
own logs; the SDK accepts it as the `requestId` option.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.