Criminal Search API reference
Every endpoint and every object, each linked to its request and response fields.
Base URL https://api.offendersearch.appHow the criminal records API reference is organised
Every endpoint documents what it is sent and what it returns in two tables, next to the guide that explains it: POST /v1/criminal/search on Search, the async poll on Async & long-running, the batch on Batch & CSV, and so on. Shared objects — the CriminalRecord that search, batch and the record lookup return, its cases and charges, the live SourceStatus, the Error body — are defined once and linked from every table that carries them. The same tables are in the markdown twin of each page.
Criminal search API endpoints — request and response fields
Each endpoint links to its reference block: a Request table (path, query and body fields, with type, required and default) and a Response table (every field, with type and when it is null). Every endpoint takes the X-API-Key header except GET /v1/criminal/sources.
| Endpoint | What it does |
|---|---|
| POST /v1/criminal/search | Search. Search criminal records for one person. Without a live block it returns the cached answer; with one it re-verifies the named jurisdictions at the source during the request. Bills one criminal_call, plus $0.02 per completed live source up to $2.00. |
| GET /v1/criminal/searches/{searchId} | Get an async search. Read an async live job. Returns 202 while it runs and 200 with the full envelope in result once every source has an outcome. Polling is free. |
| POST /v1/criminal/batch | Batch. Run up to 1,000 cached searches in one request, one result per row in input order. Each row that runs bills one criminal_call. Live verification is not available in a batch. |
| GET /v1/criminal/records/{recordId} | Get a record. Fetch one current record by its externalId, sending its sources[].code as source so the lookup is a direct key read. The record comes back unscored: matchConfidence is 0.0 and the match fields are empty, because there is no query to score against. Not billed. |
| GET /v1/criminal/sources | List sources. The coverage catalog: every source by public code, whether it is available, and when its records were last updated. No API key needed, so coverage can be checked before you sign up. Not billed. |
| GET /v1/criminal/jurisdictions | List jurisdictions. Every covered jurisdiction by public code, state, county and record kind, filtered by the query parameters. Not billed. |
| POST /v1/criminal/resolve | Resolve a website. Map a roster or records website you already use to the public jurisdiction code that covers it, or say it is not covered. Not billed. |
| GET /v1/criminal/history | Search history. Your account's 50 most recent criminal searches, newest first, with the searchId a report needs. Not billed. |
| POST /v1/criminal/report | Verification report. Render a PDF that records a search was run: the criteria, the sources searched and the records found (for a stored searchId, the page that search returned), with the not-a-consumer-report notice. A report on a stored searchId bills only the report; an inline query bills the search too. |
Criminal search API objects — CriminalRecord, Case, SourceStatus and more
Each object is defined once, on the page linked here. Wherever an endpoint or another object carries it, the type links back to that one definition.
| Object | What it is |
|---|---|
| Error | The body of every error the criminal service returns: one nested error object with a stable code to branch on and a message to log or show. A 401 or 402 comes from the gateway in the GatewayError shape instead. |
| GatewayError | The body of a 401 (missing or invalid X-API-Key) or a 402 (free trial used up, or no active subscription). The gateway answers these before the criminal service runs, so the shape is the Sex Offender API's flat detail string. |
| Query | The person you are looking for. lastName is the only required field; every other field narrows within that surname. Send it as query on POST /v1/criminal/search and POST /v1/criminal/report, or as one row of queries[] on POST /v1/criminal/batch. The fields can also be sent flat at the top level of the body. |
| LiveRequest | The live block. Its presence turns on live verification: the named jurisdictions are re-checked at the source during the request and the fresh results merge with the cached answer through the same matcher. Up to 2 sources that can answer quickly run synchronously (200); more, or any source that cannot, run as an async job (202). |
| Counts | Totals on every criminal search. The three live counts are 0 on a cached search; sourcesOnFile and sourcesPending describe the sources behind the answer on every search. |
| SearchCoverage | Which sources stand behind a search for the state or county searched, and which sources for that scope are not available yet. Codes are the public codes GET /v1/criminal/sources lists. It does not change status. |
| SearchCoverageSource | One source in a search's coverage block. |
| SourceStatus | One live source's outcome within a search. Present only on a live search; a cached search returns sourceStatus: []. |
| ResolutionEntry | What one website resolved to, as reported in a search's resolution[]. The same fields as a ResolveResult without state and county. |
| Usage | The live-check count and charge, present only on a live search. The count is the true number of completed checks even when the charge is capped. |
| MeterEvent | One billable unit this request emitted. |
| Legal | The notice carried on every criminal search response and every batch row. |
| CriminalRecord | One record from one jurisdiction, as search, batch and the record lookup return it. A person found in several jurisdictions (booked in one county, a court case in another, an inmate record statewide) comes back as one record per jurisdiction; relate them by name, dob and state. Every key is present on every record. Empties mean different things: "" is a text field the source does not publish, null is a date, number, object or demographic that is not known, and [] is a list with nothing on file. |
| Name | A name in four parts, each "" when not published. There is no full key; join the parts for display. Casing is as published; matching ignores case. |
| Dob | All birth evidence on a record. dobPrecision says which parts are real; date is a full date or null, never a made-up day. A source's placeholder date (1/1 of a year with nothing else to support it, and the like) never becomes a full date; a sentinel (1900-01-01, 0001-01-01, any 9999 date, a year before 1900 or after this year) is no birth evidence, so birthYear is null too. |
| Address | A residence, in the same slots as the Sex Offender API's address. Text fields are "" when not published. |
| Case | A court case and its charges. filedDate is ISO or null; text fields are "" when not published. |
| Sentence | A sentence. Text fields are "" when not published; dates are ISO or null. |
| Parole | Parole posture as published. Dates are ISO or null; text fields "" when not published. |
| Custody | Custody classification, alongside currentStatus and custodyFacility. Text fields "" when not published. |
| Charge | One charge on a case. severity: null means the source did not classify it, not that it is minor. |
| SourceRef | The jurisdiction a record comes from. code names a state and a place, nothing else. |
| Lifecycle | Records are never deleted when a person leaves a source; the departure is reported here and the record is still returned. |
| Coverage | Coverage totals for the whole product, by jurisdiction. |
| SourceInfo | One source in the coverage catalog. |
| JurisdictionInfo | One covered jurisdiction: its public code and its place, nothing else. |
| ResolveResult | What one website resolved to. The response names the state, the county and the public code, never the website's host. |
| ResolveListResponse | The answer when websites (a list) is sent. |
| JobRecord | An async live job as GET /v1/criminal/searches/{searchId} returns it: pending with result: null until every source has an outcome, then complete with the full search envelope in result. |
| HistoryEntry | One prior criminal search. Pass searchId to POST /v1/criminal/report to render it. |
| BatchRow | One row's result. A row that ran is the search envelope without searchId, meterEvents, usage and resolution, plus index. A row that failed validation carries only index, status: "error", error, zeroed counts and records: []. |
| ClearedEntry | One record a not_this_person clearance removed from records[] for the subjectId sent. cleared[] carries one of these per suppressed record, so an interface can say how many previously cleared people are hidden and link each to its clearance. |
| RecordClearance | The clearance that names a record's person, attached as clearance when the request carried subjectId and the record was kept: in clearanceMode: "annotate", on a this_person verdict, or because a cleared person has re-surfaced (staleReason set). A record no clearance names carries no clearance key. |
The Legal object — the FCRA notice
The notice carried on every criminal search response and every batch row.
Returned or accepted by POST /v1/criminal/search, GET /v1/criminal/searches/{searchId}, POST /v1/criminal/batch.
| Field | Type | Description |
|---|---|---|
| notice | string | The not-a-consumer-report notice, verbatim. This data may not be used for any FCRA purpose: employment, tenant screening, credit, insurance or any other FCRA-covered decision. Example "Not a consumer report. This information may not be used for any purpose under the Fair Credit Reporting Act (15 U.S.C. § 1681 et seq.)." |