# Operations

> Usage, billing, the go-live checklist, health and support.

- **HTML:** https://offendersearch.app/docs/platform/operations
- **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

## Usage and billing

- [Dashboard → Usage](/dashboard/usage) shows calls by product and by key; [Dashboard → Billing](/dashboard/billing) shows the month, the invoice and the payment method.
- `meterEvents[]` logged where a response carries it (criminal searches, live sources, documents); Regular Sex Offender searches reconciled from [Dashboard → Usage](/dashboard/usage).
- Prices per product are on [pricing](/pricing) and on each product's billing page ([Monitoring](/docs/monitoring/billing), [Map](/docs/map/billing)).

## Production checklist

1. Live key in a secret store, test key out of the production config; host switched to `api.offendersearch.app`.
2. Client timeout ≥ 60 s; `429` handled with `Retry-After`; `5xx` retried only for safe requests.
3. The `partial` branch handled: your workflow reads `status` and `sourceStatus[]` before concluding "no record".
4. Match review: your workflow treats `records[]` as candidates with a `matchConfidence`, not as confirmed identities; thresholds and a human review step decided.
5. Async ids persisted on receipt; polling or a webhook receiver in place.
6. `meterEvents[]` logged for reconciliation.
7. The notice on every response (`legal.notice`) respected: the self-service APIs are not consumer reports and may not be used for FCRA-regulated decisions; use the [FCRA Partner API](/docs/fcra) for those.
8. Data minimisation: store what your decision needs, not the whole record, and respect the 14-day history window as a reference for your own retention.

## Monitoring integration health

- Alert on the share of `partial` responses and on `sourcesIncomplete` by jurisdiction: a rising share means a source is struggling.
- Alert on `429` and `5xx` rates, and on p95 latency of synchronous searches.
- `GET /v1/sources` and `GET /v1/criminal/sources` publish freshness per source; compare `lastSuccessAt` against your expectations.

## Troubleshooting

| Symptom | Likely cause | Check |
| --- | --- | --- |
| `401` on every call | Wrong header name, wrong host for the key prefix, revoked key | Header is `X-API-Key`; `os_test_` → sandbox, `os_live_` → live |
| `402` on any route | Free trial used up, or no active subscription (there is no criminal entitlement and no `403` on criminal routes) | Dashboard → Billing |
| `422 query_too_broad` | A common surname with nothing to narrow it | Add a first name, a date of birth or a state |
| Empty `records[]` for a known person | The search was `partial`, or the name or DOB did not corroborate | Read `sourceStatus[]`; try without the DOB; check `matchBasis` on near misses |
| Async job never completes | Polling the wrong id or host, or reading the wrong key | Use the poll path from the acknowledgement verbatim (`resultsUrl`, `poll` or `pollUrl` by entry point); on a criminal job a `202` poll means still pending |

## Support

Email [support@offendersearch.app](mailto:support@offendersearch.app) with the `searchId` (or other id) and the time of the request; both are in your dashboard history. Status and announcements: the [changelog](/docs/changelog).
