Receiving Webhooks
This page defines the HTTP delivery contract and the two top-level payload shapes. Step-specific fields are documented separately in Webhook Payload.
Delivery contract
| Property | Value |
|---|---|
| Method | POST |
| Content type | application/json |
| Signature header | X-Signature when a webhook secret is configured |
| Successful acknowledgement | 200 OK |
| Delivery attempts | Up to four total attempts when delivery fails |
Your endpoint should:
- Capture the unmodified request body.
- Verify
X-Signaturebefore trusting the body. - Parse the JSON only after verification.
- Store or enqueue the event using idempotent application logic.
- Return
200 OKpromptly.
See Webhook Signature for the exact HMAC input and header format.
Standard result envelope
Verification-result webhooks use this envelope:
{
"resultId": "936f35a8-4921-430e-b016-15be48968886",
"event": "COMPLETED",
"data": {
"dv": {
"id": "d65fa9a0-596e-4d7e-afd1-59a23bfb5a74",
"status": "PASSED"
}
},
"custom": {},
"flowStatus": "COMPLETED"
}
| Field | Meaning |
|---|---|
resultId | Identifier of the overall flow result. |
event | The event for this delivery. Common verification values include COMPLETED, FAILED, REVIEW, and REJECTED. AML updates use PRODUCED, REFRESHED, or MODERATED. |
data | The typed result object. The primary key identifies the result type. |
custom | Flow-level custom data used to reconcile the result with your system. |
flowStatus | Current status of the overall flow, which may differ from the individual step status. |
The primary data keys are dv, poa, form, spid, phone, wallet, kyb, aml, and geolocation. Extended DV webhooks also include additionalData; organizations using legacy compatibility may also receive kyc beside dv.
Notification envelope
Lifecycle notifications have a different shape. They use top-level eventData and intentionally omit data and flowStatus:
{
"resultId": "936f35a8-4921-430e-b016-15be48968886",
"event": "NOTIFICATION",
"eventData": {
"version": 0,
"type": "DOCUMENT_EXPIRED",
"flowResultId": "936f35a8-4921-430e-b016-15be48968886"
},
"custom": {}
}
Route notifications by eventData.type. Current notification types are:
DOCUMENT_EXPIREDKYC_RESULT_EXPIREDFLOW_RISK_REEVALUATED
Their fields are listed under Notification Events.
Dispatching events
Use the envelope before inspecting step-specific fields:
if (payload.event === 'NOTIFICATION') {
handleNotification(payload.eventData.type, payload.eventData)
} else if (payload.data.aml) {
handleAmlUpdate(payload.event, payload.data.aml)
} else {
const resultTypes = ['dv', 'poa', 'form', 'spid', 'phone', 'wallet', 'kyb', 'geolocation']
const resultType = resultTypes.find((key) => payload.data[key] != null)
handleVerificationResult(resultType, payload)
}
Do not assume that resultId uniquely identifies one delivery: a flow can produce multiple step results and later updates. Choose an idempotency key that includes the result type and its result identifier or update kind.