GET /api/v1/customers/kyc/liveliness/output instead.
Events
| Event | Fires when |
|---|---|
customer.liveness.approved | Liveness submission status becomes completed |
customer.liveness.declined | Liveness submission status becomes auto_declined |
customer.liveness.needs_review | Liveness submission status becomes needs_review (pending back-office manual review). |
in_progress never fires a webhook — only terminal transitions do.
Delivery
- Signature:
HMACSHA512(key = your webhook secret, message = raw request body bytes), hex-encoded, lowercase. Recompute it over the exact bytes received (before any re-serialization) and compare to thex-embedly-signatureheader to verify authenticity. - Timeout: 10 seconds per attempt.
- Retries: up to 5 attempts total on non-2xx response or timeout. Production backoff: 5 min → 5 min → 60 min → 240 min after attempts 1–4 (attempt 5 is final — no further retry). Staging/Development use a flat 2-minute delay between every retry. After the 5th failed attempt the event is marked
Failedand not retried again. - Delivery is at-least-once — treat handlers as idempotent; use
data.submissionId+eventto dedupe if you log deliveries on your side.
Payload
customer.liveness.declined / customer.liveness.needs_review, failureReason is populated when HyperVerge supplied one:
| Field | Type | Description |
|---|---|---|
event | string | One of the three event names above. |
organizationId | GUID | The organization the customer belongs to (top level, not inside data). |
data.customerId | GUID | The customer the submission belongs to. |
data.submissionId | GUID | Internal id of the liveness submission row. |
data.status | string | completed | auto_declined | needs_review — matches the event. |
data.attemptNumber | int | Which liveness attempt this is for the customer (1-based, per §“Liveness status reference”). |
data.failureReason | object | null | { text, id } when HyperVerge/back-office supplied a reason; null on approval or when no reason was given. |
data.reviewedAt | ISO-8601 timestamp (UTC) | When the verdict was recorded. |
data.reviewerEmail | string | null | Populated only when a back-office reviewer manually resolved a needs_review case; null for HyperVerge auto-verdicts. |