Canonical route
Use the graph.whats91.com API v2 path for create, list, get, and update.
Create and manage Whats91 Webhooks v2 event destinations with the canonical public API route.
Create webhook destinations so Whats91 can deliver real-time message and account events to your HTTPS receiver.
Whats91 Webhooks v2 deliver real-time WhatsApp events to your HTTPS endpoint. Public API v2 webhook management uses /api/v2/webhooks only; these APIs manage Whats91 outbound event destinations and do not change Meta callback override URLs or legacy Cloud API setup fields.
Use the graph.whats91.com API v2 path for create, list, get, and update.
Omit senderId for default token resolution, or pass it when a token can access multiple senders.
The signing secret is returned once when the webhook is created and is never returned by list, get, or update.
Send the public API token in the Authorization header. For POST compatibility, authToken, auth_token, or token can also be sent in the JSON body.
Authorization: Bearer w91_public_token_hereEndpoint: GET /api/v2/webhooks/events. Fetch the event catalog before creating a webhook so your integration subscribes only to supported event keys.
/api/v2/webhooks/eventscurl -X GET "https://graph.whats91.com/api/v2/webhooks/events" \
-H "Authorization: Bearer w91_public_token_here"{
"success": true,
"message": "Webhook event catalog retrieved",
"data": {
"groups": [],
"eventKeys": [
"message.inbound.text",
"message.status.delivered",
"template.status_update"
]
},
"metadata": {
"apiVersion": "v2",
"requestId": "request-uuid"
}
}Endpoint: POST /api/v2/webhooks.
| Header | Required | Description |
|---|---|---|
| Authorization | Yes | Use Authorization: Bearer w91_public_token_here. |
| Content-Type | Yes | Use Content-Type: application/json for create and update requests. |
/api/v2/webhooks| Parameter | Type | Required | Description |
|---|---|---|---|
senderId | string | Optional | WhatsApp sender number. Number-scoped tokens can only manage webhooks for the assigned sender. |
webhook.name | string | Required | Developer-facing webhook name. |
webhook.endpointUrl | string | Required | HTTPS destination URL that receives Whats91 event deliveries. |
webhook.events | array | Required | Supported event keys from GET /api/v2/webhooks/events. |
webhook.status | string | Optional | ACTIVE or INACTIVE. Defaults to ACTIVE when omitted. |
webhook.timeoutMs | number | Optional | Delivery timeout in milliseconds, such as 5000. |
webhook.retryEnabled | boolean | Optional | Whether Whats91 should retry failed deliveries. |
webhook.retryMaxAttempts | number | Optional | Maximum retry attempts when retryEnabled is true. |
webhook.verificationHeaderKey | string | Optional | Custom header name Whats91 sends with the verification token. |
webhook.verificationToken | string | Optional | Shared verification token stored encrypted/hashed and never returned by public APIs. |
curl -X POST "https://graph.whats91.com/api/v2/webhooks" \
-H "Authorization: Bearer w91_public_token_here" \
-H "Content-Type: application/json" \
-d '{
"senderId": "916268662275",
"webhook": {
"name": "CRM delivery hook",
"endpointUrl": "https://crm.example.com/webhooks/whats91",
"events": ["message.inbound.text", "message.status.delivered"],
"status": "ACTIVE",
"timeoutMs": 5000,
"retryEnabled": true,
"retryMaxAttempts": 3,
"verificationHeaderKey": "X-CRM-Webhook-Token",
"verificationToken": "shared-secret"
}
}'{
"success": true,
"message": "Webhook created",
"data": {
"webhookUid": "wh_abc",
"uid": "wh_abc",
"name": "CRM delivery hook",
"endpointUrl": "https://crm.example.com/webhooks/whats91",
"phoneNumber": "916268662275",
"phoneNumberId": "1043189608869917",
"events": ["message.inbound.text", "message.status.delivered"],
"status": "ACTIVE",
"timeoutMs": 5000,
"retryEnabled": true,
"retryMaxAttempts": 3,
"verificationHeaderKey": "X-CRM-Webhook-Token",
"hasVerificationToken": true
},
"signingSecret": "whsec_created_once_only",
"metadata": {
"apiVersion": "v2",
"requestId": "request-uuid"
}
}{
"success": false,
"message": "Unsupported webhook event: message.invalid",
"error_code": "VALIDATION_FAILED",
"details": {},
"metadata": {
"apiVersion": "v2",
"requestId": "request-uuid"
}
}signingSecret is returned only on create. Store it immediately. List, get, and update responses never return the signing secret, encrypted secret, verification token, or token hash.
| Field | Type | Notes |
|---|---|---|
| webhook.name | string | Readable name for the destination. |
| webhook.endpointUrl | string | HTTPS endpoint URL in production. Local development URLs are allowed only where Whats91 validation allows them. |
| webhook.events | array | One or more supported event keys from the event catalog. |
| Field | Type | Notes |
|---|---|---|
| senderId | string | Sender WhatsApp number for multi-number customers. |
| webhook.status | string | ACTIVE or INACTIVE. Use INACTIVE to disable a webhook. |
| webhook.timeoutMs | number | Delivery timeout in milliseconds. |
| webhook.retryEnabled | boolean | Enables retries for failed deliveries. |
| webhook.retryMaxAttempts | number | Maximum delivery retry attempts. |
| webhook.verificationHeaderKey | string | Custom verification header key, such as X-CRM-Webhook-Token. |
| webhook.verificationToken | string | Custom shared token sent in the verification header. |
| Action | Method | Endpoint | Notes |
|---|---|---|---|
| List webhooks | GET | /api/v2/webhooks | Filter by senderId, status, event, page, and limit. |
| Get one webhook | GET | /api/v2/webhooks/:webhookUid | webhookUid is the only public identifier for retrieval. |
| Update webhook | POST | /api/v2/webhooks/:webhookUid | All webhook fields are optional, but at least one update field is required. |
| Status | Error code | When it happens |
|---|---|---|
| 401 | MISSING_AUTH_TOKEN | No public API token was supplied. |
| 401 | INVALID_AUTH_TOKEN | Token is missing, expired, revoked, or not tied to an active customer. |
| 403 | FEATURE_NOT_AVAILABLE | The subscription does not include Webhooks v2. |
| 400 | WHATSAPP_SETUP_INCOMPLETE | Whats91 cannot resolve a sender context. |
| 400 | VALIDATION_FAILED | Invalid name, empty events, unsupported event, invalid status, invalid timeout/retry values, invalid verification header, or missing update fields. |
| 400 | WEBHOOK_ENDPOINT_INVALID | The endpoint URL is malformed. |
| 400 | WEBHOOK_ENDPOINT_REQUIRES_HTTPS | The endpoint is not HTTPS in a production context. |
| 404 | WEBHOOK_NOT_FOUND | The UID does not belong to the authenticated customer and resolved sender. |
| 415 | UNSUPPORTED_CONTENT_TYPE | POST request is not JSON. |
Use these examples as starting points for server-side implementations.
curl -X GET "https://graph.whats91.com/api/v2/webhooks/events" \
-H "Authorization: Bearer w91_live_xxx"const response = await fetch("https://graph.whats91.com/api/v2/webhooks/events", {
method: "GET",
headers: {
"Authorization": "Bearer w91_live_xxx",
"Content-Type": "application/json"
}
});
const data = await response.json();
console.log(data);$ch = curl_init("https://graph.whats91.com/api/v2/webhooks/events");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer w91_live_xxx",
"Content-Type: application/json"
]
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;import requests
response = requests.request(
"GET",
"https://graph.whats91.com/api/v2/webhooks/events",
headers={
"Authorization": "Bearer w91_live_xxx",
"Content-Type": "application/json",
}
)
print(response.json())using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer w91_live_xxx");
var request = new HttpRequestMessage(HttpMethod.Get, "https://graph.whats91.com/api/v2/webhooks/events");
var response = await client.SendAsync(request);
Console.WriteLine(await response.Content.ReadAsStringAsync());Call POST /api/v2/webhooks with a destination name, HTTPS endpoint URL, event keys, and active status.
Webhook event keys cover message lifecycle updates and related Whats91 delivery events documented in the samples page.
Yes. Receivers should validate origin, use HTTPS, log payloads, and respond quickly with a successful status.
Webhook management requests, responses, and event payload samples for common Whats91 webhook flows.
Practical webhook receiver examples and use cases for CRM, delivery tracking, and template operations.
Retrieve the latest status and lifecycle events for one message.
Send Whats91-specific free-form chat text messages inside the customer service window.