# Authentication & keys

> One header, one key format, every product.

- **HTML:** https://offendersearch.app/docs/platform/authentication
- **Base URL (live):** https://api.offendersearch.app — live keys (`os_live_…`)
- **Base URL (sandbox):** https://sandbox.offendersearch.app — test keys (`os_test_…`), never billed
- **Authentication:** `X-API-Key` request header
- **OpenAPI:** https://offendersearch.app/openapi.json · https://offendersearch.app/openapi.yaml
- **Docs index for agents:** https://offendersearch.app/llms.txt

## The X-API-Key header

Send your secret key in the `X-API-Key` header on every request. There is no OAuth flow and no bearer token for the APIs; the FCRA consumer portal issues its own short-lived session for consumers, documented on the [FCRA consumer portal](/docs/fcra/consumer-portal) page.

```http
POST /v1/search HTTP/1.1
Host: api.offendersearch.app
X-API-Key: os_live_************************
Content-Type: application/json
```

The only unauthenticated endpoints are the coverage catalogs — `GET /v1/sources` and `GET /v1/criminal/sources` — so you can audit coverage before you integrate.

## Key lifecycle

| Action | Where | Notes |
| --- | --- | --- |
| Create | [Dashboard → API keys](/dashboard/keys) | Name it for its service or environment. The secret is shown in full once, at creation, and stored only as a one-way hash. |
| Test key | Same page, **Create test key** | Begins `os_test_`; accepted only by `sandbox.offendersearch.app`; never billed. |
| Live key | Same page, **Create key** | Begins `os_live_`; accepted only by `api.offendersearch.app`; every billable call is recorded against the account. |
| Rotate | Create the new key, deploy it, then revoke the old one | Two live keys can coexist, so a rotation has no gap. |
| Revoke | Same page | Immediate. Requests with a revoked key answer `401`. |

Issue one key per environment or per service rather than sharing one credential across a fleet; a leaked key is then one revocation, not a redeploy of everything.

## Organisation credentials

Keys belong to the account (the organisation), not to the person who created them. Team members are managed under [Dashboard → Team](/dashboard/team); a member who leaves does not take the keys with them, and a key keeps working until someone revokes it. Entitlements — the Map API, FCRA partner status — are properties of the account and apply to every key on it.

## Authentication errors

| Status | Meaning | Fix |
| --- | --- | --- |
| `401` | No key, an unknown key, a revoked key, or a test key sent to the live host (and the reverse). The `detail` sentence varies by route — branch on the status, not the words. | Check the header name (`X-API-Key`), the prefix against the host, and that the key has not been revoked. |
| `403` | The key is valid but the account lacks the entitlement: the Map API not turned on, not an approved FCRA partner, or a consumer account on a business endpoint. | The response `detail.code` names it. Enable it in the dashboard or request access. |

## Secure handling

- Keep keys in a secret store or environment variable (`OFFENDERSEARCH_API_KEY`), never in client-side code, mobile apps or a repository.
- Call the API from your backend. A browser or mobile client that holds a live key has published it.
- All traffic is TLS. Stored data is encrypted at rest; keys are stored only as one-way hashes; every billable search is recorded with its account, time and query and is visible in the dashboard for the 14 days results are kept.
- A Business Associate Agreement can be executed from the dashboard by a signed-in person on the account ([Dashboard → BAA](/dashboard/baa)).

## Related

- [Sandbox & production](https://offendersearch.app/docs/platform/environments)
- [Errors, rate limits & retries](https://offendersearch.app/docs/platform/errors-and-retries)
