Webhooks
Receive real-time HTTP callbacks when events occur in your Kawaa account, such as batch job completion or credit alerts.
How Webhooks Work
- 1You configure a webhook URL in your Dashboard or via API
- 2An event occurs (e.g., batch job completes)
- 3Kawaa sends an HTTP POST request to your URL with event data
- 4Your server processes the event and responds with 2xx status
Webhook Events
| Event | Description |
|---|---|
job.completed | Batch verification job finished |
job.failed | Batch job failed to complete |
credits.low | Credit balance below threshold |
credits.depleted | Credit balance reached zero |
blacklist.detected | Domain detected on blacklist |
dmarc.failed | DMARC check failed for monitored domain |
Webhook Payload
job.completed event
{
"event": "job.completed",
"timestamp": "2026-02-03T14:35:42.000Z",
"data": {
"job_id": "job_abc123xyz",
"name": "January Newsletter List",
"status": "completed",
"progress": {
"total": 1000,
"processed": 1000,
"valid": 850,
"invalid": 100,
"risky": 30,
"unknown": 20
},
"download_url": "https://api.kawaa.com/v1/jobs/job_abc123xyz/download"
}
}Signature Verification
Each webhook request includes a signature header to verify authenticity. Always validate signatures in production.
Headers
X-Kawaa-Signature: sha256=abc123...
X-Kawaa-Timestamp: 1706976000Verification (Node.js)
const crypto = require('crypto');
function verifyWebhookSignature(payload, signature, secret) {
const expectedSignature = 'sha256=' +
crypto.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
}
// In your webhook handler
app.post('/webhook', (req, res) => {
const signature = req.headers['x-kawaa-signature'];
const isValid = verifyWebhookSignature(
JSON.stringify(req.body),
signature,
process.env.WEBHOOK_SECRET
);
if (!isValid) {
return res.status(401).send('Invalid signature');
}
// Process the webhook...
res.status(200).send('OK');
});Retry Policy
If your endpoint doesn't return a 2xx status code, we retry with exponential backoff:
- • Retry 1: After 1 minute
- • Retry 2: After 5 minutes
- • Retry 3: After 30 minutes
- • Retry 4: After 2 hours
- • Retry 5: After 8 hours (final attempt)
Best Practices
Respond Quickly
Return a 2xx response within 30 seconds. Process the webhook asynchronously if needed.
Handle Duplicates
Webhooks may be delivered multiple times. Use the event ID to deduplicate.
Verify Signatures
Always validate the webhook signature to ensure the request is from Kawaa.