Developers
HerPrey API
Last updated · 2026-05-25
HerPrey's case files, offender profiles, and Dossier articles are available programmatically through a small REST API. Designed for journalists, researchers, and other partners who want to query the database from a script, notebook, or downstream system.
Access
The API is gated to the Researcher account tier. Generate a key in your account once your access is provisioned, or contact api@herprey.com to discuss a partnership. Free and standard Subscriber accounts cannot mint keys.
Authentication
Every request needs an Authorization: Bearer <key> header. Keys look like hp_live_a1b2c3... and are 40 characters long.
curl https://herprey.com/api/v1/cases \
-H "Authorization: Bearer hp_live_..."Requests without a valid key return 401 Unauthorized. Keys from accounts without the Researcher tier return 403 Forbidden.
Rate limiting
Each key gets 1,000 requests per hour. Exceeding the limit returns 429 Too Many Requests with a Retry-After header indicating the seconds until your window resets. If you need a higher limit, contact us.
Pagination
List endpoints are cursor-paginated. Pass ?limit=N (1–100, default 20) and ?cursor=<id> to page forward. The response includes pagination.nextCursor — pass it as the next page's cursor. When nextCursor is null, you've reached the end.
Endpoints
Cases
GET /api/v1/cases— list. Filters:?crime=GROOMING,?country=US,?state=CA,?era=TWO_TENS,?year=2014. Sort:?sort=newest|oldest|crimeYear|crimeYearAsc.GET /api/v1/cases/<slug>— single case detail including linked offenders + per-offender verdict / sentence.
Offenders
GET /api/v1/offenders— list. Filters:?occupation=TEACHER,?country=US,?state=CA.GET /api/v1/offenders/<slug>— single offender profile with linked-case summaries.
Dossier articles
GET /api/v1/dossier— list. Filter:?attached=case|offender|standalone.GET /api/v1/dossier/<slug>— single article with body HTML, attached case/offender references, author byline.
Editorial policies that affect the API
Suppressed identities. When our editorial standards require us to withhold an offender's name (see our editorial standards), name comes through as null regardless of your tier. The nameStatus field tells you why — SUPPRESSED or UNKNOWN. Researcher access does not bypass this rule.
Unpublished and deleted records never appear in API responses. The API mirrors what's public on the website.
Example: paging through every case
#!/usr/bin/env python3
import os, requests
key = os.environ["HERPREY_KEY"]
url = "https://herprey.com/api/v1/cases?limit=100"
all_cases = []
while url:
r = requests.get(url, headers={"Authorization": f"Bearer {key}"})
r.raise_for_status()
body = r.json()
all_cases.extend(body["data"])
next_cursor = body["pagination"]["nextCursor"]
url = (
f"https://herprey.com/api/v1/cases?limit=100&cursor={next_cursor}"
if next_cursor else None
)
print(f"{len(all_cases)} cases")Stability
This is API v1. Breaking changes will land under /api/v2 and we'll commit to running v1 for at least 12 months past v2 release. Additive changes (new fields, new endpoints) ship under v1 without notice.
Support
Questions, edge cases, or you want a higher rate limit? Email api@herprey.com.