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:
Environment Variable
CLI Flags
Docker Compose
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:
Node.js/Express
Python/Flask
Go
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"
Comma-separated list of events to forward. If empty, all events are forwarded.
Available Events
Event Description 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
Auto-Reply
Automatically respond to all incoming messages:
Environment Variable
CLI Flag
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
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.
Control automatic media downloads from incoming messages:
export WHATSAPP_AUTO_DOWNLOAD_MEDIA = true # Default
Enabled (Default)
Disabled
Media files are automatically downloaded to statics/media/ directory: {
"event" : "message" ,
"payload" : {
"id" : "3EB0C127D7BACC83D6A3" ,
"image" : "statics/media/1752404751-ad9e37ac.jpeg"
}
}
Media URLs are provided instead: {
"event" : "message" ,
"payload" : {
"id" : "3EB0C127D7BACC83D6A3" ,
"image" : {
"url" : "https://mmg.whatsapp.net/..." ,
"caption" : "Check this out!"
}
}
}
Download manually using /message/{message_id}/download endpoint.
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:
Initial Request
10-second timeout per request.
Retry on Failure
Up to 5 retry attempts with exponential backoff: 1s, 2s, 4s, 8s, 16s.
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
Variable Default Description 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