Sex offender API reference
Every endpoint and every object, each linked to the one place its fields are defined.
Base URL https://api.offendersearch.appHow the sex offender 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/search on Search, the async endpoints on Async & webhooks, and so on. Shared objects — the Record a search returns, the per-registry 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 and in openapi.json.
Sex offender API endpoints — request and response fields
Each endpoint links to its reference block: a Request table (headers, path, query and body fields, with type, required and default) and a Response table (every field, with type and when it is null).
| Endpoint | What it does |
|---|---|
| POST /v1/search | Search. Search every US sex offender registry in one call. Send a SearchRequest; get back one de-duplicated, scored result set with a status for every registry searched. |
| POST /v1/searches | Async search. Submit a search and collect the result later, by polling or by webhook. Accepts every SearchRequest field plus webhookUrl, including a live block (the named registries are re-verified live inside the job and billed as on POST /v1/search), and returns 202 with a job id immediately. |
| GET /v1/searches/{searchId} | Get a search. Read an async job's status and, once it has finished, its full result. |
| GET /v1/searches/{searchId}/results | Stored search results. Re-open a past search on this account and get back exactly the records it returned. The search is not run again and the call is not billed. |
| POST /v1/evidence/searches | Start a live evidence search. On the Live Evidence host — https://evidence.offendersearch.app, not the main API's base URL; same key, same header. Send the same body as POST /v1/search; the registries named in live.jurisdictions (up to 20) are the ones printed. The live check runs as usual, so the records come back exactly as POST /v1/search returns them, and each named registry's own public website is printed to one PDF behind a cover page. Always answers 202; collect the result from GET /v1/evidence/searches/{searchId}. |
| GET /v1/evidence/searches/{searchId} | Poll a live evidence search. On the Live Evidence host — https://evidence.offendersearch.app. Read the job's status and, once it has finished, the full search response plus evidence[], one entry per registry named in live.jurisdictions. |
| GET /v1/evidence/searches/{searchId}/{jurisdiction}.pdf | Download an evidence document. On the Live Evidence host — https://evidence.offendersearch.app. Download one registry's live evidence document — the registry's own public website, printed as shown behind a cover page. The path is the downloadUrl of the matching evidence[] entry. Not billed: the document was billed when it was produced. |
| POST /v1/batch | Batch search. Run up to 1000 searches in one call, one result per input row, in input order. Each row is billed as one search. |
| POST /v1/report | Verification report. One consolidated PDF for a search you already ran, with a source citation on every record. The search's recorded criteria are run again when you request it. |
| POST /v1/searches/{searchId}/proof | Proof documents. Render per-registry proof documents for a search you already ran. Needs billing on the account. |
| GET /v1/proof-docs/{token} | Fetch a proof document. Download one rendered proof document by the token in its documents[].url. |
| GET /v1/records/{recordId} | Get a record. Fetch one Record by the recordId or the registry uuid a search returned. A recordId resolves while the search that returned it is retained (14 days). |
| GET /v1/sources | List sources. The coverage catalog: every registry the API searches, by code, with its coverage and health. No API key required. |
| POST /v1/compat/sexoffender | Compatibility search. The drop-in endpoint: legacy parameter names in, the legacy {offenders, page, totalPages} envelope out. Switch an existing integration by changing the base URL and key. |
| GET /v1/compat/sexoffender | Compatibility search (GET). The same search as the POST form, with the parameters in the query string. |
| POST /v1/clearances | Record a clearance. Record that the person behind a personRef is (this_person) or is not (not_this_person) the subject identified by your subjectId. The verdict must cite the search that showed the person. A second verdict for the same subject, client and person replaces the first. Included in the search price; nothing here is metered. |
| GET /v1/clearances | List a subject's clearances. Every clearance recorded for one subjectId (and clientId, when you send one), newest first. Active clearances only unless includeRevoked=true. The ids you send are hashed before the lookup, so a listing needs the same subjectId and clientId the verdicts were recorded under. |
| GET /v1/clearances/{clearanceId} | Retrieve a clearance. One clearance by id — the clearanceId a search response's cleared[] or clearance carries. subjectId and clientId are null on this route: only a per-account hash of them is stored. |
| DELETE /v1/clearances/{clearanceId} | Revoke a clearance. Sets revokedAt. The verdict stops applying at once: the next search for that subject shows the person again. The clearance stays readable with includeRevoked=true, so the audit trail is not lost. |
Sex offender API objects — Record, SourceRef, 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 |
|---|---|
| Query | Who or where to search for. Every field is optional; send what you know. A name, a date of birth or age, or a location narrows the search, and a query that narrows on nothing is refused with a 422 rather than answered with a partial list. |
| LiveBlock | Asks for named registries to be re-checked at query time (Live verification). Omit it for the Regular answer. Send jurisdictions or scope, not both. |
| SourceStatus | One registry's outcome within a search. Each registry the search touched has one entry in sourceStatus[], so coverage is stated per response rather than assumed. |
| LiveUsage | The live-check charge summary. Present only on the result of a search that carried a live block — the inline response, or the polled result of a live job; its presence is the signal that the answer was re-verified live. |
| MeterEvent | One billable unit behind a live result. Present only on a live result, in meterEvents[]. |
| EvidenceLiveUsage | The usage block of a live evidence search: every LiveUsage field — the live check is billed exactly as on the main API — plus the evidence documents. |
| EvidenceDocument | One registry's live evidence document: the registry's own public website, printed as shown to a PDF behind a cover page. One entry per registry named in live.jurisdictions, in evidence[]. A complete document carries the capture and download fields; an incomplete one carries incompleteReason and detail and is never billed. |
| ProofRequest | Asks for per-registry proof documents: the registries to render and the format. Billing must be enabled on the account. Each rendered document is billed as one PDF, at the same rate as a verification report. |
| ProofBundle | The proof documents rendered for a search. {"status": "none"} when no proof was requested. |
| Record | One registrant, normalized to the same shape across every US registry. Every key is present on every record; an empty value is "", [] or null as stated per field, never a missing key. |
| Name | A person's name as the registry publishes it, split into parts. Each part is "" when the registry does not publish it. |
| Address | One published address. A record carries every address the registry publishes, each typed. |
| Offense | One offense as the registry publishes it. Every field is present; a field the registry does not publish is "" (or null for federal). Dates are ISO-8601, at the precision the registry published. |
| SourceRef | Where a record came from: the registry, its own link to the registrant, and three timestamps. source is the registry that supplied the record's top-level values; sources[] lists every registry that holds the person. |
| StateData | The extended per-state detail. Returned only when the request sends include: ["stateData"]; otherwise stateData is null and omittedFields names it. Each field is "", [] or null when the registry does not publish it. |
| Error | The error body. detail is a sentence you can log or show; the HTTP status is the value to branch on. |
| RateLimitError | The 429 Too Many Requests body. The Retry-After header carries the same wait as detail.retryAfterSeconds. |
| OffendersIoRequest | The parameters of the compatibility endpoint, in the legacy offenders.io names. Sent as a JSON body to POST /v1/compat/sexoffender, or as query parameters to GET /v1/compat/sexoffender. |
| OffendersIoResponse | The legacy {offenders, page, totalPages} envelope, returned unchanged so an existing integration keeps working. |
| OffendersIoOffender | One registrant in the legacy flat shape: every legacy key, plus personUuid, county, stateData, matchConfidence and matchState. Coordinates use -1 for missing, not null. |
| CompatError | The error body on the compatibility endpoint: {code, message} in the legacy shape, instead of {detail}. |
| Clearance | One verdict: the person behind a personRef is, or is not, the subject being screened. Returned by every /v1/clearances route. subjectId and clientId are echoed only on the request that carried them (create and list); on GET /v1/clearances/{clearanceId} they are null, because only a per-account hash of them is stored. |
| 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. |
Product overview
- Sex offender search API
- Sex offender registry API
- Offender search API
- Background check API
- Bulk sex offender search
- Background check API pricing
- Background check API integration
- Integrations
- Free background check API
- Pay-as-you-go background check API
- Background check API in Python
- Background check API in Node.js
- NSOPW API