Offendersearch
Background check API · Integration

How to integrate a background check API

Eight steps from an empty project to a production integration: keys, the first call, matching rules, async and webhooks, batch, monitoring, errors, and keeping the evidence. Every step links to the reference.

curl https://api.offendersearch.app/v1/search \
  -H "X-API-Key: $OFFENDERSEARCH_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "query": { "firstName": "John", "lastName": "Doe", "dob": "1980-04-12" } }'
Step by step

The eight steps

1. Create a key and keep it server-side

Sign up and create a key in the dashboard — it works immediately on the 25-search free trial. Send it as X-API-Key from your server, never from a browser or mobile app. Use one key per environment so you can rotate staging without touching production. Details: authentication.

2. Make the first call

POST /v1/search searches the sex offender registries; POST /v1/criminal/search searches criminal records. Same key, same request shape. Send a first and last name and — whenever you have it — a full date of birth. See the quickstart.

3. Decide with the match state, not the name

Every record says how it matched: full date of birth, birth year, age, or name only. Automate only on full-date matches and route everything else to a person. Treat any source in sourceStatus that did not answer as “not clear”. The matching rules and result completeness pages cover each case.

4. Use async for long searches

Live re-verification and broad searches can take longer than a request should wait. POST /v1/searches returns a searchId at once; poll GET /v1/searches/{id} or pass a webhookUrl and the finished result is posted to it. See async and webhooks.

5. Batch your lists

Screen a roster in one request with POST /v1/batch — CSV or JSON, up to 1,000 rows per call, billed per row. Criminal records have their own POST /v1/criminal/batch. See batch.

6. Monitor instead of re-screening

For people you keep — long-term staff, volunteers, contractors in a program you are entitled to screen — a monitor watches for changes and alerts you, for $3 a person a month. Locations can be watched too. See the Monitoring API.

7. Handle errors like a payment API

A 422 means the input was rejected — fix it, don’t retry. A 429 carries Retry-After. A 200 can still describe an incomplete search, which is why step 3 reads sourceStatus. See errors.

8. Store the evidence with the decision

Keep the record identifiers and source citations with whatever your team decided, so a later review can see exactly what was found. Request a verification PDF only when a document is needed for a file.

Code

The integration in code

The pieces most integrations need, in the order you will write them.

// One rule set for every record the API returns.
function triage(record) {
  if (record.matchState === 'dob_match') return 'auto';      // full date of birth agreed
  if (record.matchState === 'year_match' ||
      record.matchState === 'age_match') return 'review';    // a person looks
  return 'review';                                           // name only: never automatic
}

// An unanswered source means "not clear", never "clear".
const incomplete = response.sourceStatus.filter((s) => !s.ok || s.incomplete);
curl https://api.offendersearch.app/v1/searches \
  -H "X-API-Key: $OFFENDERSEARCH_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "query": { "firstName": "John", "lastName": "Doe", "dob": "1980-04-12" },
    "webhookUrl": "https://yourapp.example/hooks/offendersearch"
  }'
# -> 202 { "searchId": "srch_9f2a7c", ... }
# poll GET /v1/searches/srch_9f2a7c, or receive the finished result at webhookUrl
curl https://api.offendersearch.app/v1/batch \
  -H "X-API-Key: $OFFENDERSEARCH_KEY" \
  -H "Content-Type: text/csv" \
  --data-binary $'firstName,lastName,dob,state\nMaria,Garcia,1980-04-12,TX\nJohn,Doe,,NJ'
curl https://api.offendersearch.app/v1/monitors \
  -H "X-API-Key: $OFFENDERSEARCH_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "product": "sex-offender", "type": "person",
        "person": { "name": "Maria Garcia", "dob": "1980-04-12" },
        "channels": { "email": ["alerts@yourapp.example"] } }'
switch (res.status) {
  case 401: throw new Error('Check the X-API-Key header');
  case 402: throw new Error('Billing is not enabled on this account');
  case 422: return { declined: (await res.json()).detail };  // fix the input, don't retry
  case 429: return retryAfter(res.headers.get('Retry-After')); // back off, then retry
}
Before you ship

Integration checklist

  • The key lives on the server and is different per environment
  • Every request sends a full date of birth when you have one
  • Only dob_match records are acted on automatically
  • Unanswered sources are shown as “not clear”, never as “clear”
  • Long searches use POST /v1/searches, not a long-held request
  • 422 is surfaced to the user to fix; 429 backs off using Retry-After
  • Record identifiers and citations are stored with each decision
  • Hiring and tenant decisions go through FCRA workflows, not the standard search

Making a hiring or tenant decision? Use an FCRA workflow.

FCRA workflows are built primarily for tenant screening and hiring decisions. If a result will help decide whether to hire someone or rent to them, the check has to run as an FCRA-regulated consumer report, with a permissible purpose, consent, accuracy controls and a dispute path for the person. Our standard search and API are not a consumer report. FCRA workflows run through FCRA Partner Access, for background check companies and screening platforms under a written FCRA agreement.

FCRA pricing is quoted per partner, so contact us for pricing.

Contact us for FCRA pricingHow FCRA workflows work

FAQ

Background check API integration questions

How long does it take to integrate a background check API?

The first working call takes minutes. A production integration — matching rules, async handling, batch and error handling — is typically an afternoon to a couple of days, depending on how much of your review workflow already exists.

Do I need a sandbox?

You can build against the free trial: 25 real searches, no card. Keys carry no entitlements, so create a separate key per environment and revoke any one without affecting the others.

Is there an SDK?

The API is plain REST with JSON, so any HTTP client works, and the OpenAPI specification is published for generating a typed client in your language. The docs show curl, Node and Python for every endpoint.

Should I call it from the browser?

No. Call it from your server and keep the key secret. Show your users the outcome your workflow decides on, not the raw records.

Can I migrate from another sex offender search API without rewriting my parser?

Yes. POST /v1/compat/sexoffender accepts the parameters and returns the envelope of legacy sex offender search APIs, so a switch is a base URL and key change. The migration guide maps every field.

What about hiring and tenant decisions?

Those are FCRA-regulated, so they run as FCRA orders through FCRA Partner Access rather than on the standard search endpoints. The FCRA API has its own order workflow, webhooks and dispute endpoint — contact us for pricing.

Related: background check API · background check API pricing · criminal background check API · employment background check API · API documentation

Make the first call in the next five minutes

25 free searches on real data, no card.

The Offendersearch APIs

One account, one key, one bill — the sex offender registry and criminal records, side by side.

Sex offender registry

Criminal records

Build with it