Webhooks
Our identity validation process is an asynchronous workflow. Once a user finishes or abandons the verification flow, our system sends an HTTP POST webhook notification to your backend with the final results.
Important Session Limit: The entire identity validation session must be completed by the user within 20 minutes from instantiation. If this limit is exceeded, the session automatically times out.
Setting up the webhook
To maintain high security and system integrity, webhook endpoints and access tokens are managed exclusively by authorized operators.
- Setup Request: Submit your webhook destination URL through your designated communication channels with our support team.
- Endpoint Requirements: Your server endpoint must accept incoming POST requests with a JSON body (Content-Type: application/json) and immediately respond with a 2xx success status code.
Example of Webhook Payload:
{
"id": "5169bc58-5777-472b-8eb6-8bb660d62812",
"document": "12345678910",
"approved": true,
"status": "APPROVED",
"merchant_id": "3da83a2e-92f7-4e6c-b799-84cf84b6ab8b",
"reason": "FACEMATCH_APPROVED",
"reason_description": "Comparação facial aprovada",
"step": "FACEMATCH"
}Field Definitions:
| field | type | always present | description |
|---|---|---|---|
id | string (uuid) | yes | the validation session id (the same session_id returned when the session was created) |
document | string | yes | the document number (CPF) of the validated user |
approved | boolean | yes | true when the validation was approved |
status | string | yes | final status of the validation session (see Webhook Status) |
merchant_id | string (uuid) | yes | your merchant id |
reason | string | no | code identifying the reason for the result (see Reason values) |
reason_description | string | no | human-readable description of the reason, in Portuguese, ready for display |
step | string | no | the validation step that produced the result: OCR, QUALITY, LIVENESS, FACEMATCH or CPF_VALIDATION |
⚠️ Backward Compatibility Note: The fields reason, reason_description, and step are strictly additive extensions of the webhook structure. Core historical fields (id, document, approved, status, merchant_id) remain unchanged in name, type, and behavior. Additive fields are omitted entirely (never sent as null) if they do not apply to the specific session event. Your parsing architecture must accept new additive keys without rejecting the payload.
Webhook Status
The status parameter reflects the overarching business outcome of the session. It will always equal one of the following four values:
{
"APPROVED"
"REPROVED"
"EXPIRED"
"ERROR"
}Reason and Step Breakdown
When the reason key is provided, use this matrix to map out granular failures or successes within your internal user tracking systems:
reason | reason_description | step | result |
|---|---|---|---|
FACEMATCH_APPROVED | Comparação facial aprovada | FACEMATCH | approved |
DOCUMENT_APPROVED | Documento aprovado | OCR | approved |
LIVENESS_APPROVED | Prova de vida aprovada | LIVENESS | approved |
FACEMATCH_NOT_APPROVED | Comparação facial reprovada | FACEMATCH | reproved — selfie does not match the document photo |
DOCUMENT_NOT_APPROVED | Documento não aprovado | OCR | reproved — document rejected |
DOCUMENT_NOT_ALLOWED | Documento não permitido | OCR | reproved — document type not accepted |
DOCUMENT_WITHOUT_CPF | Documento sem CPF | OCR or CPF_VALIDATION | reproved — document has no readable CPF, or the CPF is not regular at the federal registry (non-existent, suspended, cancelled or deceased holder) |
MAX_RETRIES_EXCEEDED | Reprovado por excesso de tentativas | LIVENESS | reproved — too many failed liveness attempts |
💡 Open Set Design: Treat the reason column as an open, evolving list. If your backend encounters an unrecognized code due to a future system update, fallback to status and approved for your automated business rules, and safely pipe reason_description to your administrative dashboards.
Early CPF Pre-Validation
Validation sessions can fail instantly before a user ever activates their camera hardware. If the provided CPF string is flags an irregular status at the Federal Registry level, the webhook will fire almost instantly with step: "CPF_VALIDATION" and status: "REPROVED". Your receiving endpoint should be structurally prepared to handle callbacks immediately following session creation.
Structured Payload Examples
Approved session:
{
"id": "5169bc58-5777-472b-8eb6-8bb660d62812",
"document": "12345678910",
"approved": true,
"status": "APPROVED",
"merchant_id": "3da83a2e-92f7-4e6c-b799-84cf84b6ab8b",
"reason": "FACEMATCH_APPROVED",
"reason_description": "Comparação facial aprovada",
"step": "FACEMATCH"
}Reproved session (facematch failed):
{
"id": "5169bc58-5777-472b-8eb6-8bb660d62812",
"document": "12345678910",
"approved": false,
"status": "REPROVED",
"merchant_id": "3da83a2e-92f7-4e6c-b799-84cf84b6ab8b",
"reason": "FACEMATCH_NOT_APPROVED",
"reason_description": "Comparação facial reprovada",
"step": "FACEMATCH"
}Reproved session (irregular CPF):
{
"id": "5169bc58-5777-472b-8eb6-8bb660d62812",
"document": "12345678910",
"approved": false,
"status": "REPROVED",
"merchant_id": "3da83a2e-92f7-4e6c-b799-84cf84b6ab8b",
"reason": "DOCUMENT_WITHOUT_CPF",
"reason_description": "Documento sem CPF",
"step": "CPF_VALIDATION"
}Best practices
- Idempotency: process notifications idempotently, using the
idfield as the deduplication key. - Respond fast: acknowledge with
2xxright away and do any heavy processing asynchronously. - Tolerant parsing: ignore unknown fields and unknown
reasoncodes — the payload contract is additive.
Updated about 1 month ago
