# Authentication

> API key authentication, scopes, and security best practices.

URL: https://docs.reaktly.com/docs/api-reference/authentication

## API keys

All REST endpoints authenticate with an API key in the `x-api-key` header:

```bash
curl https://api.reaktly.com/ingest \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d '{ ... }'
```

Keys are created in the dashboard under **Settings → API keys**. The secret is shown once at creation — store it in your secret manager or environment, never in code. The dashboard keeps a prefix (e.g. `rk_live_abc…`) so you can tell keys apart later.

> **Note:**
> **API keys are not operator keys.** The `op_…` operator key in your website's widget snippet is public by design — it ships in page source and is protected by your allowed domains. API keys are secrets and belong on a server.

## Scopes

A key can only do what its scopes allow — grant the minimum you need:

| Scope | Dashboard label | Grants |
|---|---|---|
| `iq:import` | IQ Import | Push data into a knowledge base ([Ingestion API](/docs/api-reference/ingestion)) |
| `iq:read` | IQ Read | Read knowledge base data |
| `usage:read` | Usage Read | Read usage statistics and analytics |
| `articles:read` | — | Read published articles ([Articles API](/docs/api-reference/articles)); provisioned by Reaktly |

An endpoint returns `403` when the key is valid but lacks the required scope.

## Rotating a key

1. Create the replacement key with the same scopes.
2. Deploy the new value to your integration.
3. Verify traffic, then deactivate the old key in the dashboard.

Keys can carry an expiry date; set one for keys used by contractors or temporary migrations.

## Security best practices

- **Store keys in environment variables or a secret manager** — never in code, git, or client-side JavaScript.
- **One key per integration** — a leaked key then has a small blast radius and a clear owner.
- **Use the minimum scopes** — an ingestion key does not need `usage:read`.
- **Set expiration dates** where possible, and rotate on a schedule.
- **Never put an API key in a website** — browsers and mobile apps cannot keep secrets. The widget uses the public operator key instead.

## Errors

| Status | Meaning | What to do |
|---|---|---|
| `401` | Missing or invalid API key | Check the header name (`x-api-key`) and that the key is active |
| `403` | Valid key, insufficient scope or no access to the resource | Grant the scope, or check that the resource belongs to your tenant |
| `429` | Rate limited | Back off and retry ([Error handling](/docs/integrations/error-handling)) |