# Filtering criminal searches

> Filter a criminal search by severity, outcome, charge, custody, date and location. Every record a filter removes is counted; unknown values are kept by default.

- **HTML:** https://offendersearch.app/docs/criminal/filtering
- **Base URL (live):** https://api.offendersearch.app — live keys (`os_live_…`)
- **Base URL (sandbox):** https://sandbox.offendersearch.app — test keys (`os_test_…`), never billed; see https://offendersearch.app/docs/criminal/sandbox.md
- **Authentication:** `X-API-Key` request header
- **OpenAPI:** https://offendersearch.app/openapi.json · https://offendersearch.app/openapi.yaml
- **Criminal reference as markdown:** https://offendersearch.app/docs/criminal.md

## Criminal search filters: narrow a named search

A criminal search always starts from a name. Add `filters` to keep only the records you care about (felonies, convictions, court cases, a date window, a custody status) and `locations` to say where the person lived or where their records are. Both are optional request keys on [POST /v1/criminal/search](https://offendersearch.app/docs/criminal/search.md); a search without them answers exactly as before, and a filtered search is billed like any other search.

Filters test the [normalized fields](https://offendersearch.app/docs/criminal/normalized-fields.md) every record carries, so the same request works in every jurisdiction. The source's own words are still returned beside them.

**A filter never hides a record silently.** Every record a filter or location removes is counted in `counts.filteredOut`, by the filter that removed it, and every record kept only because its value is unknown is counted in `counts.unknownKept`. If filtering is ever switched off, a filtered search is refused with `503 filters_unavailable`; it is never answered unfiltered.

## How criminal record filters combine

Every filter you send must pass (AND). The values inside one list are alternatives (OR): `"severity": ["felony", "misdemeanor"]` keeps either. A list filter also takes a single string.

- **Record filters** test the whole record: `recordCategory`, `custodyStatus`, `hasPhoto`, `sources`, `excludeVacatedOrSealed`, the date ranges (`offenseDate`, `filedDate`, `dispositionDate`, each tested against the record's latest date of that kind) and `lookbackYears` (the latest of the three within that many years of today).
- **Charge filters** test the record's charges: `severity`, `outcome`, `convictedOnly`, `chargeCategories`, `statute` (the start of the published citation) and `chargeText` (text anywhere in the published description). `severityBasis` narrows `severity` to the bases you trust and does nothing on its own. `convictedOnly: true` adds `convicted` to the outcomes a charge may have.

### chargeMatch: any vs all

`chargeMatch` decides how charge filters meet. With `"any"` (the default) one charge must pass every charge filter, so "a felony conviction" means one charge that is both. With `"all"` each filter may be met by a different charge. Take this record, searched with `"severity": ["felony"], "convictedOnly": true`:

```json
"cases": [ { "caseNumber": "2019-CF-0412", "charges": [
  { "description": "BURGLARY OF HABITATION", "disposition": "DISMISSED" },   // felony, dismissed
  { "description": "THEFT < $750",           "disposition": "GUILTY" }      // misdemeanor, convicted
] } ]
```

| chargeMatch | Result |
| --- | --- |
| `"any" (default)` | Filtered out, counted under `filteredOut.severity`: no single charge is both a felony and a conviction. |
| `"all"` | Returned with `matchesFilters: [{case: 0, charge: 0}, {case: 0, charge: 1}]`: the felony is met by one charge and the conviction by the other. |

A record that passes a charge filter carries `matchesFilters`: the `{case, charge}` positions, in `normalized.cases[].charges[]`, of the charges that met them. Every charge is still returned.

## Criminal filter counts: filteredOut, unknownKept, quarantined

- `counts.filteredOut`: records removed, keyed by the filter that removed each one. A record is counted once, under the first filter it failed. Location misses are `locations`, or `noResidence` when a residence test had no published address to test. A record that fails the per-charge test is counted under the first charge filter you sent. For a name too common to search unfiltered, the index applies your filters together before matching, and those records are counted once under `filters`.
- `counts.unknownKept`: returned records that passed a filter only because their value is unknown, for `severity`, `outcome`, `custodyStatus` and the date ranges.
- `counts.quarantined`: candidate records whose normalized values are withheld (`normalized.quality: "quarantined"`). Their own fields are returned as usual.
- `appliedFilters`: the filters as validated, with `unknown` and `chargeMatch` always present.

### Unknown values: keep or exclude

`filters.unknown` decides what `severity`, `outcome`, `convictedOnly`, `custodyStatus` and the date filters do with a value that is not known. `"keep"` (the default) returns the record and counts it in `unknownKept`; `"exclude"` removes it and counts it in `filteredOut`.

Records marked vacated, expunged or sealed are returned, marked `normalized.vacatedOrSealed: true`, unless you send `excludeVacatedOrSealed: true`.

## Locations: residence vs jurisdiction in a criminal search

| kind | Matches | Notes |
| --- | --- | --- |
| `residence` | Where the person lives: the published address (`state`, `county`, `city`, `zipcode`, or a radius). | A record with no published address cannot match; it is counted as `noResidence`. |
| `jurisdiction` | Where the record is: the state and county of the court, jail or agency. | `city`, `zipcode` and a radius are refused with `422 invalid_location`. |
| `any (default)` | Either of the two. | `city`, `zipcode` and a radius test the residence only. |

- **Up to 10 locations, ORed.** A record is kept when it matches any of them, and lists the 0-based indexes of the ones it matched in `matchedLocations`.
- **A radius applies to the residence only.** `lat`, `lng` and `radiusMiles` (0.1 to 100 miles) go together and are measured to the published address. A residence without coordinates cannot be tested and counts as `noResidence`.
- **Locations define the candidates.** Each location runs its own search: a `jurisdiction` location searches its state and county, a `residence` location searches its ZIP or city when it has one, and `any` or a radius searches the name across every record. The candidates are pooled, then each is tested against every location. A name too broad to read in full is refused with `422 query_too_broad`, never answered in part.
- **One way to say where.** Send `locations` or the flat `state`, `county`, `city` and `zipcode` query keys, not both: both is `422 ambiguous_location`. A county matches with or without the word "County".

## Criminal search filter examples

### 1. A known person and two places they lived

You know the name and date of birth, a ZIP the person lived in, and that they also spent time in Oklahoma. One location tests the residence; the other matches either an Oklahoma address or an Oklahoma record.

```bash
curl -X POST https://api.offendersearch.app/v1/criminal/search \
  -H "X-API-Key: $OFFENDERSEARCH_KEY" \
  -H "Content-Type: application/json" \
  -d '{
        "query": { "lastName": "Rivera", "firstName": "Jordan", "dob": "1988-04-12" },
        "locations": [
          { "kind": "residence", "zipcode": "77060" },
          { "kind": "any", "state": "OK" }
        ]
      }'
```

```json
{
  "status": "complete",
  "counts": { "records": 2, "recordsReturned": 2,
              "sourcesQueried": 0, "sourcesComplete": 0, "sourcesIncomplete": 0,
              "candidatesCapped": false, "exclusionsIncluded": false,
              "filteredOut": { "locations": 3, "noResidence": 1 },
              "unknownKept": {}, "quarantined": 0 },
  "records": [
    { "externalId": "TX-HARRIS-DC:case:201944871",
      "name": { "first": "JORDAN", "middle": "", "last": "RIVERA", "suffix": "" },
      "matchState": "dob_match",
      "address": { "type": "residence", "line1": "16966 NORTHCHASE DR APT 313",
                   "city": "HOUSTON", "county": "Harris", "state": "TX", "zipcode": "77060",
                   "lat": null, "lng": null },
      "matchedLocations": [0] },
    { "externalId": "OK-TULSA:booking:2021-118342",
      "name": { "first": "JORDAN", "middle": "", "last": "RIVERA", "suffix": "" },
      "matchState": "dob_match",
      "matchedLocations": [1] }
  ],
  "appliedFilters": {
    "locations": [ { "kind": "residence", "zipcode": "77060" },
                   { "kind": "any", "state": "OK" } ],
    "unknown": "keep", "chargeMatch": "any"
  }
}
```

- Each record says which location it matched in `matchedLocations` (0 is the ZIP, 1 is Oklahoma).
- `filteredOut.noResidence: 1` is a candidate that matched neither location and had no published address to test against the ZIP. It was not dropped silently: it is counted.

### 2. Felony convictions in the last 7 years, anywhere

Charge filters test charges. With the default `chargeMatch: "any"`, one charge must be both a felony and a conviction, and the record's latest offense, filing or disposition date must be within 7 years.

```bash
curl -X POST https://api.offendersearch.app/v1/criminal/search \
  -H "X-API-Key: $OFFENDERSEARCH_KEY" \
  -H "Content-Type: application/json" \
  -d '{
        "query": { "lastName": "Rivera", "firstName": "Jordan", "dob": "1988-04-12" },
        "filters": { "severity": ["felony"], "convictedOnly": true, "lookbackYears": 7 }
      }'
```

```json
{
  "status": "complete",
  "counts": { "records": 2, "recordsReturned": 2,
              "sourcesQueried": 0, "sourcesComplete": 0, "sourcesIncomplete": 0,
              "candidatesCapped": false, "exclusionsIncluded": false,
              "filteredOut": { "severity": 4, "lookbackYears": 1 },
              "unknownKept": { "severity": 1 }, "quarantined": 0 },
  "records": [
    { "externalId": "TX-HARRIS-DC:case:201944871",
      "cases": [ { "caseNumber": "201944871",
                   "charges": [ { "statute": "PC 22.02", "description": "AGG ASSAULT W/DEADLY WEAPON",
                                  "severity": "felony", "disposition": "GUILTY" } ] } ],
      "normalized": {
        "recordCategory": "court", "topSeverity": "felony",
        "hasConviction": true, "convictionCount": 1,
        "cases": [ { "stage": "closed", "caseClass": "felony",
                     "charges": [ { "category": "assault", "notACharge": false,
                                    "severity": "felony", "severityBasis": "published",
                                    "degree": null, "outcome": "convicted", "convicted": true,
                                    "custodyEvent": null } ] } ] },
      "matchesFilters": [ { "case": 0, "charge": 0 } ] }
  ],
  "appliedFilters": { "severity": ["felony"], "convictedOnly": true, "lookbackYears": 7,
                      "unknown": "keep", "chargeMatch": "any" }
}
```

- `matchesFilters` points at the charge that met every charge filter, by its position in `normalized.cases[].charges[]`. Every charge on the record is still returned.
- `unknownKept.severity: 1` is a returned record whose severity could not be classified. It is kept because `unknown` defaults to `keep`; send `"unknown": "exclude"` to remove such records instead.

### 3. In custody or wanted, within 25 miles of Dallas

A radius tests where the person lives, so `kind: "any"` with a radius matches on the residence only. A location with no ZIP or city searches the name across every record, so a very common name can be refused with `422 query_too_broad`; add a first name or date of birth.

```bash
curl -X POST https://api.offendersearch.app/v1/criminal/search \
  -H "X-API-Key: $OFFENDERSEARCH_KEY" \
  -H "Content-Type: application/json" \
  -d '{
        "query": { "lastName": "Rivera", "firstName": "Jordan" },
        "locations": [ { "kind": "any", "lat": 32.78, "lng": -96.80, "radiusMiles": 25 } ],
        "filters": { "custodyStatus": ["in_custody", "wanted"] }
      }'
```

```json
{
  "status": "complete",
  "counts": { "records": 1, "recordsReturned": 1,
              "sourcesQueried": 0, "sourcesComplete": 0, "sourcesIncomplete": 0,
              "candidatesCapped": false, "exclusionsIncluded": false,
              "filteredOut": { "noResidence": 6, "locations": 2, "custodyStatus": 3 },
              "unknownKept": {}, "quarantined": 0 },
  "records": [
    { "externalId": "TX-DALLAS:booking:26-0041177",
      "currentStatus": "in_custody",
      "normalized": { "recordCategory": "jail", "custodyStatus": "in_custody",
                      "residence": { "city": "GARLAND", "state": "TX", "zip5": "75040",
                                     "lat": 32.93, "lng": -96.62, "geoPrecision": "street" } },
      "matchedLocations": [0] }
  ],
  "appliedFilters": {
    "custodyStatus": ["in_custody", "wanted"],
    "locations": [ { "kind": "any", "lat": 32.78, "lng": -96.8, "radiusMiles": 25.0 } ],
    "unknown": "keep", "chargeMatch": "any"
  }
}
```

- `noResidence: 6` are candidates with no published address, or an address without coordinates, so the radius could not be tested. They are counted, not hidden.
- `appliedFilters` echoes each location with the keys it was read as.

### 4. Violent or weapons charges, with a published severity only

`severityBasis` works together with `severity`: list every severity you accept and the bases you trust. `"unknown": "exclude"` removes charges and records whose severity could not be decided at all.

```bash
curl -X POST https://api.offendersearch.app/v1/criminal/search \
  -H "X-API-Key: $OFFENDERSEARCH_KEY" \
  -H "Content-Type: application/json" \
  -d '{
        "query": { "lastName": "Rivera", "firstName": "Jordan", "dob": "1988-04-12" },
        "filters": {
          "chargeCategories": ["assault", "weapons"],
          "severity": ["felony", "misdemeanor", "infraction"],
          "severityBasis": ["published"],
          "unknown": "exclude"
        }
      }'
```

```json
{
  "status": "complete",
  "counts": { "records": 1, "recordsReturned": 1,
              "sourcesQueried": 0, "sourcesComplete": 0, "sourcesIncomplete": 0,
              "candidatesCapped": false, "exclusionsIncluded": false,
              "filteredOut": { "chargeCategories": 2, "severity": 2 },
              "unknownKept": {}, "quarantined": 0 },
  "records": [
    { "externalId": "TX-HARRIS-DC:case:201944871",
      "matchesFilters": [ { "case": 0, "charge": 0 } ] }
  ],
  "appliedFilters": {
    "severity": ["felony", "misdemeanor", "infraction"], "severityBasis": ["published"],
    "chargeCategories": ["assault", "weapons"],
    "unknown": "exclude", "chargeMatch": "any"
  }
}
```

- With `chargeMatch: "any"`, one charge must be an assault or weapons charge and carry a severity the source published itself.
- `severityBasis` must be sent with `severity`; on its own it is refused with a 422.

### 5. Convicted court records, vacated or sealed left out

A screening-style search: court records only, a conviction on at least one charge, and records marked vacated or sealed left out by choice. `include: ["facets"]` adds counts over the whole result.

```bash
curl -X POST https://api.offendersearch.app/v1/criminal/search \
  -H "X-API-Key: $OFFENDERSEARCH_KEY" \
  -H "Content-Type: application/json" \
  -d '{
        "query": { "lastName": "Rivera", "firstName": "Jordan", "dob": "1988-04-12" },
        "filters": { "recordCategory": ["court"], "outcome": ["convicted"],
                     "excludeVacatedOrSealed": true },
        "include": ["facets"]
      }'
```

```json
{
  "status": "complete",
  "counts": { "records": 3, "recordsReturned": 3,
              "sourcesQueried": 0, "sourcesComplete": 0, "sourcesIncomplete": 0,
              "candidatesCapped": false, "exclusionsIncluded": false,
              "filteredOut": { "recordCategory": 5, "excludeVacatedOrSealed": 1, "outcome": 2 },
              "unknownKept": { "outcome": 1 }, "quarantined": 0 },
  "records": [ "…" ],
  "facets": {
    "recordCategory": { "court": 3 },
    "severity": { "felony": 1, "misdemeanor": 1, "unknown": 1 },
    "outcome": { "convicted": 2, "dismissed": 1, "unknown": 1 },
    "jurisdiction.state": { "TX": 2, "OK": 1 },
    "chargeCategories": { "assault": 1, "theft": 1, "traffic": 1 },
    "custodyStatus": { "disposed": 2, "unknown": 1 }
  },
  "appliedFilters": { "recordCategory": ["court"], "outcome": ["convicted"],
                      "excludeVacatedOrSealed": true, "unknown": "keep", "chargeMatch": "any" }
}
```

- `facets` counts every record that passed, not only this page. A record with several outcomes or charge categories counts once under each.
- Without `excludeVacatedOrSealed`, a record marked vacated or sealed is returned with `normalized.vacatedOrSealed: true`.

## Sorting and facets for filtered criminal searches

`sort` orders a search that sends `filters` or `locations`: `relevance` (the default), or `offenseDate`, `filedDate` or `dispositionDate`, newest first by the record's latest date of that kind, with records that have none last.

`include: ["facets"]` adds `facets`: counts of every record that passed (not only the page) by record category, highest severity, outcome, state, charge category and custody status. `include: ["normalizedDetail"]` adds the rule that decided each charge's outcome, for audits.

Filters work on cached searches and on live checks of up to 2 sources. A live search that has to run as a job refuses them with `422 filters_with_async_live`.

## Criminal filter errors

| error.code | When |
| --- | --- |
| `invalid_filter_value` | A value outside a filter's list, a wrong type, an unknown filter key, a `statute` or `chargeText` under 2 characters, a `lookbackYears` outside 1–100, or a bad `sort`, `unknown` or `chargeMatch`. The message lists the allowed values. |
| `invalid_date_range` | A date range with neither `from` nor `to`, a value that is not `YYYY-MM-DD` or not a real date, or `from` after `to`. |
| `invalid_location` | An empty `locations` list; an unknown key, a bad state or ZIP, or no place in a location; `lat`, `lng` and `radiusMiles` not sent together or out of range; a radius below 0.1; a radius, `city` or `zipcode` on `kind: "jurisdiction"`. |
| `too_many_locations` | More than 10 locations. |
| `ambiguous_location` | `locations` sent together with the flat `state`, `county`, `jurisdiction`, `city`, `zipcode` or `address` query keys. |
| `radius_too_large` | `radiusMiles` above 100. |
| `filters_with_async_live` | `filters` or `locations` on a live search that has to run as a job. Filters work on cached searches and on live checks of up to 2 sources. |
| `filters_unavailable (503)` | Filtering is switched off for the moment. A filtered search is never answered unfiltered; retry after `Retry-After` seconds, or search without filters. |

## The SearchFilters object — criminal search filter fields

The `filters` of a criminal search. Every key is optional; filters are ANDed and the values inside one list are ORed. A list filter also takes a single string. Any other key is `422 invalid_filter_value`.

Returned or accepted by [`POST /v1/criminal/search`](https://offendersearch.app/docs/criminal/search#reference-post-v1-criminal-search).

| Field | Type | Required / default | Description |
| --- | --- | --- | --- |
| `recordCategory` | `array of string` — one of `"court"`, `"jail"`, `"prison"`, `"warrant"`, `"registry"`, `"exclusion"`, `"other"` | optional | The kind of record (`normalized.recordCategory`). |
| `severity` | `array of string` — one of `"felony"`, `"misdemeanor"`, `"infraction"` | optional | Charge severity. With `unknown: "keep"` an unclassified charge also passes. |
| `severityBasis` | `array of string` — one of `"published"`, `"statute_code"`, `"statute_table"`, `"case_type"`, `"charge_text"` | optional | Narrows `severity`: a charge's severity counts only when it was decided on one of these bases. Must be sent with `severity`; on its own it is a 422 `invalid_filter_value`. |
| `outcome` | `array of string` — one of `"convicted"`, `"pending"`, `"dismissed"`, `"nolle_prosequi"`, `"acquitted"`, `"deferred_or_diverted"`, `"vacated"`, `"warrant"`, `"transferred"`, `"closed_unspecified"`, `"administrative"` | optional | Charge outcome class. With `unknown: "keep"` a charge whose outcome is unknown also passes. |
| `convictedOnly` | `boolean` | optional · default `false` | `true` adds `convicted` to the outcomes a charge may have. Alone it means a convicted charge; with `outcome` the charge may have any of those outcomes or `convicted`. |
| `chargeCategories` | `array of string` — one of `"supervision"`, `"homicide"`, `"sex_offense"`, `"robbery"`, `"domestic_violence"`, `"dui"`, `"assault"`, `"weapons"`, `"burglary"`, `"fraud"`, `"theft"`, `"drug_distribution"`, `"drug_possession"`, `"traffic"`, `"public_order"`, `"other"` | optional | What the charge is about. |
| `chargeMatch` | `string` — one of `"any"`, `"all"` | optional · default `"any"` | `any`: one charge must meet every charge filter. `all`: each charge filter may be met by a different charge on the record. |
| `statute` | `string` | optional | The start of the published statute citation, ignoring spaces and case: `22.02` matches `22.02(a)(1)`. At least 2 characters. Example `"22.02"`. |
| `chargeText` | `string` | optional | Text that appears anywhere in the published charge description, ignoring case. At least 2 characters. Example `"assault"`. |
| `custodyStatus` | `array of string` — one of `"in_custody"`, `"released"`, `"on_parole"`, `"on_probation"`, `"active_warrant"`, `"wanted"`, `"registered"`, `"disposed"`, `"absconder"`, `"deceased"`, `"excluded"` | optional | The record's custody status. With `unknown: "keep"` a record whose status is unknown also passes. |
| `offenseDate` | [DateRange](https://offendersearch.app/docs/criminal/filtering#object-daterange) | optional | The record's latest offense date must fall in this range. |
| `filedDate` | [DateRange](https://offendersearch.app/docs/criminal/filtering#object-daterange) | optional | The record's latest filing date must fall in this range. |
| `dispositionDate` | [DateRange](https://offendersearch.app/docs/criminal/filtering#object-daterange) | optional | The record's latest disposition date must fall in this range. |
| `lookbackYears` | `integer` | optional | The latest of the record's offense, filing and disposition dates must be within this many years of today. A whole number from 1 to 100. Example `7`. |
| `hasPhoto` | `boolean` | optional · default `false` | `true` keeps only records with a published photograph. |
| `sources` | `array of string` | optional | Keep only records from these source codes. Example `["TX-HARRIS-DC"]`. |
| `excludeVacatedOrSealed` | `boolean` | optional · default `false` | `true` leaves out records marked `normalized.vacatedOrSealed`. By default they are returned, marked. |
| `unknown` | `string` — one of `"keep"`, `"exclude"` | optional · default `"keep"` | What `severity`, `outcome`, `convictedOnly`, `custodyStatus` and the date filters do with a value that is not known. `keep` returns the record and counts it in `counts.unknownKept`; `exclude` removes it and counts it in `counts.filteredOut`. |

## The DateRange object — date filter fields

An inclusive ISO date range. Send `from`, `to` or both; `from` after `to`, a non-ISO value or an impossible date is `422 invalid_date_range`.

Returned or accepted by [`POST /v1/criminal/search`](https://offendersearch.app/docs/criminal/search#reference-post-v1-criminal-search).

| Field | Type | Required / default | Description |
| --- | --- | --- | --- |
| `from` | `string (date)` | optional | First date in the range. Example `"2019-01-01"`. |
| `to` | `string (date)` | optional | Last date in the range. Example `"2026-10-23"`. |

## The Location object — residence and jurisdiction fields

One place in `locations[]`. It needs at least one of `state`, `county`, `city`, `zipcode`, or a radius (`lat`, `lng` and `radiusMiles` together). Any other key is `422 invalid_location`.

Returned or accepted by [`POST /v1/criminal/search`](https://offendersearch.app/docs/criminal/search#reference-post-v1-criminal-search).

| Field | Type | Required / default | Description |
| --- | --- | --- | --- |
| `kind` | `string` — one of `"residence"`, `"jurisdiction"`, `"any"` | optional · default `"any"` | `residence` matches where the person lives (the published address). `jurisdiction` matches where the record is (the court, jail or agency's state and county). `any` matches either. A radius, `city` and `zipcode` describe a residence: on `jurisdiction` they are `422 invalid_location`, and on `any` they test the residence only. |
| `state` | `string` | optional | Two-letter state code. Example `"TX"`. |
| `county` | `string` | optional | County name; `Harris` and `Harris County` match the same county. Example `"Harris"`. |
| `city` | `string` | optional | City of the residence, matched exactly, ignoring case. Example `"Houston"`. |
| `zipcode` | `string` | optional | Five-digit ZIP of the residence. A ZIP+4 is read as its first five digits; `zip` is accepted as another name for this key. Example `"77060"`. |
| `lat` | `number` | optional | Latitude of the radius centre, -90 to 90. Requires `lng` and `radiusMiles`. Example `32.78`. |
| `lng` | `number` | optional | Longitude of the radius centre, -180 to 180. Requires `lat` and `radiusMiles`. Example `-96.8`. |
| `radiusMiles` | `number` | optional | Miles from `lat`/`lng` to the person's published residence, 0.1 to 100. Above 100 is `422 radius_too_large`; below 0.1 is `422 invalid_location`. A residence without coordinates cannot be tested and counts as `noResidence`. Example `25`. |

## The SearchFacets object — facet counts on a filtered search

Counts over every record that passed the filters: the whole result, not the page. Each key maps a value to a number of records.

Returned or accepted by [`POST /v1/criminal/search`](https://offendersearch.app/docs/criminal/search#reference-post-v1-criminal-search), [`GET /v1/criminal/searches/{searchId}`](https://offendersearch.app/docs/criminal/async#reference-get-v1-criminal-searches-searchid).

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| `recordCategory` | `object` |  | Records by `normalized.recordCategory`. Example `{"court":9,"jail":5}`. |
| `severity` | `object` |  | Records by their highest charge severity; `unknown` when none is classified. Example `{"felony":2,"misdemeanor":9,"unknown":3}`. |
| `outcome` | `object` |  | Records by outcome class; a record with several outcomes counts once under each. Example `{"convicted":6,"dismissed":4,"pending":4}`. |
| `jurisdiction.state` | `object` |  | Records by the state where the record is; the 60 largest. Example `{"TX":12,"OK":2}`. |
| `chargeCategories` | `object` |  | Records by charge category; a record with several categories counts once under each. Example `{"traffic":7,"theft":3,"assault":2}`. |
| `custodyStatus` | `object` |  | Records by `normalized.custodyStatus`. Example `{"released":10,"in_custody":4}`. |

---

## Related

- Previous: [Search - POST /v1/criminal/search](https://offendersearch.app/docs/criminal/search.md)
- Next: [Matching, confidence & partial names](https://offendersearch.app/docs/criminal/matching.md)
- Index: [Criminal Search API reference](https://offendersearch.app/docs/criminal.md)
