Skip to content
Last updated

Webhooks

Webhooks let you receive lifecycle events from Checkr Tenant in near-real-time instead of polling the API. When a subscribed event happens, Checkr Tenant sends an HTTP POST to the URL you registered, with a JSON payload describing the event.

Available events

All webhook events are listed below. More will be added over time and your endpoints will start receiving new event types automatically. Design your handler to ignore events it doesn't recognize.

EventFires when
order.applicant.visitedThe applicant visits the apply link for an order at any time before they complete the application.
order.applicant.startedThe applicant consents to and starts the screening application.
order.applicant.completedThe applicant finishes and submits the application.
report.product.completedA product finishes processing and results are available on the report.
report.completedAn order has finished processing and the full report is available.

Registering an endpoint

Webhook endpoints are managed from the Developer settings page in your dashboard. Each endpoint is scoped to a single organization and receives every event your organization emits — there is no per-event filtering yet.

When you create a webhook you also receive a signing secret, used to verify incoming requests. Save it somewhere durable — it is shown once at creation time and cannot be retrieved later.

URL requirements

Your endpoint URL must:

  • Use HTTPS.
  • Be reachable from the public internet. URLs pointing at localhost, private networks, or other internal addresses are rejected.

Live vs. test mode

Each webhook is registered in either live or test mode, and only receives events for resources that match its mode:

  • Live — receives events for live (production) resources.
  • Test — receives events for test-mode resources only.

This lets you exercise your webhook handler end-to-end against test-mode resources before pointing real production traffic at it.

Testing connectivity

Use the Test action on the dashboard to send a bare connectivity probe to your URL — a POST with no body and no signature. Your endpoint should respond with any 2xx status to indicate it is reachable. The probe is not a real event delivery and is not retried.

Delivery

Each delivery is an HTTP POST from Checkr Tenant to the URL you registered:

FieldValue
MethodPOST
Content-Typeapplication/json
User-AgentCheckrTenant/1
Tenant-SignatureSignature header (see below)

A delivery is considered successful when your endpoint responds with a 2xx status code. Anything else — non-2xx responses, network errors, or timeouts — is treated as a failure and retried with exponential backoff. Your endpoint should be idempotent: the same event id may be delivered more than once.

Event payload

Every webhook request body has the same envelope:

{
  "id": "evt_K9dM2pXqR4vN8tLZbWyHJa",
  "object": "event",
  "type": "report.completed",
  "created_at": "2026-04-29T17:42:13Z",
  "data": {
    "id": "rp_F3hQ7wEsLp2xBnVcRuMyTk",
    "order_id": "ord_WHImYp5RjqUxBowWilloQ"
  }
}
FieldDescription
idUnique event id (evt_…). Stable across retries — use it for idempotency on your side.
objectAlways event.
typeEvent type (e.g. report.completed). See Available events.
created_atUTC timestamp the event was created, in ISO-8601 format. Use this for ordering — delivery order is not guaranteed.
dataEvent-specific payload. Shape varies by event type — see Data shape per event below.

Data shape per event

The shape of data depends on the event type:

Eventdata fields
order.applicant.visitedid (applicant id), order_id
order.applicant.startedid (applicant id), order_id
order.applicant.completedid (applicant id), order_id
report.product.completedid (product result id), report_id, product (snake case product name e.g. criminal_history)
report.completedid (report id), order_id

For report events fetch the full report from GET /reports/{id} when you need its contents.

Verifying signatures

Every delivery includes a Tenant-Signature header so you can verify the request came from Checkr Tenant and was not modified in transit:

Tenant-Signature: t=1714414933,v1=8d2b...c4f1

v1 is the hex-encoded HMAC-SHA256 of <t>.<raw_request_body>, computed with your endpoint's signing secret as the key. Recompute it on your side and compare against v1 using a constant-time comparison. Read the raw request body before any JSON parsing — re-serialization changes the bytes you HMAC.