Skip to content

Webhook Best Practices

This guide covers production-ready patterns for receiving and processing SendAPI webhook events reliably.

Respond Quickly

Your webhook endpoint should return a 200 OK response within 5 seconds. If your processing takes longer, acknowledge the event immediately and offload heavy work to a background queue.

javascript
// ✅ Good — acknowledge immediately, process later
app.post('/webhook', (req, res) => {
  const event = req.body;
  queue.add('process-webhook', event); // Background job
  res.status(200).json({ received: true });
});

// ❌ Bad — blocks until processing completes
app.post('/webhook', async (req, res) => {
  await processEvent(req.body);  // Might take 10+ seconds
  res.json({ received: true });
});

Handle Duplicates (Idempotency)

SendAPI may deliver the same event more than once (e.g., during retries). Use the event id to deduplicate:

javascript
app.post('/webhook', async (req, res) => {
  const eventId = req.body.id;

  // Check if we've already processed this event
  const exists = await db.webhookEvents.findOne({ eventId });
  if (exists) {
    return res.status(200).json({ received: true }); // Already processed
  }

  // Store and process
  await db.webhookEvents.create({ eventId, data: req.body });
  await processEvent(req.body);

  res.status(200).json({ received: true });
});

Verify Event Authenticity

When SDK support is available, verify webhook signatures to ensure events are genuinely from SendAPI and haven't been tampered with. Until then, restrict your webhook endpoint by IP or use a secret URL path.

Event Types

EventDescription
sms.deliveredSMS was successfully delivered to the handset
sms.failedSMS delivery failed
whatsapp.message.sentWhatsApp message was sent
whatsapp.message.deliveredWhatsApp message was delivered
whatsapp.message.readWhatsApp message was read
whatsapp.message.receivedInbound WhatsApp message received
whatsapp.session.connectedWhatsApp session paired successfully
whatsapp.session.disconnectedWhatsApp session lost connection
email.deliveredEmail was delivered to the inbox
email.openedRecipient opened the email
email.clickedRecipient clicked a link
email.bouncedEmail bounced (hard or soft)

Retry Policy

If your endpoint returns a non-2xx status code or times out, SendAPI retries with exponential backoff:

AttemptDelay
1st retry1 minute
2nd retry5 minutes
3rd retry30 minutes
4th retry2 hours
5th retry12 hours

After 5 failed attempts, the event is marked as failed and can be manually retried from the dashboard.

Released under the MIT License.