Webhooks API
Register callback URLs to receive real-time notifications when verification events occur. Webhook payloads are signed with HMAC-SHA256 for security.
POST
/webhooks/configureRegister a webhook callback URL. The signing secret is returned only once — store it securely.
Request Body
| Parameter | Type | Description |
|---|---|---|
clientIdrequired | string | Your API client ID |
callbackUrlrequired | string | HTTPS URL to receive events |
eventsrequired | string[] | Events to subscribe to (at least one) |
Available Events
| Parameter | Type | Description |
|---|---|---|
document.verified | event | Document passed verification |
document.rejected | event | Document failed verification |
liveness.passed | event | Liveness check passed |
liveness.failed | event | Liveness check failed |
identity.verified | event | Full identity verification approved |
identity.rejected | event | Identity verification rejected |
identity.manual_review | event | Flagged for manual review |
curl -X POST https://api.verifyhq.com/v1/webhooks/configure \
-H "X-API-Key: your_api_key" \
-H "Content-Type: application/json" \
-d '{
"clientId": "client_abc123",
"callbackUrl": "https://your-app.com/webhooks/verifyhq",
"events": ["document.verified", "identity.verified", "liveness.passed"]
}'Response
201 Createdjson
{
"id": "wh_abc123",
"callbackUrl": "https://your-app.com/webhooks/verifyhq",
"events": ["document.verified", "identity.verified", "liveness.passed"],
"secret": "whsec_a1b2c3d4e5f6...",
"message": "Store the signing secret securely — it will not be shown again. Verify webhook signatures using HMAC-SHA256 with the X-Webhook-Signature header."
}GET
/webhooks/client/:clientIdList all webhook configurations for a client.
200 OKjson
[
{
"id": "wh_abc123",
"callbackUrl": "https://your-app.com/webhooks/verifyhq",
"events": ["document.verified", "identity.verified"],
"active": true,
"createdAt": "2025-01-15T10:00:00Z"
}
]DELETE
/webhooks/:idDeactivate a webhook configuration.
200 OKjson
{
"message": "Webhook deactivated successfully."
}Verifying Webhook Signatures
Every webhook delivery includes an X-Webhook-Signature header. Verify it using HMAC-SHA256:
import crypto from 'crypto';
function verifyWebhook(payload, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected),
);
}
// In your Express handler:
app.post('/webhooks/verifyhq', (req, res) => {
const signature = req.headers['x-webhook-signature'];
const isValid = verifyWebhook(
JSON.stringify(req.body),
signature,
process.env.WEBHOOK_SECRET,
);
if (!isValid) return res.status(401).send('Invalid signature');
// Process the event
const { event, data } = req.body;
console.log(event, data);
res.status(200).send('OK');
});Webhook Payload Format
Example Payloadjson
{
"event": "identity.verified",
"timestamp": "2025-01-15T10:35:00Z",
"data": {
"verificationId": "ver_abc123",
"userId": "user_123",
"status": "VERIFIED",
"tier": "ENHANCED",
"completedAt": "2025-01-15T10:35:00Z"
}
}Respond quickly
Your endpoint must respond with a 2xx status within 30 seconds. Failed deliveries are retried with exponential backoff (up to 3 retries).