<!-- /en/docs/authentication (en) -->

# Authentication

## One key for everything

Authentication is a partner API key shaped `fl_live_<64 hex>`. The same key works on every endpoint: generation, billing, key management.

Pass it in one of two ways:

```bash
# X-API-Key header (recommended)
curl -H "X-API-Key: $FRANKLAB_KEY" https://apergrex.ru/franklab/api/v1/billing/balance

# Or Authorization: Bearer
curl -H "Authorization: Bearer $FRANKLAB_KEY" https://apergrex.ru/franklab/api/v1/billing/balance
```

## Response statuses

| Code | Reason | What to do |
|---|---|---|
| 401 | Key missing, unknown or deactivated | Check the key; issue a new one in the cabinet (**Settings → API**) |
| 403 | A legacy service key was sent | A partner `fl_live_` key is required |
| 429 | Rate limit exceeded | Retry later; the default is 60 requests/minute per partner |

## Rate limits

On top of the per-partner limit there is a gateway-wide limit (100 requests/minute per IP). A 429 response is safe to retry with a delay.

## Key safety

- The key is stored server-side as a hash only — it cannot be "shown again"; a lost key is revoked and replaced.
- Send the key over HTTPS only — never in URLs, logs or client-side code.
- Revoke instantly from your signed-in cabinet session: `DELETE /v1/billing/api-keys/{id}` (or the **Settings → API** page). Revocation never needs the key itself — and a key cannot mint a replacement for itself.
- Use a separate key per integration — labels keep them apart in the list.

## Managing keys

Listing your keys is API-key authenticated. Minting and revoking keys requires the **cabinet partner session** (partner cookie): an API key must not be able to issue further keys, so a compromised key is fully revoked by its own deactivation — it leaves no "children" that would outlive it. This is the same trust model as the **Settings → API** page.

```bash
# list (prefixes only; the raw value is never returned) — API-key auth
curl -H "X-API-Key: $FRANKLAB_KEY" https://apergrex.ru/franklab/api/v1/billing/api-keys
```

Create (`POST /v1/billing/api-keys`) and revoke (`DELETE /v1/billing/api-keys/{id}`) a key from the cabinet: the **Settings → API** page — or the same request sent from a signed-in cabinet session (the `franklab_token` cookie).
