Async jobs & webhooks
When a job will take longer than a request, you get an id. How to poll it, how webhooks differ by product, and how to make retries safe.
The pattern
- Submit. The endpoint answers with a
searchId(or the product's id) and the path to poll. The key differs per entry point —resultsUrlonPOST /v1/searches(202),pollon a Sex Offender live search that went async (200,status: "pending") and on a criminal202,pollUrlon alive.evidence202— so read the one your entry point documents. - Persist the id immediately. It is the only handle to the work and to its bill.
- Poll.
GETthe poll path every 2–5 seconds and cap your attempts (a few minutes). Sex Offender:statuspending/runningwhile it works, the full envelope when done,errorif the job failed (nothing billed). Criminal:202with a JobRecord (result: null) while pending,200with the envelope underresultwhen complete,422if the stored query was refused when run. - Or be told. Where the product supports it, give a
webhookUrland the finished envelope is POSTed to you.
| Product | Async entry | Poll | Webhook |
|---|---|---|---|
| Sex Offender | POST /v1/searches (202, resultsUrl); POST /v1/search with more live sources than run inline (200, status: "pending", poll); live.evidence: "pdf" (202, pollUrl) | GET /v1/searches/{searchId} (API key, not a session) | webhookUrl on POST /v1/searches only; not signed — put a secret token in your URL. Details. |
| Criminal | POST /v1/criminal/search with more than two live sources (202, poll) | GET /v1/criminal/searches/{searchId} — 202 while pending, 200 with result | Poll only. Details. |
| Monitoring | Alerts are produced by the daily evaluation | GET /v1/monitors/{monitorId}/alerts | Alert deliveries to channels.webhookUrl; see Delivery for the signature header and the current signing status. |
| FCRA | Orders progress asynchronously | GET /v1/fcra/orders/{order_id} | Signed events to the partner's endpoint; redelivery via POST /v1/fcra/events/{event_id}/resend. Details. |
Idempotency
The APIs do not read an idempotency header. Every accepted async submission is a new job, billed at acceptance. Make retries safe on your side: persist the id from the acknowledgement before anything else, and on a dropped connection recover by polling that id instead of submitting again. A 429 or a 5xx on submission means no job was accepted, so submitting again is safe.
Receiving a webhook
- Answer
2xxquickly and do the work after; a slow handler is treated as a failed delivery. - Treat deliveries as at-least-once: key your processing on the event or search id.
- Where a product signs deliveries, verify the signature on the raw body before trusting it; where it does not (sex offender search
webhookUrl), authenticate with a secret token in the URL and fetch the result from the API if you need certainty.