OffenderSearch
Developers · SDKs

Background check SDKs: Python, Node.js and a CLI.

Official clients for the background check API: pip install offendersearch, npm install @offendersearch/sdk, and the offendersearch command. One method per documented endpoint, typed responses and errors, retries that honour Retry-After, a webhook verifier, and a sandbox key that makes every example free to run.

25 free calls · No card · $0.15 a call, $0.11 past 2,000 a monthNo code? Run the same search in the screening dashboard ›
pip install offendersearch

from offendersearch import OffenderSearch
client = OffenderSearch()                     # OFFENDERSEARCH_API_KEY; os_test_ → sandbox
r = client.search({"firstName": "Jordan", "lastName": "Rivera", "dob": "1988-04-12"})
print(r["status"], r["counts"]["records"])  # complete 0
What you get

Background check SDK — Two packages and a CLI, one API surface

offendersearch (PyPI)

Python 3.9+, zero dependencies, typed TypedDict responses, typed exceptions, a transport= seam for httpx or tests. Tutorial: background check API in Python.

@offendersearch/sdk (npm)

Node 18+, ESM and CommonJS, bundled TypeScript types, zero runtime dependencies, fetch-based with an injectable fetch. Tutorial: background check API in Node.js.

offendersearch (CLI)

Ships in the npm package: search, criminal, record, monitors, verify-webhook. JSON out, so it composes with jq.

client.search(query, …)            POST /v1/search                 client.criminal.search(query, …)   POST /v1/criminal/search
client.search_async / searchAsync  POST /v1/searches               client.criminal.search_pages       every page
client.get_search / getSearch      GET  /v1/searches/{id}          client.criminal.batch              POST /v1/criminal/batch
client.wait                        poll until complete             client.criminal.get_record         GET  /v1/criminal/records/{id}
client.batch                       POST /v1/batch                  client.criminal.sources            GET  /v1/criminal/sources
client.get_record / getRecord      GET  /v1/records/{id}           client.monitors.create             POST /v1/monitors
client.report                      POST /v1/report (PDF)           client.monitors.alerts             GET  /v1/monitors/{id}/alerts
client.evidence_pdf / evidencePdf  live evidence capture (PDF)     client.map.viewport                GET  /v1/map/viewport
client.clearances.*                /v1/clearances                  client.fcra.*                      /v1/fcra/* (approved partners)
webhooks.verify / verifyWebhook    X-Offendersearch-Signature      typed errors                       401 402 403 404 422 429 504 5xx

Both packages cover every documented path in the API reference — registry search, criminal records, batch, async, reports and evidence, clearances, monitors, the Map API and the FCRA orders API — and a test in the repository fails when the contract gains a path neither SDK has.

Install

pip install offendersearch · npm install @offendersearch/sdk — Install and the first call

Both packages read OFFENDERSEARCH_API_KEY. A key that starts with os_test_ sends every request to the sandbox, where fixed sample people answer the same way every time and nothing is billed; a live key goes to the live host. The hero above is the whole first call in each language — the synthetic subject Jordan Rivera, 1988-04-12 returns a complete answer with zero records, which is the clear case you want to see first. Create a key to run it; 25 live calls are free, no card.

Responses

Typed background check responses — matchState, counts and record types in your editor

The two fields that drive every decision are typed in both languages: matchState on each record (dob_match, year_match, age_match, or null when you sent no date) and counts.sourcesIncomplete on the response, which is the one number that means something may be missing. Criminal records carry recordType — court_case, jail_booking, doc_inmate, warrant, healthcare_exclusion — so a booking is never read as a conviction.

NeedPythonNode.js
One registry searchclient.search(query)client.search(query)
Criminal records, pagedclient.criminal.search_pages(query)for await (const p of client.criminal.searchPages(query))
Async + waitclient.search_async(…); client.wait(id)client.searchAsync(…); await client.wait(id)
Batch of 1,000client.batch(rows)client.batch(rows)
Report PDFclient.report(search_id=…) → bytesclient.report({ searchId }) → Buffer
Monitor + alertsclient.monitors.create(…); .alerts(id)client.monitors.create(…); .alerts(id)

Field meanings: the record object and the criminal record object; match states in the matching reference.

Webhooks

Verify background check webhooks — One signature scheme, one function

Monitor alerts and FCRA events arrive with X-Offendersearch-Signature: t=<unix>,v1=<hex>, an HMAC-SHA256 over "<t>.<body>" with the secret issued when you created the monitor or endpoint. Both SDKs verify it in constant time with a five-minute replay window, on the raw body bytes.

from offendersearch import webhooks
ok = webhooks.verify(secret, request.headers["X-Offendersearch-Signature"], raw_body)

Try it without writing code: the webhook tester signs sample events and checks your verification. The scheme is explained in webhook example and API signature.

Start free ›25 free calls, no card.
Errors & retries

Background check API errors in the SDKs — Typed, with Retry-After honoured

Every non-2xx answer becomes a typed error with the HTTP status, the API’s machine code when it sent one, and the human message. Both clients retry 429, 502, 503 and 504 (and a dropped connection) up to three times, waiting the Retry-After seconds the API names, with exponential backoff otherwise. Nothing else is retried: a 422 is a contract — the request was refused with a sentence you can show a user — and a 401 is yours to fix.

ClassStatusMeaning
AuthenticationError401Missing or invalid X-API-Key
PaymentRequiredError402Billing or a subscription is needed
ForbiddenError403The key may not do this
NotFoundError404No such search, record, monitor or order
ValidationError400 · 413 · 422Refused, nothing ran; .code and the field errors say why
RateLimitError429Nothing ran or was billed; .retryAfter / .retry_after
DeadlineError504A deadline you set was hit, or incomplete_no_results
ServerError5xxAlready retried; .requestId for support

The catalogue and both error envelopes are in the errors reference and API errors, explained.

Sandbox

Background check SDK sandbox — Free, fixed answers, same shapes as production

The sandbox is a separate host with the same paths and response shapes. It answers from a fixed cast of sample people — Exact Match (1980-01-01) is a DOB-verified registry hit, Felony Record (1975-06-15) a closed felony case, Clear Visitor a clean answer — so your tests are deterministic, your CI runs without a card, and a monitor you create there files its alert at once. Mint up to three os_test_ keys from the dashboard; every scenario is listed on the sandbox reference.

Support

SDK versioning and support — What we promise about the packages

  • Semantic versioning. A breaking change to a method signature is a major version; a new endpoint or field is a minor one.
  • Both packages release together with one version number, from one repository, with a contract test that fails when the API gains a path neither SDK covers.
  • Python 3.9+ and Node 18+ are supported until each runtime’s own end of life.
  • No runtime dependencies in either package, so an upgrade never pulls a transitive surprise.
  • The API itself is versioned at /v1; additions are non-breaking and listed in the changelog.
  • Source is published with the first release under the OffenderSearch organisation; issues and questions go to support@offendersearch.app.
Scope

What the background check SDKs do not do

  • They do not make a hiring or housing decision FCRA-compliant on their own; those run as orders through FCRA Partner Access, reached via client.fcra once approved.
  • They do not take or trace a Social Security number. Searches are by name, date of birth and place.
  • They do not include driving records, drug tests, credit, or education and employment verification — the API is public records: 58 US sex offender registries and criminal court, jail, prison, warrant and exclusion-list records.
  • They do not run in a browser or a mobile app. The key stays on your server.
  • There is no Go, Ruby, PHP or Java package yet. The API is plain HTTPS and JSON; the Postman collection and the reference cover any language.
FAQ

Background check SDK questions

Which languages have an official background check SDK?

Python (pip install offendersearch) and Node.js / TypeScript (npm install @offendersearch/sdk, which also installs the offendersearch CLI). Any other language uses the REST API directly.

Do the SDKs cost anything?

No. Both are MIT licensed. API use is $0.15 a call ($0.11 past 2,000 a month), 25 free calls on sign-up, no card; details on the pricing page.

Can I use the SDKs with the sandbox?

Yes — pass an os_test_ key and every request goes to the sandbox automatically, or set sandbox=True / { sandbox: true } explicitly.

Do the SDKs support the FCRA orders API?

Yes, under client.fcra: end users, search plans, orders, scope, reports, receipts, evidence, disputes, invitations, consent documents, branding, adverse action, revisions, monitors, webhook endpoints and events. It works on the sandbox for everyone and on the live host for approved partners.

How do the SDKs handle rate limits?

A 429 means nothing ran and nothing was billed. The client waits the Retry-After seconds and retries, up to three times by default, then raises RateLimitError with retry_after / retryAfter set.

Is there a Go, Ruby, PHP or Java SDK?

Not yet. The REST API is plain HTTPS and JSON, documented with an OpenAPI 3 spec, so any HTTP client works; tell support@offendersearch.app which language you need next.

Can I generate a client from the OpenAPI spec instead?

Yes. The spec is served at /openapi.json and /openapi.yaml; the API reference is rendered from it. The official SDKs add retries, typed errors, pagination and webhook verification on top.

Where do I report a bug in an SDK?

Email support@offendersearch.app with the package version, the method called, and the request id from the error (requestId / request_id). Source is published with the first release.

Background check SDKs — Install one and run the first search

pip install offendersearch or npm install @offendersearch/sdk, create a key, paste the example. 25 calls are free.