Webhook Integration Guide
The Theary Background Check API supports webhooks to receive real-time notifications when verifications are completed, require action, or receive inbound responses. This guide covers webhook configuration, security, event types, and integration examples.Overview
Webhooks are HTTP callbacks that notify your application when verification events occur. The API sends POST requests to your configured endpoints with event payloads and HMAC-SHA256 signatures for security verification.Webhook Events
The API sends three types of webhook events:verification.completed- Sent when a verification search reaches a terminal outcome (VERIFIED, NO_RECORD, WRONG_ORG)verification.action_required- Sent when the verification cannot proceed without action (THIRD_PARTY_RECORD, UPSTREAM_ISSUE, SYSTEM_FAILURE, SLA_REACHED, HUMAN_ESCALATION, OTHER)verification.notification- Sent when an inbound notification is received and processed (non-terminal outcomes)
Webhook Configuration
Webhooks can be configured at two levels:Request-Level Configuration
Configure webhooks per verification request:Tenant-Level Configuration
Configure webhooks at the tenant level (applies to all verifications unless overridden): Contact your Theary account manager to configure tenant-level webhook settings.Endpoint Resolution
The API resolves webhook endpoints using the following priority:- Search-specific endpoint: If configured for the search type (e.g.,
EMPLOYMENT), that endpoint is used - Fallback endpoint: If no search-specific endpoint is configured, the fallback endpoint is used
- Tenant-level configuration: If no request-level configuration is provided, tenant-level settings are used
- When a search type is configured with multiple webhook targets, the API will deliver to all matching targets that allow the event.
- If
eventsis omitted on a target, it will receive onlyverification.completed(backward compatible). - Per-target
headersare merged into the request headers. IfbasicAuthis set, anAuthorization: Basic ...header is included.
Webhook Payload Structure
All webhook payloads follow a consistent structure withevent, occurredAt, and data fields. For detailed payload structures and examples, see Webhook Events.
Terminal events (verification.completed, verification.action_required) always include a single channel field representing the primary verification channel. Intermediate notifications keep the original channels array to provide full auditing of concurrent communication paths.
Webhook Headers
Each webhook request includes these headers:| Header | Description |
|---|---|
Content-Type | Always application/json. |
X-Event-Type | Event type (verification.completed, verification.action_required, verification.notification). |
X-Event-Id | Unique delivery ID for this webhook (use for idempotency). |
X-Search-Type | Optional; resolved search type such as EMPLOYMENT, EDUCATION, CRIMINAL, REFERENCE. |
X-External-Search-Id | Optional; echoes the external search identifier provided when the order was created. |
X-Endpoint-Source | Indicates whether the request used a type-specific or fallback endpoint. |
User-Agent | Always Theary-Webhook-Delivery/1.0. |
Authorization | Present only when the webhook target specifies Basic Auth credentials (Authorization: Basic <base64(username:password)>). |
X-Webhook-Signature | Included when a tenant-level or per-target secret is configured; value is sha256=<hex> for HMAC validation. |
- If neither the tenant config nor the target defines a signing secret,
X-Webhook-Signatureis omitted. - Per-target custom headers are merged into the request when configured (for example
X-Customer: acme).
Security: Signature Verification
All webhook payloads are signed using HMAC-SHA256. Verify the signature to ensure authenticity:Node.js Example
Python Example
Integration Examples
Express.js Webhook Handler
Flask Webhook Handler (Python)
Retry Logic
The API automatically retries failed webhook deliveries:- Retry attempts: Configurable (default: 3, max: 10)
- Backoff strategy: Exponential backoff with jitter
- Retry timing: 2^attempt seconds (e.g., 2s, 4s, 8s)
- Client errors (4xx): Not retried
- Server errors (5xx): Retried with exponential backoff
Best Practices
1. Always Verify Signatures
Never process webhooks without verifying the HMAC signature. This ensures the webhook is from Theary and hasn’t been tampered with.2. Respond Quickly
Respond with HTTP 200 status code as soon as you receive the webhook. Perform heavy processing asynchronously.3. Handle Idempotency
Webhooks may be retried, so ensure your handlers are idempotent. Use theX-Event-Id header to track processed events.
4. Use HTTPS Endpoints
Always use HTTPS endpoints for webhook delivery. The API only sends to HTTPS URLs.5. Monitor Webhook Delivery
Track delivery status and set up alerts for failed deliveries. Monitor your logs for webhook processing errors.6. Store Secrets Securely
Never hardcode webhook secrets. Use environment variables or secure secret management services.7. Test with Webhook Testing Tools
Use tools like ngrok or webhook.site to test your webhook endpoints during development.Error Handling
HTTP Status Codes
Your webhook endpoint should return appropriate HTTP status codes:- 200 OK: Webhook received and processed successfully
- 400 Bad Request: Invalid payload format (not retried)
- 401 Unauthorized: Invalid signature (not retried)
- 500 Internal Server Error: Server error (will be retried)
Handling Failures
If your endpoint fails to process a webhook:- The API will retry based on your
retryAttemptsconfiguration - After all retries are exhausted, the webhook is marked as failed
- You can check webhook delivery status via the API (if available)
- Consider implementing a dead-letter queue for failed webhooks
Testing Webhooks
Using ngrok
Using webhook.site
- Visit webhook.site
- Copy the unique URL provided
- Use it in your webhook configuration for testing
- View incoming webhooks in real-time
Troubleshooting
Webhooks Not Received
- Check endpoint URL: Ensure your endpoint is accessible via HTTPS
- Verify signature: Check that your secret matches the one in the webhook config
- Check firewall: Ensure your server allows incoming connections from Theary
- Review logs: Check API logs for webhook delivery errors
Invalid Signature Errors
- Verify secret: Ensure the secret in your code matches the one in webhook config
- Check payload format: Ensure you’re serializing the payload correctly
- Encoding: Verify HMAC-SHA256 is using the correct encoding (hex)
Webhooks Received Multiple Times
- Idempotency: Implement idempotency checks using
X-Event-Id - Retry logic: This is expected behavior - the API retries failed deliveries
- Duplicate detection: Store processed event IDs to prevent duplicate processing
Related Documentation
- WebhookConfigDto Schema - Webhook configuration schema
- Create Order - Creating orders with webhook configuration
- Error Handling - Error handling best practices