Offendersearch
Criminal API Reference

Coverage today & the sources endpoint

The public coverage catalog with per-jurisdiction currency - the source of truth, no key required.

Base URL https://api.offendersearch.app

Coverage today

The dataset spans five kinds of criminal record: county jail rosters, statewide DOC (state-prison) inmate systems, court records and dispositions, warrant systems, and statewide registries. Each is a distinct record shape — a jail booking leads with a booking date and charges, a DOC record with a facility and custody status, a court record with a case number and disposition — and each is addressed by its own jurisdiction code. The corpus is continuously updated.

Record kindWhat it holdsCode shape
County jailA county jail booking roster — name, booking date, charges, custody status.<ST>-<COUNTY>
Statewide DOCA state Department of Corrections inmate system — custody status, facility, admission.<ST>-DOC
CourtStatewide court records — case number, court, filed date, charge and disposition.<ST>-COURT
WarrantA warrant / most-wanted system — offense, physical description, status.<ST>-WARRANT
RegistryA statewide registry — name, date of birth, classification, often an address.<ST>-REGISTRY

Stated conservatively: the county, court and federal layers grow jurisdiction by jurisdiction, so any list of what is covered today goes stale. Do not hard-code a coverage list from this page — read it from the API, which is the machine-readable source of truth for coverage.

The authoritative answer to “what is covered?” is the API, not this page. GET /v1/criminal/sources below is that answer — every jurisdiction, its coverage status, and its live currency. Read it at integration and coverage grows under you for free; hard-code a list and it is wrong the day a jurisdiction is added.

GET /v1/criminal/sources

The coverage catalog plus per-jurisdiction currency — the honest, public answer to “how current is your data?”, one row per jurisdiction with the timestamp of its last update. No API key required, so you can check it before you buy and audit it afterwards. It is the one /v1/criminal/* endpoint that needs no credential, and it takes no body and no parameters.

Each row names only a state, a county and a record kind — never a portal or vendor. A statewide DOC system reads “TX — Department of Corrections”, a county jail reads “Dallas County, TX — County Jail Roster”, a federal system reads “Federal — Warrant Records”. The mapping from record kind to label is fixed, and no source host ever appears.

Request
GET /v1/criminal/sources
curl https://api.offendersearch.app/v1/criminal/sources
Response
200 OK
{
  "coverage": {
    "jurisdictions_total": 1410,
    "jurisdictions_live_connector": 727,
    "jurisdictions_pending_connector": 683,
    "states_covered": 50
  },
  "sources": [
    {
      "id": "TX-DALLAS",
      "name": "Dallas County, TX — County Jail Roster",
      "covers": ["TX"],
      "scope": "county",
      "status": "live",
      "health": { "lastSuccessAt": "2026-08-24T05:12:00+00:00",
                  "ageSeconds": 30074, "freshFor": ["daily", "weekly"] }
    },
    {
      "id": "TX-DOC",
      "name": "TX — Department of Corrections",
      "covers": ["TX"],
      "scope": "state",
      "status": "live",
      "health": { "lastSuccessAt": "2026-08-24T04:58:00+00:00",
                  "ageSeconds": 30914, "freshFor": ["daily", "weekly"] }
    }
  ],
  "count": 1410
}

The coverage summary

The coverage block reports the true totals from the product’s own manifest — covered today versus known-but-pending — so a jurisdiction not yet covered is counted in the pending total, never silently omitted. The numbers move as coverage grows; read them live rather than freezing them into your own copy.

KeyMeaning
coverage.jurisdictions_totalEvery jurisdiction the product knows about — covered today plus known-but-pending.
coverage.jurisdictions_live_connectorJurisdictions covered today.
coverage.jurisdictions_pending_connectorKnown, but not yet covered.
coverage.states_coveredDistinct states represented.

Per-jurisdiction health & freshness

Every sources[] row carries a health block — the currency of that one jurisdiction, computed at request time. lastSuccessAt is the ISO-8601 timestamp of its last update, ageSeconds is how old that snapshot is right now, and freshFor restates that age as the freshness tiers it sits inside. These are read-outs of a continuously updated corpus, not a schedule.

KeyMeaning
sources[].idThe public jurisdiction code — usable directly in live.jurisdictions. Never an internal code.
sources[].nameA human jurisdiction label — county/state plus record kind. Never a portal or vendor name.
sources[].coversThe state(s) this jurisdiction covers.
sources[].scopecounty | state | federal.
sources[].statuslive (covered today) | pending (known, not yet covered).
sources[].health.lastSuccessAtISO-8601 of the last update. null = never ingested.
sources[].health.ageSecondsAge of that snapshot right now, computed at request time. null when never ingested.
sources[].health.freshForThe freshness tiers the snapshot sits inside — a restatement of ageSeconds, not a filter. [] when never ingested.
None of this is a filter. A jurisdiction contributes its records to a cached search whatever its health says; currency never withholds anything. Read this endpoint to know a jurisdiction’s currency, not to predict which ones will answer — the answer is always the whole corpus.

Reading the freshness picture

Because every value in each health block is computed at request time, one call is a current snapshot of the whole fleet. A small transform turns it into an at-a-glance summary:

Summarise the live currency, no key
curl -s https://api.offendersearch.app/v1/criminal/sources | jq '
  .sources
  | map(select(.health.ageSeconds != null))
  | { median_age_hours: (map(.health.ageSeconds/3600) | sort | .[length/2|floor]),
      live:    (map(select(.status=="live"))    | length),
      pending: (map(select(.status=="pending")) | length) }'

A companion endpoint returns the same catalog as codes, filterable by state and record kind and gated on an API key — GET /v1/criminal/jurisdictions. Use /sources for the public, no-key currency picture, and /jurisdictions to enumerate the codes you will send in a search.