Skip to main content
Webhooks let your backend receive real-time HTTP notifications as a person moves through an Identity Link verification. Instead of polling, you register a URL and VU POSTs a signed JSON payload whenever a step completes or fails.
Webhook endpoints are part of the API, so they need a Premium or Pro plan — the same requirement as POST /oauth/token. See Plans.

Register an endpoint

The request body accepts exactly two fields: url (required) and description (optional). Anything else is rejected. The call answers 201:
The response carries no secret. Signing is not per endpoint — there is one signing secret per account, and every endpoint you register receives payloads signed with it.

Where the signing secret lives

Your webhookSecret is a 256-bit value shown in the app under Settings → Developers, next to your Client Id and Client Secret. The same value comes back from an authenticated GET /users/me. To rotate it, use Refresh in that screen or call:
The response contains the new secret. Rotation takes effect immediately, so deploy the new value to your verifier before you rotate, or accept a short window of rejected deliveries.

Events

Twelve events cover the lifecycle. started fires when a step begins, successful when it clears, failed when it is definitively lost.
A failed attempt with retries left produces no webhook — the person is simply asked to try again, and remainingRetries drops by one. The *.failed events mark the exhausted attempt, which is also the point where the link is consumed.

Payload

Every payload has the same two-key shape: a type and a data object.
_externalUserId and _metadata are copied from the link that produced the verification. If the link carried no externalUserId, the field arrives as an empty string; with no metadata, _metadata is {}.

Geolocation on terminal events

verification.successful and verification.failed also carry data.geolocation, when a location was captured. Intermediate events never do — at verification.started the capture has not happened yet.
Absent keys are dropped rather than sent as null, so treat every field as optional.
The webhook geolocation is a subset. permission and sample are stripped, and the anti-fraud fields policy, ipDistanceKm and serverIp are never delivered by webhook — exactly as they are absent from the public endpoints. If your risk logic needs them, fetch the verification with a token after receiving the event.

Verify the signature

VU signs the payload with HMAC-SHA256 over the exact request body, keyed with your account webhookSecret, and sends the hex digest in the X-Signature-SHA256 header. Verify against the raw body. Parsing and re-serializing the JSON first will change the bytes and break the comparison.

Delivery and retries

Retries are deliberately short. VU makes up to 3 attempts, 100 ms apart, and stops as soon as your endpoint answers 200, 201, 202 or 204. Anything else — a 500, a timeout, a redirect — burns an attempt. After the third, the event is dropped and never redelivered.
That budget is far too small to absorb a slow handler, so:
  • Answer immediately, then process asynchronously. Acknowledge inside a few hundred milliseconds and push the work to a queue.
  • Be idempotent. The same event can arrive more than once, and verification.started is re-emitted on the adaptive branch under some retry paths.
  • Do not treat webhooks as the only source of truth. Reconcile with GET /verifications/{id}/status?linkId={linkId} for anything that matters commercially — a verification whose webhook was lost still has a correct status on the API.
  • Read the result before it expires. Past the verification’s expiresAt, GET /verifications/{id} answers 410. See Plans for how that window is calculated.

Manage endpoints

PATCH accepts url and description. Every route requires the same Bearer token as the rest of the API.
The /webhook-endpoints routes live on the same base URL as POST /links: https://api.identity.vu-one.com/api/v1. There is no separate host. If they answer 404 with given resource is not implemented, the route did not match: check the base URL, path, and method on the Errors page.

Next steps

  • Read extracted verification data in the KYC Results guide.
  • Understand how liveness events map to webhook types in the Liveness guide.
  • Review error codes if webhook registration fails on the Errors page.
Last modified on August 30, 2026