Webhooks
Receive incoming WhatsApp messages and delivery status updates in real-time. WaConnect forwards events to your server via HTTP POST requests.
Setup
Provide Your Callback URL
Contact your WaConnect administrator and provide the URL of your webhook endpoint (e.g., https://your-app.com/api/whatsapp/incoming). The URL must be publicly accessible over HTTPS.
Set a Callback Secret (Recommended)
Provide a secret string to your administrator. WaConnect will use it to sign every webhook request with an HMAC-SHA256 signature, allowing you to verify authenticity.
Webhook Payload
When an incoming message arrives, WaConnect sends an HTTP POST request to your Callback URL with the following structure:
Headers
| Header | Value |
|---|---|
Content-Type | application/json |
X-Webhook-Event | message.received |
X-Webhook-Delivery-Attempt | 1 (increments on retry) |
X-Webhook-Signature | sha256=HEX_SIGNATURE (if Callback Secret is set) |
Body
{
"event": "message.received",
"timestamp": "2026-04-11T10:30:00.000Z",
"accountId": "uuid-of-your-account",
"accountName": "Your Company Name",
"message": {
"messageId": "wamid.HBgLMTU1NTEyMzQ1NjcVAgASGCA0",
"from": "15551234567",
"contactName": "John Doe",
"contactWaId": "15551234567",
"messageType": "text",
"content": {
"text": "I need help with my order."
},
"context": null,
"phoneNumberId": "106540352242922",
"timestamp": "2026-04-11T10:29:58.000Z"
},
"conversation": {
"id": "123456789012345",
"origin": {
"type": "user_initiated"
}
},
"pricing": {
"billable": true,
"pricingModel": "CBP",
"category": "user_initiated"
}
}JSON
Verifying the Signature
If you set a Callback Secret, every webhook request includes an X-Webhook-Signature header. To verify it:
- Read the raw request body as a UTF-8 string.
- Compute an HMAC-SHA256 hash of the body using your Callback Secret as the key.
- Compare the hex-encoded hash with the value after
sha256=in the header.
C# Example (ASP.NET Core)
A complete webhook receiver controller with HMAC signature verification:
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
namespace WebhookReceiver.Controllers
{
[ApiController]
[Route("api/whatsapp/incoming")]
public class WhatsAppWebhookController : ControllerBase
{
// The same secret you provided to the WaConnect admin
private const string CallbackSecret = "your_secure_secret_phrase";
[HttpPost]
public async Task<IActionResult> ReceiveMessage()
{
// 1. Read the raw body
using var reader = new StreamReader(Request.Body);
var rawBody = await reader.ReadToEndAsync();
// 2. Verify the HMAC-SHA256 signature
if (Request.Headers.TryGetValue("X-Webhook-Signature", out var sigHeader))
{
var expected = ComputeHmacSha256(rawBody, CallbackSecret);
var provided = sigHeader.ToString().Replace("sha256=", "");
if (!string.Equals(expected, provided,
StringComparison.OrdinalIgnoreCase))
{
return Unauthorized("Invalid signature.");
}
}
// 3. Parse the payload
try
{
var doc = JsonDocument.Parse(rawBody);
var root = doc.RootElement;
if (root.GetProperty("event").GetString() == "message.received")
{
var msg = root.GetProperty("message");
var from = msg.GetProperty("from").GetString();
var type = msg.GetProperty("messageType").GetString();
Console.WriteLine($"Received {type} from {from}");
if (type == "text")
{
var text = msg.GetProperty("content")
.GetProperty("text").GetString();
Console.WriteLine($"Content: {text}");
}
// Process the message in your business logic
}
// 4. Always return 200 OK quickly
return Ok();
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
return BadRequest();
}
}
private static string ComputeHmacSha256(string payload, string secret)
{
var keyBytes = Encoding.UTF8.GetBytes(secret);
var msgBytes = Encoding.UTF8.GetBytes(payload);
using var hmac = new HMACSHA256(keyBytes);
var hash = hmac.ComputeHash(msgBytes);
return Convert.ToHexString(hash).ToLower();
}
}
}C#
Retry Policy
If your server responds with an error or times out, WaConnect retries delivery automatically:
| Attempt | Delay | Retries On |
|---|---|---|
| 1st | Immediate | — |
| 2nd | 1 second | 5xx errors, timeouts, 429 |
| 3rd | 2 seconds | 5xx errors, timeouts, 429 |
| 4th | 4 seconds | 5xx errors, timeouts, 429 |
WaConnect will not retry on 4xx client errors (except 429 Too Many Requests). Always return 200 OK as quickly as possible and process the message asynchronously.
Important: Your webhook endpoint must respond within 5 seconds. If processing takes longer, acknowledge the request immediately and handle the message in a background queue.