Webhooks

Receive real-time HTTP callbacks when events occur in your Kawaa account, such as batch job completion or credit alerts.

How Webhooks Work

  1. 1You configure a webhook URL in your Dashboard or via API
  2. 2An event occurs (e.g., batch job completes)
  3. 3Kawaa sends an HTTP POST request to your URL with event data
  4. 4Your server processes the event and responds with 2xx status

Webhook Events

EventDescription
job.completedBatch verification job finished
job.failedBatch job failed to complete
credits.lowCredit balance below threshold
credits.depletedCredit balance reached zero
blacklist.detectedDomain detected on blacklist
dmarc.failedDMARC 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: 1706976000

Verification (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.