Skip to main content

Overview

GOWA WhatsApp API provides webhook-based message receiving with configurable auto-reply, auto-read, and auto-download features. All incoming events are forwarded to your webhook endpoint in real-time.

Webhook Configuration

Setting Up Webhooks

Configure webhook URLs via environment variables or CLI flags:
export WHATSAPP_WEBHOOK="https://yourapp.com/webhook"
export WHATSAPP_WEBHOOK_SECRET="your-secret-key"

Multiple Webhooks

Forward events to multiple endpoints (comma-separated):
export WHATSAPP_WEBHOOK="https://app1.com/webhook,https://app2.com/webhook"

Webhook Security

HMAC Signature Verification

All webhook requests include an X-Hub-Signature-256 header for security:
const crypto = require('crypto');
const express = require('express');
const app = express();

app.use(express.raw({type: 'application/json'}));

app.post('/webhook', (req, res) => {
  const signature = req.headers['x-hub-signature-256'];
  const payload = req.body;
  const secret = 'your-secret-key';

  // Verify signature
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(payload, 'utf8')
    .digest('hex');

  const receivedSignature = signature.replace('sha256=', '');
  
  if (!crypto.timingSafeEqual(
    Buffer.from(expectedSignature, 'hex'),
    Buffer.from(receivedSignature, 'hex')
  )) {
    return res.status(401).send('Unauthorized');
  }

  // Process webhook
  const data = JSON.parse(payload);
  console.log('Received event:', data.event);
  
  res.status(200).send('OK');
});
Always verify webhook signatures to prevent unauthorized requests. Never skip this step in production.

Webhook Events

Event Filtering

Control which events are forwarded to your webhook:
export WHATSAPP_WEBHOOK_EVENTS="message,message.ack,group.participants"
WHATSAPP_WEBHOOK_EVENTS
string
Comma-separated list of events to forward. If empty, all events are forwarded.

Available Events

EventDescription
messageText, media, contact, location messages
message.reactionEmoji reactions to messages
message.revokedDeleted/revoked messages (Delete for Everyone)
message.editedEdited messages
message.ackDelivery and read receipts
message.deletedMessages deleted for current user (Delete for Me)
group.participantsGroup member join/leave/promote/demote
group.joinedYou were added to a group
newsletter.joinedYou subscribed to a newsletter/channel
newsletter.leftYou unsubscribed from a newsletter
newsletter.messageNew messages in subscribed newsletters
newsletter.muteNewsletter mute setting changed
call.offerIncoming call received

Webhook Payload Structure

All webhooks follow this format:
{
  "event": "message",
  "device_id": "[email protected]",
  "payload": {
    // Event-specific data
  }
}

Text Message Example

{
  "event": "message",
  "device_id": "[email protected]",
  "payload": {
    "id": "3EB0C127D7BACC83D6A1",
    "chat_id": "[email protected]",
    "from": "[email protected]",
    "from_name": "John Doe",
    "timestamp": "2024-03-04T10:30:00Z",
    "is_from_me": false,
    "body": "Hello, how are you?"
  }
}

Delivery Receipt Example

{
  "event": "message.ack",
  "device_id": "[email protected]",
  "timestamp": "2024-03-04T10:30:15Z",
  "payload": {
    "ids": ["3EB00106E8BE0F407E88EC"],
    "chat_id": "[email protected]",
    "from": "[email protected]",
    "receipt_type": "delivered",
    "receipt_type_description": "means the message was delivered to the device"
  }
}

Group Event Example

{
  "event": "group.participants",
  "device_id": "[email protected]",
  "timestamp": "2024-03-04T10:35:00Z",
  "payload": {
    "chat_id": "[email protected]",
    "type": "join",
    "jids": ["[email protected]"]
  }
}
See the complete Webhook Payload Documentation for all event types.

Auto-Reply

Automatically respond to all incoming messages:
export WHATSAPP_AUTO_REPLY="Thank you for your message. We'll respond soon."
Auto-reply sends a response to every incoming message, including group messages. Use carefully to avoid spam.

Auto-Read Messages

Automatically mark incoming messages as read:
export WHATSAPP_AUTO_MARK_READ=true
WHATSAPP_AUTO_MARK_READ
boolean
default:"false"
When enabled, all incoming messages are immediately marked as read (blue checkmarks).

Use Cases

Customer Service Bot

Enable auto-read for bots that process messages programmatically.

Notification Channels

Disable auto-read to preserve unread counts for human agents.

Auto-Download Media

Control automatic media downloads from incoming messages:
export WHATSAPP_AUTO_DOWNLOAD_MEDIA=true  # Default
Media files are automatically downloaded to statics/media/ directory:
{
  "event": "message",
  "payload": {
    "id": "3EB0C127D7BACC83D6A3",
    "image": "statics/media/1752404751-ad9e37ac.jpeg"
  }
}
Downloaded media files accumulate in statics/media/. Implement cleanup jobs to manage disk space.

Webhook Retry Behavior

The API implements exponential backoff for webhook delivery:
1

Initial Request

10-second timeout per request.
2

Retry on Failure

Up to 5 retry attempts with exponential backoff: 1s, 2s, 4s, 8s, 16s.
3

Success Criteria

HTTP status 200-299 indicates successful delivery.

Webhook Best Practices

Return HTTP 200 within 10 seconds. Process heavy tasks asynchronously:
app.post('/webhook', async (req, res) => {
  // Return success immediately
  res.status(200).send('OK');
  
  // Process asynchronously
  processWebhookAsync(req.body).catch(console.error);
});
Network issues may cause duplicate webhook deliveries. Use message IDs for deduplication:
const processedIds = new Set();

if (processedIds.has(data.payload.id)) {
  return; // Skip duplicate
}
processedIds.add(data.payload.id);
Always use HTTPS webhook URLs in production to secure data transmission.

TLS Certificate Verification

For self-signed certificates or Cloudflare tunnels:
export WHATSAPP_WEBHOOK_INSECURE_SKIP_VERIFY=true
Security Risk: Disabling TLS verification removes protection against man-in-the-middle attacks. Only use in:
  • Development/testing environments
  • Cloudflare tunnels (which provide their own security layer)
  • Internal networks with self-signed certificates
For production: Use proper SSL certificates (e.g., Let’s Encrypt).

Complete Example

Full webhook handler with event processing:
const express = require('express');
const crypto = require('crypto');
const app = express();

app.use(express.raw({type: 'application/json'}));

app.post('/webhook', (req, res) => {
  // Verify signature
  const signature = req.headers['x-hub-signature-256'];
  const expectedSig = crypto
    .createHmac('sha256', 'your-secret-key')
    .update(req.body, 'utf8')
    .digest('hex');
  
  if (signature !== `sha256=${expectedSig}`) {
    return res.status(401).send('Unauthorized');
  }

  // Parse event
  const data = JSON.parse(req.body);
  
  // Route by event type
  switch (data.event) {
    case 'message':
      handleMessage(data.payload);
      break;
    case 'message.ack':
      handleReceipt(data.payload);
      break;
    case 'group.participants':
      handleGroupEvent(data.payload);
      break;
  }
  
  res.status(200).send('OK');
});

function handleMessage(payload) {
  console.log(`Message from ${payload.from}: ${payload.body}`);
  
  // Auto-respond to specific keywords
  if (payload.body.toLowerCase().includes('help')) {
    // Send help message using API
  }
}

app.listen(3001);

Configuration Summary

VariableDefaultDescription
WHATSAPP_WEBHOOK-Webhook URL(s) (comma-separated)
WHATSAPP_WEBHOOK_SECRETsecretHMAC signature secret
WHATSAPP_WEBHOOK_EVENTS(all)Event filter (comma-separated)
WHATSAPP_WEBHOOK_INSECURE_SKIP_VERIFYfalseSkip TLS verification
WHATSAPP_AUTO_REPLY-Auto-reply message text
WHATSAPP_AUTO_MARK_READfalseAuto-mark messages as read
WHATSAPP_AUTO_DOWNLOAD_MEDIAtrueAuto-download media files

See Also

Build docs developers (and LLMs) love