# Getting started in five minutes

> Key, environment, one request, one response. Then the product quickstart that fits your question.

- **HTML:** https://offendersearch.app/docs/platform/getting-started
- **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 seven steps

1. **Get your API key.** Create an account at [offendersearch.app/sign-up](/sign-up), open [Dashboard → API keys](/dashboard/keys) and create a key. The secret is shown once. Store it as `OFFENDERSEARCH_API_KEY`.
2. **Select your environment.** Use a test key (`os_test_…`) against `https://sandbox.offendersearch.app` to integrate — fixed test names, never billed. Use a live key (`os_live_…`) against `https://api.offendersearch.app` for real searches, which are billed. See [Sandbox & production](/docs/platform/environments).
3. **Copy a working request.** The three examples below search the sex offender registries for one person. Swap `/v1/search` for `/v1/criminal/search` to search criminal records instead.
4. **Execute it.** A `200` carries the full answer. `status` is `complete` or `partial`; `counts.records` is how many people matched; `records[]` are the matches, best first.
5. **Understand the result.** Read `status` and `sourceStatus[]` before `records[]`: an empty `records[]` is only an answer when every source finished. Each record carries `matchConfidence` and, with a date of birth, a `matchState` saying how strongly the birth date agreed.
6. **Handle errors.** `401` means the key is wrong or missing; `422` means the query was refused (read `detail`); `429` means slow down (`Retry-After`). See [Errors, rate limits & retries](/docs/platform/errors-and-retries).
7. **Go live.** Switch the host and the key; nothing else changes. Run the [production checklist](/docs/platform/operations#production-checklist).

## A working request

**cURL**
```bash
curl -X POST https://api.offendersearch.app/v1/search \
  -H "X-API-Key: $OFFENDERSEARCH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"query": {"firstName": "Jordan", "lastName": "Rivera", "dob": "1988-04-12"}}'
```

**Python**
```python
import os, requests

API_KEY = os.environ["OFFENDERSEARCH_API_KEY"]        # os_live_… or os_test_…
BASE = os.environ.get("OFFENDERSEARCH_BASE", "https://api.offendersearch.app")

resp = requests.post(
    f"{BASE}/v1/search",
    headers={"X-API-Key": API_KEY, "Content-Type": "application/json"},
    json={"query": {"firstName": "Jordan", "lastName": "Rivera", "dob": "1988-04-12"}},
    timeout=60,
)
resp.raise_for_status()
data = resp.json()
print(data["status"], data["counts"]["records"], "records")
for r in data["records"]:
    print(r["matchConfidence"], r["matchState"], r["name"]["first"], r["name"]["last"])
```

**JavaScript**
```javascript
const API_KEY = process.env.OFFENDERSEARCH_API_KEY;   // os_live_… or os_test_…
const BASE = process.env.OFFENDERSEARCH_BASE ?? "https://api.offendersearch.app";

const res = await fetch(`${BASE}/v1/search`, {
  method: "POST",
  headers: { "X-API-Key": API_KEY, "Content-Type": "application/json" },
  body: JSON.stringify({ query: { firstName: "Jordan", lastName: "Rivera", dob: "1988-04-12" } }),
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
const data = await res.json();
console.log(data.status, data.counts.records, "records");
for (const r of data.records) console.log(r.matchConfidence, r.matchState, r.name.first, r.name.last);
```

Jordan Rivera is a fictional name. In the sandbox, use the fixed test names on each product's sandbox page to get deterministic results: [Sex Offender](/docs/sandbox), [Criminal](/docs/criminal/sandbox), [Monitoring](/docs/monitoring/sandbox), [Map](/docs/map/sandbox), [FCRA](/docs/fcra/sandbox).

## The response, in brief

```json
{
  "searchId": "srch_1f2e3d4c5b6a79880a1b",
  "status": "complete",
  "elapsedMs": 412,
  "counts": { "records": 1, "recordsReturned": 1, "sourcesQueried": 58, "sourcesComplete": 58, "sourcesIncomplete": 0 },
  "warnings": [],
  "sourceStatus": [ { "source": "TX", "status": "ok", "matched": 1, "fromCache": true, "incomplete": false, "incompleteReason": null } ],
  "records": [
    {
      "recordId": "rec_3f9a1c2b4d5e6f708192",
      "matchConfidence": 0.96,
      "matchBasis": ["lastName:exact", "firstName:exact", "dob"],
      "matchDetail": { "strategies": { "lastName": "exact", "firstName": "exact" }, "fieldsPresent": ["lastName", "firstName", "dob"], "verification": "dob_match" },
      "matchState": "dob_match",
      "name": { "first": "Jordan", "middle": "", "last": "Rivera", "suffix": "", "full": "Jordan Rivera" },
      "dob": "1988-04-12",
      "dobPrecision": "exact",
      "registrationState": "TX",
      "offenses": [ { "crime": "…", "statute": "…", "convictionDate": "…" } ],
      "sources": [ { "jurisdiction": "TX", "registryName": "Texas Public Sex Offender Registry", "recordUrl": "https://…", "lastCheckedAt": "2026-10-24T03:10:00+00:00" } ]
    }
  ]
}
```

Field names are exact; the values are illustrative. A Regular search like this one carries no `meterEvents[]` (it is one `call`, reported in the dashboard); `usage` and `meterEvents` appear when a `live` block ran. The complete field list is in each product's data reference: [Sex Offender Record](/docs/record-object), [Criminal Record](/docs/criminal/record-object).

## What this costs

A sandbox request costs nothing. A live-host search is one billable call, counted in [Dashboard → Usage](/dashboard/usage); when a search also charges live sources or documents, the response itemises those in `meterEvents[]`. Live re-checks of named sources, evidence documents and monitors are separate meters; each product's pricing is on its billing or quickstart page and on [pricing](/pricing).

## Next

- [Sex Offender quickstart](https://offendersearch.app/docs/quickstart)
- [Criminal Records quickstart](https://offendersearch.app/docs/criminal/quickstart)
- [Monitoring quickstart](https://offendersearch.app/docs/monitoring/quickstart)
- [Which API should I use?](https://offendersearch.app/docs/products/which-api)
- [Integrate with an AI coding assistant](https://offendersearch.app/docs/ai/coding-assistants)
