The PDF guide includes additional details, diagrams, and examples not covered on this page.🔗 Download OpenAPI Spec
Import into Postman, Swagger UI, or any OpenAPI-compatible tool.
Unlike competitors with weekly updates, our Sex Offender Registry API features real-time updates, sub-200ms response times, and an exclusive 99.9% Uptime SLA, making it the reliable choice for background checks, security platforms, and public safety applications.
Base URL
The standard endpoint is not intended for PHI/ePHI workflows. Approved Enterprise HIPAA/BAA workflows use a dedicated account-enabled access path with header authentication and require an executed Business Associate Agreement (BAA). Contact us for details.
Authentication
For quick demos, pass your API key as a query parameter key.
Send your API key in X-API-Key or Authorization: Bearer, and send search fields in a JSON body. This keeps credentials and search parameters out of browser history, referrers, screenshots, and many logging systems.
Content-Type: application/json
X-API-Key: {YOUR_API_KEY}
X-Request-Id: 550e8400-e29b-41d4-a716-446655440000
{
"firstName": "Alice",
"lastName": "Smith"
}
The same fields listed in Query Parameters can be sent as JSON properties in POST requests. For compatibility, the standard endpoint also accepts key in the JSON body; the production example above uses headers. GET requests remain supported for demos and compatibility. Approved Enterprise HIPAA/BAA workflows see a separate documented path with a JSON body. Contact us for details.
Get a free API key and start with 50 free requests each month.
💡 Using an AI assistant? You can also access full records via our MCP server with the same API key — no code needed.
Request IDs
For production troubleshooting, send an optional X-Request-Id request header with a unique opaque ID from your system. Use a UUID or similar correlation ID; do not include names, email addresses, dates of birth, member IDs, patient IDs, search values, or other sensitive data. Values may contain letters, numbers, ., _, :, and -, up to 64 characters.
The API returns X-Offenders-Request-Id as the Offenders.io-generated request ID on every response. If you send X-Request-Id, the response X-Request-Id echoes your value; otherwise it mirrors the Offenders.io request ID. Include both IDs in support tickets when available. If your client times out before receiving response headers, provide the X-Request-Id you sent plus the exact UTC timestamp.
Search Modes
Regular Search
Targeted lookups by name, DOB, address, zip code, or any combination. Structured address searches use fuzzy address matching by default and are billed at the fuzzy search rate. At least one query param is required.
When a DOB is supplied, Regular Search uses indexed, precision-aware matching: exact records must match the full date, year_month records must match the same year and month, and year records must match the same year. Records with missing or unknown DOB are not included by the Regular indexed DOB path.
Extensive Mode +$0.05/call
Add &mode=extensive to a full-name search to run live source-level enrichment and receive additional jurisdiction data where supported. The standard Extensive request is name-led: send firstName and lastName, then add other supported parameters as filters when needed.
For a structured full-name Extensive search, a supplied DOB is applied to the live name-led candidates using the same precision-aware rules. Candidates with missing or unknown DOB may remain as safety-net matches. Because Extensive Mode uses additional live candidate sources and name variants, it can return a different number of records than the same Regular request; it is not only a response-field enrichment switch.
- aliases — searches all known names and aliases on file
- locations — full address history including residential, employment, and secondary addresses
- stateData — jurisdiction-specific registry details including offenses, vehicles, registration status, and more; field availability varies by jurisdiction
⚠ Slower response (~2s+). Has rate limit — not for batch processing.
GIS / Geospatial Search EXCLUSIVE
Find offenders within a radius of any GPS coordinate. The only API with native geospatial search. Can combine with name/city filters. GIS search includes automatic failover to secondary infrastructure for high availability.
Fuzzy Matching +$0.02/call
Add &fuzzy=true to a name search to enable typo-tolerant matching. Structured address searches are fuzzy by default. Fuzzy matching is generally available, billed at +$0.02 per fuzzy call, and works with or without mode=extensive. It runs on a dedicated search cluster separate from the primary API, providing additional geo-redundancy and infrastructure redundancy. Choose the request shape that matches your input.
Example Matches
These examples illustrate records that may match. Actual results depend on the registry data indexed for each person and any additional filters you send.
| Search input | May match | Why |
|---|---|---|
Jon Smyth | John Smith | One spelling edit in each name |
Rob Johnson | Robert Johnson | Partial or prefix first name |
Bob Smith | Robert Smith | When Bob is present in the record's nickname or alias index |
Alex Smith Johnson | Alex Smith-Johnson | Hyphenated or space-separated surname variants |
123 Main Dr | 123 Main Drive | Common street-suffix abbreviations in structured address search |
Structured Name Search (firstName / lastName)
Best when name fields are separate. fuzzy=true applies to either provided name field, but a structured search requires at least two search parameters overall. For example, send both firstName and lastName, or combine one name with state, zipcode, dob, or GIS coordinates. Each provided name is matched against the correct field for more precise results.
Free-Text Search (q)
Best when you have a single combined name string, or want to search across names and addresses together. Searches across first name, last name, aliases, address, city, and zip code in one query.
Structured Address Search (address)
Best when you have street-address fields separate from names. The address parameter is fuzzy by default, handles common street suffix abbreviations, can be combined with city, state, zipcode, and dob filters, and is billed at the fuzzy search rate. Use either q or address, not both; address also cannot be combined with lat/lng GIS coordinates.
Query Parameters
| Parameter | Type | Description | Example |
|---|---|---|---|
key | string | Your API key (required). If using POST, you can send it in X-API-Key or Authorization: Bearer instead. | YOUR_API_KEY |
firstName | string | First name of offender | Alice |
lastName | string | Last name of offender | Smith |
dob | string | Date of birth (YYYY-MM-DD). Matching respects source precision: exact records match the full date, year_month records match the same year and month, and year records match the same year. Regular indexed DOB searches exclude missing or unknown DOB; structured full-name Extensive searches may retain those records as safety-net candidates. | 1990-01-15 |
city | string | Residence city | San Francisco |
state | string | Residence state (full name or 2-letter code) | CA |
zipcode | string | Residence zip code | 94104 |
address | string | Street address search. Fuzzy by default; supports common address abbreviations and is billed at the fuzzy search rate (+$0.02/call). Do not combine with q or lat/lng. If combined with mode=extensive, also send firstName and lastName so enriched name results can be filtered by address. | 123 Main St |
lat | number | Latitude (GIS search) | 30.967 |
lng | number | Longitude (GIS search) | -91.116 |
radius | number | Radius in miles (default 1, max 100) | 5 |
mode | string | Set to extensive for live aliases and enriched state-level data. Structured full-name searches can use additional live candidates and may retain missing or unknown DOB safety-net matches, so result counts can differ from Regular Search (+$0.05/call) | extensive |
fuzzy | boolean | Enable typo-tolerant fuzzy matching (+$0.02/call) | true |
q | string | Free-text search across names, aliases, address, city, and zip code. Use with fuzzy=true instead of firstName/lastName. | John Smith San Francisco |
prefixMatch | string | Prefix match on firstName or lastName | firstName |
createdAtStart | string | Filter by when the registrant first appeared in our system. Use this to create alerts for new offenders (e.g., new registrants in a zip code this month). | 2026-01-01 |
createdAtEnd | string | Filter by first appearance in system | 2026-01-31 |
updatedAtStart | string | Filter by last update in system | 2026-01-01 |
updatedAtEnd | string | Filter by last update in system | 2026-01-31 |
faceId | string | Face ID from Facial Search API | 4d8ade05... |
uuid | string | Pull single record by UUID | 807ff46d... |
personUuid | string | Pull single record by Person UUID | 83425e56... |
page | number | Page number for GIS search pagination. Each page is billed as a separate API call. | 3 |
Response Fields
Each offender object in the offenders array contains:
| Field | Type | Description | Example | Empty |
|---|---|---|---|---|
name | string | Full name including middle name | "JOHN M DOE" | "" |
firstName | string | First name | "JOHN" | "" |
middleName | string | Middle name | "MICHAEL" | "" |
lastName | string | Last name | "DOE" | "" |
aliases | array | Known aliases (Extensive Mode only) | [{"givenName":"JAY","surName":"DOE"}] | [] |
dob | ISO date | Normalized date of birth in UTC when available. Use dobPrecision to distinguish a full date from source-reported year-month, year-only, or unknown values. | "1990-01-15T00:00:00.000Z" | null |
dobPrecision | string | Source precision of dob: exact, year_month, year, or unknown. | "exact" | "unknown" |
address | string | Residence street address | "123 MAIN ST" | "" |
city | string | Residence city | "RICHMOND" | "" |
state | string | Residence state (full name) | "Virginia" | "" |
zipcode | string | Residence zip code | "23219" | "" |
county | string | Residence county | "RICHMOND CITY" | "" |
locations | array | All official addresses (Extensive Mode only) | see Location Object | [] |
sex | string | Registered sex | "Male" | "" |
age | string | Age | "35" | "" |
eyeColor | string | Eye color | "Brown" | "" |
hairColor | string | Hair color | "Black" | "" |
height | string | Height | "5 ft 10 in" | "" |
weight | string | Weight | "180 lbs." | "" |
race | string | Race | "White" | "" |
ethnicity | string | Ethnicity | "Non-Hispanic" | "" |
marks | string | Marks, tattoos, scars | "TAT R ARM, SC L KNEE" | "" |
riskLevel | string | Risk level | "Tier 3" | "" |
crime | string | Crimes committed for registration | "SEXUAL ASSAULT (01/15/2005)" | "" |
registrationDate | ISO date | Date first registered | "2005-03-01T00:00:00.000Z" | null |
offenderUrl | string | URL to source state agency page | "https://example.gov/offender/123" | null |
offenderImageUrl | string | Profile image URL | "https://example.gov/photo/123" | null |
lat | number | Latitude of address | 37.5407 | -1 |
lng | number | Longitude of address | -77.4360 | -1 |
jurisdiction | string | Jurisdiction code (e.g. CA, WV) | "VA" | null |
isAbsconder | boolean | Known absconder status | false | null |
isPredator | boolean | Classified as sexual predator or sexually violent offender | true | null |
offenderImageUrlR2 | string | CDN-hosted profile image URL (faster, more reliable) | "https://img.offenders.io/photo/abc123.jpg" | null |
createdAt | ISO date | When the record first appeared in our system | "2025-06-15T08:30:00.000Z" | null |
updatedAt | ISO date | Last update timestamp | "2026-03-31T12:00:00.000Z" | null |
uuid | string | Unique record identifier | "807ff46d-1234-5678-9abc-def012345678" | "" |
content | string | Pre-formatted HTML summary | "" | |
sources | array | Data source references | [{"id":"nsopw","name":"NSOPW"}] | [] |
page | number | Current page (GIS only) | 1 | 1 |
totalPages | number | Total pages (GIS only) | 3 | 1 |
stateData | object | State agency enriched data (Extensive Mode only) | see stateData Schema | null |
stateData Schema
The stateData object contains structured, jurisdiction-specific data verified in realtime against authoritative sources where supported. Search coverage includes 183 U.S. registry jurisdictions spanning all 50 states, DC, U.S. territories, and tribal jurisdictions; stateData availability and fields vary by jurisdiction.
| Field | Type | Description | Example |
|---|---|---|---|
stateOffenderId | string | State registry ID | "SO-123456" |
status | string | Registration status | "Active", "Incarcerated" |
designation | string | Offender classification | "Sexually Violent Offender" |
complianceStatus | string | Registration compliance | "COMPLIANT", "NON-COMPLIANT" |
offenses | array | Criminal convictions (see Offense Object below) | see below |
aliases | array | Known aliases | ["JOHN DOE", "J DOE"] |
locations | array | Official addresses (see Location Object below) | see below |
vehicles | array | Registered vehicles | [{"plate":"ABC1234","make":"Toyota","model":"Camry","year":"2015","color":"White"}] |
victimInfo | array | Victim information | [{"gender":"Female","minor":true}] |
initialRegistrationDate | string | First registration date | "2000-12-19" |
registrationEnds | string | Registration end date | "2030-12-31" |
isLifetimeRegistration | boolean | Lifetime registration flag | true |
lastVerificationDate | string | Last verification date | "2025-02-20" |
addressVerificationDate | string | Last address verification | "2025-02-20" |
judgmentOfConvictionUrl | string | Registry-hosted judgment of conviction PDF URL, when provided by the jurisdiction | "https://sexoffenders.ehawaii.gov/coveredoffender/resource/A3005425__QA.pdf" |
marks | string | Scars, marks, tattoos | "TAT R ARM, SC L KNEE" |
ethnicity | string | Ethnicity | "Hispanic", "Non-Hispanic" |
lawAgency | string | Supervising law enforcement | "HOUSTON POLICE DEPT" |
incarcerationStatus | string | Incarceration/supervision status | "On Parole" |
verificationRequirement | string | Verification frequency | "QUARTERLY" |
employer | string | Employer information | "ACME CORP, CHARLESTON WV" |
school | string | School attendance | "STATE UNIVERSITY" |
comments | string | Additional notes from state registry | "VICTIM WAS A 12 YR OLD FEMALE" |
registrationStartDate | string | Registration start date | "2005-03-01" |
registrationEndDate | string | Registration end date (if not lifetime) | "2030-12-31" |
registrationDuration | string | Registration duration | "25 Years" |
photos | array | Additional offender photos | [{"url":"https://...","date":"2025-01-15"}] |
criminalHistory | array | Full criminal history entries | [{"offense":"BURGLARY","date":"2010-05-01"}] |
Offense Object
| Field | Type | Example |
|---|---|---|
offense | string | "LEWD,LASCIVIOUS CHILD U/16" |
convictionDate | string | "07/02/1998" |
releaseDate | string | "12/27/2006" |
statute | string | "F.S. 800.04" |
victimAge | string | "16" |
victimSex | string | "Female" |
jurisdiction | string | "Miami-Dade, FL" |
adjudication | string | "Adjudicated Guilty" |
caseNumber | string | "CR-2024-0001" |
Location Object
| Field | Type | Example |
|---|---|---|
type | string | "RESIDENTIAL", "WORK" |
streetAddress | string | "123 MAIN ST" |
city | string | "RICHMOND" |
state | string | "VA" |
zipCode | string | "23221" |
fromDate | string | "05/19/2023" |
toDate | string | "08/01/2024" |
latitude | number | 40.7128 |
longitude | number | -74.0060 |
Field availability varies by jurisdiction. Not all fields are present for every record.
Full Example Response
//Response { "offenders": [ { "name": "First M Last", "firstName": "First", "firstName_nicknames": ["firsty", "firs", "1st"], "lastName": "Last", "aliases": [ { "prefix": null, "givenName": "FIR", "middleName": null, "surName": "ST", "suffix": null }, { "prefix": null, "givenName": "FIRST", "middleName": "M", "surName": "LA", "suffix": null }, { "prefix": null, "givenName": "FIRST", "middleName": "NONAME", "surName": "LAST", "suffix": null }, { "prefix": null, "givenName": "X", "middleName": null, "surName": "THE X", "suffix": null } ], "dob": "1900-10-01T00:00:00.000Z", "dobPrecision": "exact", "address": "10000 San Francisco Way", "city": "San Francisco", "state": "California", "zipcode": "94104", "locations": [ { "name": null, "type": "R", "streetAddress": "10000 San Francisco Way", "city": "San Francisco", "county": "California", "state": "CA", "zipCode": "94104", "zipCodeExtension": null, "latitude": 50.12345, "longitude": -34.67890 }, { "name": null, "type": "E", "streetAddress": "200 FL DRIVE", "city": "Miami", "county": "Miami-Daide", "state": "FL", "zipCode": "33129", "zipCodeExtension": null, "latitude": 34.67890, "longitude": -50.12345 } ], "sex": "Male", "age": "123", "offenderUrl": "https://meganslaw.ca.gov/OffenderDisplay.aspx?search...", "offenderImageUrl": "https://meganslaw.ca.gov/NSOPWPI.ashx?f=...&NSOPRFlag=True", "jurisdiction": "CA", "isAbsconder": false, "isPredator": true, "eyeColor": "Green", "hairColor": "Brown", "height": "5'11\"", "weight": "200 lbs.", "race": "White", "marks": "tattoo on r_arm (cross / cover the cross with tribal symbol); tattoo on l_arm (pic of a lady); tattoo on l_arm (something); ...", "riskLevel": "2", "crime": "Crime: 14:81 - Indecent Behavior with Juveniles; Juvenile victim, Conviction date: 2199-09-09, Jurisdiction: California", "registrationDate": "2012-12-31T00:00:00.000Z", "content": "<br><b>Zip Code: </b>94104<br><b>Sex: </b>Male<br><b>Age: </b>123...", "lat": 50.12345, "lng": -34.67890, "sources": [ { "name": "National Sex Offender Public Website", "id": "nsopw", "url": "https://www.nsopw.gov/" }, { "name": "New York State Division of Criminal Justice Services", "id": "criminaljustice.ny.gov", "url": "https://www.criminaljustice.ny.gov/" } ], "updatedAt": "2026-03-05T21:35:42.936Z", "uuid": "5893a310-37ce-58d8-b101-39e76a60e94a", "stateData": { "stateOffenderId": "SO-123456", "status": "Active", "designation": "Sexually Violent Offender", "offenses": [ { "offense": "AGGRAVATED SEXUAL BATTERY", "convictionDate": "11/04/1999", "statute": "18.2-67.3", "jurisdiction": "Richmond Circuit", "victimAge": "Unknown" } ], "aliases": ["JOHN A DOE", "JOHNNY DOE"], "initialRegistrationDate": "2000-12-19", "lastVerificationDate": "2026-02-20", "judgmentOfConvictionUrl": "https://sexoffenders.ehawaii.gov/coveredoffender/resource/A3005425__QA.pdf", "complianceStatus": "COMPLIANT", "isLifetimeRegistration": true, "incarcerationStatus": "On Parole", "lawAgency": "RICHMOND POLICE DEPT", "vehicles": [{"plate":"ABC1234","make":"Toyota","year":"2015"}], "victimInfo": [{"gender":"Female","minor":true}] } } ] }
Result Limits
- Regular Search: 50 records max. Filter by city or zip for better results.
- GIS Search: Radius defaults to 1 mi (max 100 mi). 50 records per page — use
pageandtotalPagesto paginate. Each page request counts as one billable API call. By default, GIS results are limited to records updated within the last 90 days. UseupdatedAtStartto override this window. - Fuzzy Search: Up to 500 records per request. Requires at least two search parameters for structured name search.
Higher limits for name searches can be enabled at no extra cost. All results are returned in a single API call. Contact us to enable this for your account.
Error Handling
| Code | Meaning | Example Response |
|---|---|---|
| 400 | Bad Request — missing, duplicate, too broad, or invalid parameters. Date parameters such as dob must be valid, non-future dates within the supported range. | {"code":400,"message":"Invalid date format for 'dob' parameter"} |
| 401 | Unauthorized — missing or invalid API key | {"code":401,"message":"Missing API key"} |
| 405 | Method Not Allowed | {"code":405,"message":"Method Not Allowed"} |
| 503 | Service Unavailable — search infrastructure temporarily down. GIS and fuzzy searches automatically fall back to secondary infrastructure. | {"offenders":[],"error":503} |
When the error field is present in the response, results may be incomplete or empty. Your application should check for this field and handle accordingly.
Code Examples
JavaScript / Node.js
const res = await fetch( `https://api.offenders.io/sexoffender?key=${API_KEY}&zipcode=94104` ) const { offenders } = await res.json() console.log(offenders[0].name, offenders[0].city)
Python
import requests r = requests.get("https://api.offenders.io/sexoffender", params={ "key": API_KEY, "firstName": "Alice", "zipcode": "94104" }) offenders = r.json()["offenders"]
cURL
curl "https://api.offenders.io/sexoffender?key=YOUR_KEY&lat=30.967&lng=-91.116&radius=2"cURL (POST with Header Auth)
Use X-API-Key, or swap that header for Authorization: Bearer YOUR_KEY.
curl -X POST "https://api.offenders.io/sexoffender" \
-H "Content-Type: application/json" \
-H "X-API-Key: YOUR_KEY" \
-H "X-Request-Id: 550e8400-e29b-41d4-a716-446655440000" \
--data '{"firstName":"Alice","lastName":"Smith","fuzzy":true}'
# Bearer token form also works:
# -H "Authorization: Bearer YOUR_KEY"
Batch Processing
Need to process thousands of records? Use our web-based batch tool at batch.offenders.io — upload a CSV with First Name, Last Name, and optional DOB. See the Batch Processing Guide for details.
Ready to integrate?
Get your free API key and start making calls in minutes — via REST API or MCP server.
Get Free API Key →