Webhooks
Receive real-time notifications when events happen in your Gonos account.
Registering an endpoint
Register a webhook endpoint to start receiving events. You can register multiple endpoints and subscribe each to different event types.
curl -X POST https://api.gonos.co/api/v1/webhooks/endpoints \
-H "X-API-Key: gn_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-app.com/webhooks/gonos",
"events": ["check.completed", "report.ready", "dispute.filed"]
}'The response includes a secret field. Save this value securely — you will need it to verify webhook signatures.
Event types
| Event | Description |
|---|---|
check.created | A new background check was created |
check.completed | A check finished processing |
check.failed | A check encountered an error |
report.ready | The report for a check is available |
adverse_action.created | An adverse action was initiated |
adverse_action.finalized | An adverse action was finalized |
dispute.filed | A consumer filed a dispute |
dispute.resolved | A dispute was resolved |
candidate.updated | Candidate information was updated |
Payload format
Webhook payloads are JSON objects with a consistent envelope:
{
"id": "evt_abc123",
"type": "check.completed",
"created_at": "2026-03-24T12:00:00Z",
"data": {
"check_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "completed",
"disposition": "clear"
}
}Signature verification
Every webhook request includes an X-Gonos-Signature header. Verify this signature to ensure the request is authentic and has not been tampered with.
import hmac
import hashlib
def verify_signature(payload: bytes, signature: str, secret: str) -> bool:
expected = hmac.new(
secret.encode(),
payload,
hashlib.sha256,
).hexdigest()
return hmac.compare_digest(f"sha256={expected}", signature)The signature is computed as sha256=HMAC-SHA256(secret, raw_body). Always use the raw request body (not parsed JSON) for verification.
Retry policy
If your endpoint returns a non-2xx status code or times out (30 second limit), Gonos retries the delivery with exponential backoff:
| Attempt | Delay |
|---|---|
| 1st retry | 1 minute |
| 2nd retry | 5 minutes |
| 3rd retry | 30 minutes |
| 4th retry | 2 hours |
| 5th retry | 24 hours |
After 5 failed retries, the event is marked as failed. You can view failed deliveries in the admin dashboard under Webhooks.
Best practices
- Respond with
200 OKquickly — process the event asynchronously - Always verify the signature before processing
- Use idempotency: the same event may be delivered more than once
- Store the event
idto deduplicate - Monitor your endpoint for failures in the admin dashboard
Managing endpoints
# List endpoints
GET /api/v1/webhooks/endpoints
# Update events
PATCH /api/v1/webhooks/endpoints/{endpoint_id}
{"events": ["check.completed", "dispute.filed"]}
# Delete endpoint
DELETE /api/v1/webhooks/endpoints/{endpoint_id}
# Rotate secret
POST /api/v1/webhooks/endpoints/{endpoint_id}/rotate-secret