Webhooks

Receive real-time notifications for message events, status updates, and more.

Setting Up Webhooks

  1. Create an endpoint
    Set up an HTTPS endpoint on your server to receive webhook events.
  2. Configure in Dashboard
    Go to Dashboard → Developer → Webhooks and add your endpoint URL.
  3. Select events
    Choose which events you want to receive notifications for.
  4. Verify signatures
    Always verify the webhook signature to ensure requests are from Aerostic.

Event Types

message.received

Triggered when a new message is received from a customer

{
  "event": "message.received",
  "timestamp": "2026-01-30T15:45:00Z",
  "data": {
    "id": "msg_abc123",
    "from": "+919876543210",
    "type": "text",
    "text": "Hi, I need help with my order",
    "wamid": "wamid.ABGGFlC..."
  }
}
message.sent

Triggered when a message is successfully sent

{
  "event": "message.sent",
  "timestamp": "2026-01-30T15:45:05Z",
  "data": {
    "id": "msg_def456",
    "to": "+919876543210",
    "status": "sent",
    "wamid": "wamid.ABGGFlC..."
  }
}
message.delivered

Triggered when a message is delivered to the recipient

{
  "event": "message.delivered",
  "timestamp": "2026-01-30T15:45:10Z",
  "data": {
    "id": "msg_def456",
    "to": "+919876543210",
    "status": "delivered",
    "deliveredAt": "2026-01-30T15:45:10Z"
  }
}
message.read

Triggered when a message is read by the recipient

{
  "event": "message.read",
  "timestamp": "2026-01-30T15:46:00Z",
  "data": {
    "id": "msg_def456",
    "to": "+919876543210",
    "status": "read",
    "readAt": "2026-01-30T15:46:00Z"
  }
}
message.failed

Triggered when a message fails to send

{
  "event": "message.failed",
  "timestamp": "2026-01-30T15:45:05Z",
  "data": {
    "id": "msg_ghi789",
    "to": "+919876543210",
    "status": "failed",
    "error": {
      "code": "INVALID_RECIPIENT",
      "message": "Phone number is not on WhatsApp"
    }
  }
}
contact.created

Triggered when a new contact is added

{
  "event": "contact.created",
  "timestamp": "2026-01-30T15:45:00Z",
  "data": {
    "id": "contact_xyz",
    "phone": "+919876543210",
    "name": "John Doe",
    "tags": ["new", "website"]
  }
}

Signature Verification

Security Best Practice

Always verify webhook signatures to prevent spoofed requests.

Every webhook request includes an X-Aerostic-Signature header. Verify this signature using your webhook secret:

verify-signature.js
const crypto = require('crypto');

function verifyWebhookSignature(payload, signature, secret) {
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
  
  return signature === `sha256=${expectedSignature}`;
}

// Express.js middleware example
app.post('/webhook', express.raw({ type: '*/*' }), (req, res) => {
  const signature = req.headers['x-aerostic-signature'];
  const isValid = verifyWebhookSignature(req.body, signature, WEBHOOK_SECRET);
  
  if (!isValid) {
    return res.status(401).json({ error: 'Invalid signature' });
  }
  
  const event = JSON.parse(req.body);
  console.log('Received event:', event.event);
  
  // Process the event...
  
  res.status(200).json({ received: true });
});

Retry Policy

If your endpoint returns a non-2xx status code, we'll retry the webhook with exponential backoff:

AttemptDelay
Attempt 1Immediate
Attempt 230 seconds
Attempt 35 minutes
Attempt 430 minutes
Attempt 52 hours

After 5 failed attempts, the webhook will be marked as failed and you'll receive an email notification.

Best Practices

Respond quickly

Return a 200 status within 5 seconds

Process async

Queue events for background processing

Handle duplicates

Use event IDs to detect duplicates

Use HTTPS

Secure your endpoint with TLS