Appearance
Webhooks
YeboVerify can send webhook notifications to your server when verification events occur. This is useful for async verification flows or for keeping your system in sync with verification results.
Setting Up Webhooks
Configure Your Webhook URL
bash
curl -X PUT https://api.yeboverify.com/v1/account/webhook \
-H "X-API-Key: your_api_key" \
-H "Content-Type: application/json" \
-d '{
"webhookUrl": "https://yourapp.com/webhooks/yeboverify",
"webhookSecret": "whsec_your_secret_here"
}'Webhook Secret
The webhook secret is used to sign webhook payloads using HMAC-SHA256. Always verify the signature to ensure the webhook is from YeboVerify.
Webhook Events
verification.completed
Sent when a verification is completed (approved, rejected, or needs review).
Payload:
json
{
"event": "verification.completed",
"verificationId": "vrf_id_abc123xyz",
"externalRef": "user_123",
"status": "completed",
"decision": "approved",
"confidence": "high",
"faceScore": 92.3,
"ocrConfidence": 85,
"extractedData": {
"surname": "SMITH",
"names": "JOHN MICHAEL",
"dateOfBirth": "1990-05-15",
"idNumber": "9005151234567",
"documentType": "NATIONAL_ID"
},
"timestamp": "2024-01-15T12:00:05.000Z"
}Payload Fields:
| Field | Type | Description |
|---|---|---|
event | string | Event type (verification.completed) |
verificationId | string | Unique verification ID |
externalRef | string | Your reference ID (if provided) |
status | string | completed, failed, or needs_review |
decision | string | approved, rejected, or needs_review |
confidence | string | high, medium, or low |
faceScore | number | Face similarity score (0-100) |
ocrConfidence | number | OCR confidence (0-100) |
extractedData | object | Extracted document data |
timestamp | string | ISO 8601 timestamp |
Webhook Signature Verification
All webhook requests include a signature header for verification:
X-Webhook-Signature: sha256=d5a1e2b3c4f5...Node.js Verification
javascript
const crypto = require('crypto');
function verifyWebhookSignature(payload, signature, secret) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(JSON.stringify(payload))
.digest('hex');
const actualSignature = signature.replace('sha256=', '');
return crypto.timingSafeEqual(
Buffer.from(expectedSignature),
Buffer.from(actualSignature)
);
}
// Express middleware
app.post('/webhooks/yeboverify', express.json(), (req, res) => {
const signature = req.headers['x-webhook-signature'];
const webhookSecret = process.env.YEBOVERIFY_WEBHOOK_SECRET;
if (!verifyWebhookSignature(req.body, signature, webhookSecret)) {
console.error('Invalid webhook signature');
return res.status(401).send('Invalid signature');
}
const event = req.body;
switch (event.event) {
case 'verification.completed':
handleVerificationCompleted(event);
break;
default:
console.log('Unknown event type:', event.event);
}
res.status(200).send('OK');
});
function handleVerificationCompleted(event) {
console.log(`Verification ${event.verificationId} completed`);
console.log(`Decision: ${event.decision}`);
console.log(`User: ${event.externalRef}`);
// Update your database, send notifications, etc.
}Python Verification
python
import hmac
import hashlib
import json
from flask import Flask, request, abort
app = Flask(__name__)
WEBHOOK_SECRET = 'your_webhook_secret'
def verify_signature(payload, signature, secret):
expected = hmac.new(
secret.encode(),
json.dumps(payload, separators=(',', ':')).encode(),
hashlib.sha256
).hexdigest()
actual = signature.replace('sha256=', '')
return hmac.compare_digest(expected, actual)
@app.route('/webhooks/yeboverify', methods=['POST'])
def handle_webhook():
signature = request.headers.get('X-Webhook-Signature')
if not signature:
abort(401)
payload = request.json
if not verify_signature(payload, signature, WEBHOOK_SECRET):
abort(401)
event_type = payload.get('event')
if event_type == 'verification.completed':
handle_verification_completed(payload)
return 'OK', 200
def handle_verification_completed(event):
print(f"Verification {event['verificationId']} completed")
print(f"Decision: {event['decision']}")
print(f"User: {event.get('externalRef')}")
# Update your database, send notifications, etc.Webhook Retry Policy
If your webhook endpoint returns an error (non-2xx status code) or times out, YeboVerify will retry the webhook:
| Attempt | Delay |
|---|---|
| 1 | Immediate |
| 2 | 30 seconds |
| 3 | 2 minutes |
| 4 | 10 minutes |
| 5 | 1 hour |
After 5 failed attempts, the webhook is marked as failed and no further retries are attempted.
Best Practices
1. Return 200 Quickly
Always return a 200 OK response as quickly as possible. Process the webhook data asynchronously.
javascript
app.post('/webhooks/yeboverify', (req, res) => {
// Respond immediately
res.status(200).send('OK');
// Process asynchronously
processWebhookAsync(req.body).catch(console.error);
});2. Handle Duplicate Events
Webhooks may be delivered more than once. Use the verificationId to deduplicate:
javascript
const processedEvents = new Set();
function handleWebhook(event) {
if (processedEvents.has(event.verificationId)) {
console.log('Duplicate event, skipping');
return;
}
processedEvents.add(event.verificationId);
// Process the event...
}3. Verify Signatures
Always verify the webhook signature before processing. This prevents spoofed webhooks.
4. Use HTTPS
Always use HTTPS for your webhook endpoint. YeboVerify will not send webhooks to HTTP URLs.
5. Handle Timeouts
Your webhook endpoint should respond within 30 seconds. If processing takes longer, use a queue:
javascript
const { Queue } = require('bullmq');
const webhookQueue = new Queue('webhooks');
app.post('/webhooks/yeboverify', async (req, res) => {
// Add to queue for async processing
await webhookQueue.add('verification.completed', req.body);
res.status(200).send('OK');
});Testing Webhooks
Using ngrok for Local Development
- Install ngrok:
npm install -g ngrok - Start your local server:
npm run dev - Expose it:
ngrok http 3000 - Update your webhook URL to the ngrok URL
Manual Webhook Test
You can simulate a webhook for testing:
bash
curl -X POST http://localhost:3000/webhooks/yeboverify \
-H "Content-Type: application/json" \
-H "X-Webhook-Signature: sha256=test_signature" \
-d '{
"event": "verification.completed",
"verificationId": "vrf_test_123",
"status": "completed",
"decision": "approved",
"confidence": "high",
"faceScore": 92.3,
"timestamp": "2024-01-15T12:00:00.000Z"
}'