Engati BSP APIs
Introduction
Use this documentation if you are building a direct API integration with Engati BSP for WhatsApp messaging
What can you do with these APIs
- Send outbound WhatsApp messages across supported message types
- Send approved template messages for business-initiated conversations
- Receive inbound user messages through webhooks
- Track message delivery, read, failed, and sent status updates
- Upload, retrieve, download, and delete media
- Create, list, and manage WhatsApp message templates
- Configure webhook-based event delivery
Before you start
- You will need to ask for a base URL, sandbox number and API Key, if you are starting afresh. Get in touch with your partnership manager or email at [email protected]
- If you are an existing customer and need access to a new number and API Key, kindly get in touch with your account manager or email at [email protected]
Engati BSP APIs
Onboarding
Before using the API, your WABA and phone number must be onboarded. This is managed through WhatsApp Manager inside the Engati platform.
Multi-partner solution
BSP Platform supports multi-partner (ISV / reseller) setups where partners can manage customer WABAs.
Multi-partner onboarding is available on request. Contact [email protected] to enable it. |
|---|
- Authentication
Every request must include a BSP API key in header format.
Bearer token (preferred)
Authorization: Bearer <your-api-key> |
|---|
- Test Credentials
Use these credentials on staging to try the API immediately.
Base URL: <Get in touch with your account manager or contact [email protected]>
API Key: <Get in touch with your account manager or contact [email protected]>
Phone Number: <Get in touch with your account manager or contact [email protected]>
Display Name: BSP Test Number
- Sending Messages (Outbound)
POST /v1/messages
The sender phone number is derived from your API key. Required headers for all requests:
Authorization: Bearer <your-api-key> Content-Type: application/json |
|---|
Base envelope for all message types:
{ "messaging_product": "whatsapp", "recipient_type": "individual", "to": "<e164-number>", "type": "<message-type>", ... type-specific fields } |
|---|
3.1 Text
"type": "text", "text": { "preview_url": true, "body": "Hello! Visit https://engati.ai for more info." } |
|---|
3.2 Image
"type": "image", "image": { "link": "https://example.com/image.jpg", "caption": "Here is your invoice summary." } |
|---|
Supported: JPEG, PNG. Max 5 MB.
3.3 Video
"type": "video", "video": { "link": "https://example.com/video.mp4", "caption": "Watch our product demo." } |
|---|
Supported: MP4, 3GP. Max 16 MB.
3.4 Audio
"type": "audio", "audio": { "link": "https://example.com/audio.ogg" } |
|---|
Supported: AAC, AMR, MP4, MPEG, OGG (Opus). Max 16 MB. No caption.
3.5 Document
"type": "document", "document": { "link": "https://example.com/invoice.pdf", "caption": "Invoice #1234", "filename": "invoice_1234.pdf" } |
|---|
Supported: PDF, DOC, DOCX, XLS, XLSX, PPT, PPTX, TXT and more. Max 100 MB.
3.6 Sticker
"type": "sticker", "sticker": { "link": "https://example.com/sticker.webp" } |
|---|
Supported: static WEBP only. Max 100 KB.
3.7 Location
"type": "location", "location": { "longitude": 72.8777, "latitude": 19.0760, "name": "Engati HQ", "address": "Mumbai, Maharashtra, India" } |
|---|
3.8 Contacts
"type": "contacts", "contacts": [{ "name": { "formatted_name": "John Doe", "first_name": "John", "last_name": "Doe" }, "phones": [{ "phone": "+919876543210", "type": "MOBILE" }], "emails": [{ "email": "[email protected]", "type": "WORK" }] }] |
|---|
3.9 Reaction
"type": "reaction", "reaction": { "message_id": "wamid.HBgLMTIzNDU2Nzg5OBIA", "emoji": "👍" } |
|---|
To remove a reaction send "emoji": "".
3.10 Interactive - Reply Buttons
Up to 3 quick-reply buttons. You receive a button_reply webhook when the user taps one.
"type": "interactive", "interactive": { "type": "button", "body": { "text": "Confirm your appointment?" }, "action": { "buttons": [ { "type": "reply", "reply": { "id": "btn_yes", "title": "Yes, confirm" } }, { "type": "reply", "reply": { "id": "btn_no", "title": "No, cancel" } } ] } } |
|---|
3.11 Interactive - List Message
Scrollable menu with sections and rows. You receive a list_reply webhook when the user selects an item.
"type": "interactive", "interactive": { "type": "list", "header": { "type": "text", "text": "Support Menu" }, "body": { "text": "Choose an option below." }, "footer": { "text": "BSP Support" }, "action": { "button": "View Options", "sections": [{ "title": "Account", "rows": [ { "id": "acc_balance", "title": "Check Balance", "description": "View your account balance" }, { "id": "acc_history", "title": "Order History", "description": "See recent orders" } ] }] } } |
|---|
3.12 Interactive - CTA URL Button
Button that opens a URL when tapped.
"type": "interactive", "interactive": { "type": "cta_url", "body": { "text": "Track your order in real time." }, "action": { "name": "cta_url", "parameters": { "display_text": "Track Order", "url": "https://example.com/track?order=9876" } } } |
|---|
3.13 Interactive - Carousel message
Used for sending Carousel card style messages with interactive buttons wihtin the 24-hour window. NOTE: Attribute name and values can be passed in case it is required to be saved upon click, or else can be skipped.
{ "messaging_product": "whatsapp", "recipient_type": "individual", "to": "<PHONE_NUMBER>", "type": "interactive", "interactive": { "type": "carousel", "body": { "text": "<CAROUSEL_BODY_TEXT>" }, "action": { "cards": [ { "card_index": 0, "type": "cta_url", "header": { "type": "image", "image": { "link": "<IMAGE_LINK>" } }, "body": { "text": "<CARD_1_TITLE>" }, "action": { "buttons": [ { "type": "quick_reply", "quick_reply": { "id": "node_nodekey__flowkey||data_attributename=attributevalue", "title": "<BUTTON_1_TITLE>" } }, { "type": "quick_reply", "quick_reply": { "id": "node_nodekey__flowkey||data_attributename=attributevalue", "title": "<BUTTON_2_TITLE>" } } ] } }, { "card_index": 1, "type": "cta_url", "header": { "type": "image", "image": { "link": "<IMAGE_LINK>" } }, "body": { "text": "<CARD_2_TITLE>" }, "action": { "buttons": [ { "type": "quick_reply", "quick_reply": { "id": "node_nodekey__flowkey||data_attributename=attributevalue", "title": "<BUTTON_1_TITLE>" } }, { "type": "quick_reply", "quick_reply": { "id": "node_nodekey__flowkey||data_attributename=attributevalue", "title": "<BUTTON_2_TITLE>" } } ] } } ] } } } |
|---|
3.14 Template
Required for initiating conversations or messaging outside the 24-hour window. Templates must be pre-approved by Meta.
"type": "template", "template": { "name": "order_confirmation", "language": { "code": "en_US" }, "components": [ { "type": "header", "parameters": [{ "type": "image", "image": { "link": "https://example.com/logo.jpg" } }] }, { "type": "body", "parameters": [ { "type": "text", "text": "ORD-9876" }, { "type": "text", "text": "499.00" }, { "type": "date_time", "date_time": { "fallback_value": "May 10, 2026" } } ] }, { "type": "button", "sub_type": "url", "index": 0, "parameters": [{ "type": "text", "text": "ORD-9876" }] } ] } |
|---|
Successful response
{ "messaging_product": "whatsapp", "contacts": [{ "input": "919876543210", "wa_id": "919876543210" }], "messages": [{ "id": "wamid.HBgLMTIzNDU2Nzg5OBIA" }] } |
|---|
4. Message Templates
Message templates are pre-approved message formats required to initiate conversations or send messages outside the 24-hour service window. Templates are submitted via the API, reviewed by Meta, and the result is reflected in the template status.
4.1 Create a Template
POST /v1/message-templates
Submits a new template to Meta for review. The template is stored locally and its status updated via webhook as Meta processes it.
Request body:
{ |
|---|
"name": "order_confirmation", |
"language": "en_US", |
"category": "UTILITY", |
"parameterFormat": "NAMED", |
"components": [ |
{ |
"type": "HEADER", |
"format": "TEXT", |
"text": "Order #{{order_id}} Confirmed", |
"example": { "header_text": ["98765"] } |
}, |
{ |
"type": "BODY", |
"text": "Hi {{customer_name}}, your order has been placed.", |
"example": { "body_text": [["Jane"]] } |
}, |
{ |
"type": "FOOTER", |
"text": "Reply STOP to unsubscribe" |
} |
] |
} |
Field | Type | Description |
|---|---|---|
name | string | Lowercase letters, numbers and underscores only. Must be unique per WABA and language. |
language | string | BCP-47 language code accepted by Meta, e.g. en, en_US, hi. |
category | enum | MARKETING, UTILITY, or AUTHENTICATION. |
parameterFormat | enum | POSITIONAL (default) uses {{1}}, {{2}}. NAMED uses {{customer_name}}. |
components | array | At least one BODY component required. See component structure in Meta docs. |
Response:
{ |
|---|
"id": "1234567890", |
"status": "PENDING", |
"category": "UTILITY" |
} |
4.2 List Templates
GET /v1/message-templates
Returns a paginated list of templates associated with the phone number's WABA.
Query param | Default | Description |
|---|---|---|
status | (none) | Filter by template status. Omit to return all statuses. |
page | 0 | Zero-based page index. |
size | 20 | Page size. Minimum 1, maximum 100. |
category | (none) | Optional filter by template category: `AUTHENTICATION`, `UTILITY`, or `MARKETING`. When supplied with `status`, both filters are applied. |
Example Request:
curl -i -X GET "https://<base_url>/v1/message-templates?status=APPROVED&category=UTILITY&page=0&size=20" -H "Authorization: Bearer <your-api-key>" |
|---|
Response:
{ |
|---|
"data": [ |
{ |
"id": "1234567890", |
"name": "order_confirmation", |
"language": "en_US", |
"category": "UTILITY", |
"parameter_format": "NAMED", |
"components": [ ... ], |
"status": "APPROVED", |
"rejected_reason": null |
} |
], |
"page": 0, |
"size": 20, |
"total": 1 |
} |
4.3 Get a Template
GET /v1/message-templates/{templateId}
Returns a single template by its BSP-assigned ID.
Response fields match the list response above.
4.4 Edit a Template
PATCH /v1/message-templates/{templateId}
Edits a template's content or category. Only templates in APPROVED, REJECTED, or PAUSED status can be edited. Components are replaced as a full set.
Approved Template Update Request Body:
{ "components": [ { "type": "BODY", "text": "Hi {{customer_name}}, your order has been updated.", "example": { "body_text_named_params": [ { "param_name": "customer_name", "example": "Jane" } ] } } ] } |
|---|
Rejected or Paused Template Update Request Body:
{ "category": "MARKETING", "components": [ { "type": "BODY", "text": "Hi {{customer_name}}, your order has been updated.", "example": { "body_text_named_params": [ { "param_name": "customer_name", "example": "Jane" } ] } } ] } |
|---|
Success Response:
{ "success": true, "id": "984856724589420", "name": "test_template_with_body_2", "category": "UTILITY" } |
|---|
Error Response (Approved Category Change):
{ "code": "invalid_message_template_request", "message": "Invalid message template request: category cannot be changed for APPROVED templates" } |
|---|
4.5 Delete a Template
DELETE /v1/message-templates
Deletes a template by Meta template ID. The service marks all associated local records with the same WABA/name as deleted. At least one of name, hsm_id, or hsm_ids must be supplied; otherwise the API returns 400
Query parameter | Description |
|---|---|
name | Template name to delete. |
hsm_id | Meta template ID to delete. |
hsm_ids | JSON array of Meta template IDs to delete. URL-encode the value when necessary. |
Example Request:
curl -i -X DELETE "https://<base_url>/v1/message-templates?name=test_template_with_body&hsm_id=1243567124" -H "Authorization: Bearer <your-api-key>" |
|---|
Response:
{ "meta": { "developer_message": "message template selector=`order_confirmation` was deleted", "http_code": 200, "success": true } } |
|---|
Template statuses
Status | Description |
|---|---|
PENDING | Submitted to Meta and awaiting review. |
APPROVED | Approved by Meta. Ready to use in template messages. |
REJECTED | Rejected by Meta. The rejectionReason field contains the reason. |
PAUSED | Paused by Meta due to low quality. Cannot be used until resumed. |
DISABLED | Disabled by Meta. Template cannot be used. |
IN_APPEAL | An appeal has been submitted following rejection. |
PENDING_DELETION | Deletion has been requested and is awaiting processing. |
Template categories
Category | Description |
|---|---|
MARKETING | Promotional messages such as offers, announcements, and newsletters. |
UTILITY | Transactional messages such as order confirmations, receipts, and alerts. |
AUTHENTICATION | One-time passcodes and verification messages. |
5. Media
The media API lets you upload files to WhatsApp, retrieve their CDN metadata, download media from incoming messages, and delete uploaded media. The sender phone number and ownership are resolved from your API key.
5.1 Upload Media
POST /v1/media
Uploads a media file to WhatsApp. Send as multipart/form-data.
Form field | Required | Description |
|---|---|---|
file | Yes | Binary file content. The part must include the correct Content-Type for the file. |
type | Yes | MIME type of the file, e.g. image/jpeg, video/mp4, application/pdf. |
Example:
curl -X POST https://<base_url>/v1/media \ |
|---|
-H "Authorization: Bearer <your-api-key>" \ |
-F "file=@/path/to/image.jpg;type=image/jpeg" \ |
-F "type=image/jpeg" |
Response — Meta's full upload response, including at minimum:
{ |
|---|
"id": "1234567890" |
} |
Use the returned id when referencing this media in outbound messages or template components.
5.2 Get Media URL
GET /v1/media/{mediaId}
Retrieves metadata and the temporary CDN download URL for a media file. Meta CDN URLs expire after approximately 5 minutes.
Response — Meta's full media metadata response, including at minimum:
{ |
|---|
"id": "1234567890", |
"url": "https://lookaside.fbsbx.com/whatsapp_business/attachments/?...", |
"mime_type": "image/jpeg", |
"sha256": "abc123...", |
"file_size": "123456", |
"messaging_product": "whatsapp" |
} |
5.3 Download Media
GET /v1/media/{mediaId}/download
Downloads the binary content of a media file. This is the recommended way to fetch received media — the service resolves and injects the Meta access token transparently, so your client does not need to handle Meta credentials or CDN URLs.
The response is streamed directly from Meta's CDN with no server-side buffering. Large files are piped chunk-by-chunk, so back-pressure is handled automatically.
Response headers:
Header | Value |
|---|---|
Content-Type | MIME type of the file, e.g. image/jpeg. |
Content-Length | File size in bytes as reported by Meta. |
Content-Disposition | attachment |
Example:
curl -X GET https://<base_url>/v1/media/1234567890/download \ |
|---|
-H "Authorization: Bearer <your-api-key>" \ |
--output image.jpg |
5.4 Delete Media
DELETE /v1/media/{mediaId}
Deletes a media file from WhatsApp. Once deleted, the file can no longer be referenced in messages.
Response: 204 No Content on success.
Supported media types
Type | Formats | Max size |
|---|---|---|
Image | JPEG, PNG | 5 MB |
Video | MP4, 3GP | 16 MB |
Audio | AAC, AMR, MP4, MPEG, OGG (Opus) | 16 MB |
Document | PDF, DOC, DOCX, XLS, XLSX, PPT, PPTX, TXT and others | 100 MB |
Sticker | WEBP (static only) | 100 KB |
6. Receiving Messages (Inbound)
When a user messages your number, BSP forwards the event as HTTP POST to your webhook URL. All events share the same outer envelope:
{ "object": "whatsapp_business_account", "entry": [{ "id": "<waba-meta-id>", "changes": [{ "value": { "messaging_product": "whatsapp", "metadata": { "display_phone_number": "+919876543210", "phone_number_id": "<meta-phone-number-id>" }, ... messages[] or statuses[] }, "field": "messages" }] }] } |
|---|
Examples below show only the messages[] inner contents.
6.1 Text
"messages": [{ "from": "919876543210", "id": "wamid.xxx", "timestamp": "1714986000", "type": "text", "text": { "body": "Hi, I need help with my order." } }] |
|---|
6.2 Image
"messages": [{ "type": "image", "image": { "id": "<media-id>", "mime_type": "image/jpeg", "sha256": "<hash>", "caption": "Screenshot" } }] |
|---|
6.3 Video
"messages": [{ "type": "video", "video": { "id": "<media-id>", "mime_type": "video/mp4", "sha256": "<hash>", "caption": "Demo" } }] |
|---|
6.4 Audio
"messages": [{ "type": "audio", "audio": { "id": "<media-id>", "mime_type": "audio/ogg; codecs=opus", "sha256": "<hash>", "voice": true } }] |
|---|
voice: true means it was recorded in-app (voice note).
6.5 Document
"messages": [{ "type": "document", "document": { "id": "<media-id>", "mime_type": "application/pdf", "sha256": "<hash>", "filename": "invoice.pdf" } }] |
|---|
6.6 Sticker
"messages": [{ "type": "sticker", "sticker": { "id": "<media-id>", "mime_type": "image/webp", "sha256": "<hash>", "animated": false } }] |
|---|
6.7 Location
"messages": [{ "type": "location", "location": { "longitude": 72.8777, "latitude": 19.0760, "name": "Home", "address": "Mumbai, India" } }] |
|---|
6.8 Contacts
"messages": [{ "type": "contacts", "contacts": [{ "name": { "formatted_name": "Jane Doe" }, "phones": [{ "phone": "+911234567890", "type": "MOBILE", "wa_id": "911234567890" }] }] }] |
|---|
6.9 Reaction
"messages": [{ "type": "reaction", "reaction": { "message_id": "wamid.HBgLMTIzNDU2Nzg5OBIA", "emoji": "👍" } }] |
|---|
6.10 Interactive - Button Reply
Received when a user taps a reply button.
"messages": [{ "type": "interactive", "interactive": { "type": "button_reply", "button_reply": { "id": "btn_yes", "title": "Yes, confirm" } } }] |
|---|
6.11 Interactive - List Reply
Received when a user selects a row from a list message.
"messages": [{ "type": "interactive", "interactive": { "type": "list_reply", "list_reply": { "id": "acc_balance", "title": "Check Balance", "description": "View your account balance" } } }] |
|---|
6.12 Order
Received when a user places an order through a WhatsApp catalog.
"messages": [{ "type": "order", "order": { "catalog_id": "cat_123", "text": "Please deliver by evening.", "product_items": [ { "product_retailer_id": "SKU-001", "quantity": 2, "item_price": "150.00", "currency": "INR" } ] } }] |
|---|
6.13 Message Status Updates
Delivery status events arrive under statuses[] instead of messages[].
"statuses": [{ "id": "wamid.HBgLMTIzNDU2Nzg5OBIA", "status": "delivered", "timestamp": "1714986060", "recipient_id": "919876543210", "conversation": { "id": "conv_123", "origin": { "type": "business_initiated" } }, "pricing": { "billable": true, "pricing_model": "CBP", "category": "service" } }] |
|---|
Status | Description |
|---|---|
sent | Accepted by Meta and queued |
delivered | Delivered to the recipient's device |
read | Read by the recipient (requires read receipts enabled) |
failed | Delivery failed - errors array included in payload |
7. WhatsApp Payments APIs
Endpoints for creating and managing payment configurations linked to the WABA.
7.1 List Payment Configurations
GET /v1/payments/configurations
Returns all payment configurations associated with the WABA.
7.2 List Payment Configurations
GET /v1/payments/configurations/{{PAYMENT_CONFIGURATION_NAME}}
Retrieves details of a specific payment configuration by name.
Path Parameters:
Parameter | Description |
|---|---|
PAYMENT_CONFIGURATION_NAME | The unique name of the payment configuration |
7.3 Create Payment Configuration
POST /v1/payments/configurations
Creates a new payment configuration for the WABA.
Request Body:
{ |
|---|
"configuration_name": "primary", |
"provider_name": "razorpay", |
"purpose_code": "OTHER", |
"merchant_category_code": "7399", |
"redirect_url": "https://example.com/payments/oauth/callback" |
} |
Field | Type | Required | Description |
|---|---|---|---|
configuration_name | string | Yes | Unique identifier name for this configuration |
provider_name | string | Yes | Payment provider. Example: razorpay |
purpose_code | string | Yes | Payment purpose code. Example: OTHER |
merchant_category_code | string | Yes | MCC code for the merchant category |
redirect_url | string | Yes | OAuth callback URL after payment provider authorization |
7.4 Update Payment Configuration
PATCH /v1/payments/configurations/{{PAYMENT_CONFIGURATION_NAME}}
Updates fields of an existing payment configuration.
Request Body:
{ |
|---|
"redirect_url": "https://example.com/payments/oauth/callback-v2", |
"data_endpoint_url": "https://example.com/payments/status" |
} |
Field | Type | Required | Description |
|---|---|---|---|
redirect_url | string | No | Updated OAuth redirect URL |
data_endpoint_url | string | No | Webhook URL for payment status updates |
7.5 Delete Payment Configuration
DELETE /v1/payments/configurations/{{PAYMENT_CONFIGURATION_NAME}}
Deletes a payment configuration by name.
7.6 Generate Payment OAuth Link
POST /v1/payments/configurations/oauth-link
Generates an OAuth authorization link for connecting a payment provider account.
Request Body:
{ |
|---|
"configuration_name": "primary", |
"redirect_url": "https://example.com/payments/oauth/callback" |
} |
Field | Type | Required | Description |
|---|---|---|---|
configuration_name | string | Yes | Name of the payment configuration to generate the link for |
redirect_url | string | Yes | URL to redirect to after OAuth authorization |
8.WhatsApp Calling APIs
Endpoints for configuring WhatsApp Calling and managing WebRTC-based call sessions.
8.1 Get Calling Settings
GET /v1/calling/settings
Retrieves the current calling settings for the WABA.
8.2 Get Calling Settings With SIP Credentials
GET /v1/calling/settings?include_sip_credentials=true
Retrieves calling settings including SIP credentials.
Query Parameters:
Parameter | Type | Required | Description |
|---|---|---|---|
include_sip_credentials | true | — | When set to true, includes SIP credentials in the response |
8.3 Update Calling Settings
POST /v1/calling/settings
Updates the calling configuration for the WABA.
Request Body:
{ |
|---|
"calling": { |
"status": "ENABLED", |
"call_icon_visibility": "DEFAULT", |
"callback_permission_status": "ENABLED" |
} |
} |
Field | Type | Required | Description |
|---|---|---|---|
calling.status | string | Yes | Calling feature status. Values: ENABLED, DISABLED |
calling.call_icon_visibility | string | No | Visibility of the call icon in the chat. Values: DEFAULT, HIDDEN |
calling.callback_permission_status | string | No | Whether callback permission is enabled. Values: ENABLED, DISABLED |
8.4 Get User Call Permissions
GET /v1/calling/permissions?user_wa_id={{USER_WA_ID}}
Retrieves calling permissions for a specific user by their WhatsApp ID.
Query Parameters:
Parameter | Type | Required | Description |
|---|---|---|---|
user_wa_id | string | Yes | The WhatsApp ID of the user to check permissions for |
8.5 Business-Initiated Call: Connect
POST /v1/calling/calls
Initiates a business-to-user call. The business sends a WebRTC SDP offer to connect.
Request Body:
{ |
|---|
"to": "919999999999", |
"action": "connect", |
"session": { |
"sdp_type": "offer", |
"sdp": "<webrtc-offer-sdp>" |
} |
} |
Field | Type | Required | Description |
|---|---|---|---|
to | string | Yes | Recipient's phone number in E.164 format (without +) |
action | string | Yes | Must be connect for business-initiated calls |
session.sdp_type | string | Yes | SDP type. Must be offer for business-initiated calls |
session.sdp | string | Yes | WebRTC SDP offer string |
8.6 User-Initiated Call: Pre-Accept
POST /v1/calling/calls
Sends a pre-accept signal for a user-initiated incoming call. Used to set up the WebRTC session before fully accepting.
Request Body:
{ |
|---|
"call_id": "{{CALL_ID}}", |
"action": "pre_accept", |
"session": { |
"sdp_type": "answer", |
"sdp": "<webrtc-answer-sdp>" |
} |
} |
Field | Type | Required | Description |
|---|---|---|---|
call_id | string | Yes | The ID of the incoming call to pre-accept |
action | string | Yes | Must be pre_accept |
session.sdp_type | string | Yes | SDP type. Must be answer |
session.sdp | string | Yes | WebRTC SDP answer string |
8.7 User-Initiated Call: Accept
POST /v1/calling/calls
Fully accepts a user-initiated incoming call.
Request Body:
{ |
|---|
"call_id": "{{CALL_ID}}", |
"action": "accept", |
"session": { |
"sdp_type": "answer", |
"sdp": "<webrtc-answer-sdp>" |
} |
} |
Field | Type | Required | Description |
|---|---|---|---|
call_id | string | Yes | The ID of the call to accept |
action | string | Yes | Must be accept |
session.sdp_type | string | Yes | SDP type. Must be answer |
session.sdp | string | Yes | WebRTC SDP answer string |
8.8 Terminate Call
POST /v1/calling/calls
Terminates an active call session.
Request Body:
{ |
|---|
"call_id": "{{CALL_ID}}", |
"action": "terminate" |
} |
Field | Type | Required | Description |
|---|---|---|---|
call_id | string | Yes | The ID of the call to terminate |
action | string | Yes | Must be terminate |
9. Webhook Configuration
Inbound events are forwarded to a webhook URL configured per phone number. Your endpoint must be HTTPS and return 200 within 10 seconds.
- URL - HTTPS endpoint to receive events
- Subscriptions - event types to receive (e.g. messages)
- Custom headers - optional key-value pairs forwarded on every request
9.1 Set webhook URL
PUT /v1/phone-numbers/webhooks
Required header:
Authorization: Bearer <your-api-key> |
|---|
Request Body
{"endpoints":[{"url":"https://<base_url>/webhooks/messages","events":["messages","status"],"headers":{"X-Secret":"secret-1"}}]} |
|---|
Retry policy
Attempt | Delay |
|---|---|
1 (initial) | Immediate |
2 | 10 seconds |
3 | 30 seconds |
After 3 failed attempts the event is dropped. Return 200 immediately and process asynchronously.
10. WhatsApp Flows APIs
10.1 Create Flow
POST /v1/flows
Creates a new WhatsApp Flow.
Request Body:
{ |
|---|
"name": "Support flow", |
"categories": [ |
"OTHER" |
] |
} |
Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Display name of the flow |
categories | array[string] | Yes | Flow categories. Allowed values: OTHER, CUSTOMER_SUPPORT, SURVEY, APPOINTMENT, LEAD_GENERATION, CONTACT_US, CUSTOMER_FEEDBACK, SHOPPING, SIGN_IN, SIGN_UP |
10.2 List Flows
GET /v1/flows?fields=id,name,status,categories,validation_errors&limit=25
Returns a paginated list of flows with selected fields.
Query Parameters:
Parameter | Type | Required | Description |
|---|---|---|---|
fields | string | No | Comma-separated list of fields to return |
limit | integer | No | Number of results per page (default: 25) |
10.3 List Flows With Cursor
GET /v1/flows?fields=id,name,status&limit=10&after=
Fetches the next page of flows using a cursor for pagination.
Query Parameters:
Parameter | Type | Required | Description |
|---|---|---|---|
fields | string | No | Comma-separated fields to return |
limit | integer | No | Page size |
after | string | Yes | Cursor value from the previous response for pagination |
10.4 Get Flow
GET /v1/flows/{{FLOW_ID}}?fields=id,name,status,categories,validation_errors,json_version,data_api_version
Retrieves full details of a specific flow.
Path Parameters:
Parameter | Description |
|---|---|
FLOW_ID | The unique ID of the flow |
Query Parameters:
Parameter | Type | Required | Description |
|---|---|---|---|
fields | string | No | Comma-separated list of fields to include in the response |
10.5 Update Flow Metadata
PATCH /v1/flows/{{FLOW_ID}}
Updates the name and/or categories of an existing flow.
Request Body:
{ |
|---|
"name": "Support flow v2", |
"categories": [ |
"CUSTOMER_SUPPORT" |
] |
} |
Field | Type | Required | Description |
|---|---|---|---|
name | string | No | New display name for the flow |
categories | array[string] | No | Updated category list |
10.6 Delete Flow
DELETE /v1/flows/{{FLOW_ID}}
Permanently deletes a flow. Only flows in DRAFT status can be deleted.
10.7 Publish Flow
POST /v1/flows/{{FLOW_ID}}/publish
Publishes a flow, making it live and available to users.
10.8 Deprecate Flow
POST /v1/flows/{{FLOW_ID}}/deprecate
Marks a published flow as deprecated. Deprecated flows can no longer be sent to users.
10.9 Migrate Flows
POST /v1/flows/migrate?source_waba_id=&source_flow_names=Support flow,Feedback flow
Migrates flows from a source WABA (WhatsApp Business Account) to the current account.
Query Parameters:
Parameter | Type | Required | Description |
|---|---|---|---|
source_waba_id | string | Yes | The WABA ID to migrate flows from |
source_flow_names | string | Yes | URL-encoded comma-separated list of flow names to migrate |
10.10 Upload Flow JSON Asset
POST /v1/flows/{{FLOW_ID}}/assets
Uploads a Flow JSON definition file as an asset to a flow. Uses multipart/form-data.
Form Data:
Field | Type | Required | Description |
|---|---|---|---|
file | file | Yes | The Flow JSON file to upload (variable: {{FLOW_JSON_FILE}}) |
name | text | Yes | Asset filename, e.g. flow.json |
asset_type | text | Yes | Must be FLOW_JSON |
10.11 List Flow Assets
GET /v1/flows/{{FLOW_ID}}/assets
Lists all assets attached to a specific flow.
10.12 Get Flow Preview
GET /v1/flows/{{FLOW_ID}}/preview
Returns a preview URL for the flow.
10.13 Refresh Flow Preview
GET /v1/flows/{{FLOW_ID}}/preview?invalidate=true
Forces a cache invalidation and returns a fresh preview URL.
Query Parameters:
Parameter | Type | Required | Description |
|---|---|---|---|
invalidate | true | — | Forces preview cache refresh |
10.14 Get Flow Metrics
GET /v1/flows/{{FLOW_ID}}/metrics?name=ENDPOINT_REQUEST_COUNT&granularity=DAY&since=2026-06-01&until=2026-06-10
Retrieves flow usage metrics for a given time range.
Query Parameters:
Parameter | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Metric name. Supported: ENDPOINT_REQUEST_COUNT, ENDPOINT_REQUEST_ERROR |
granularity | string | Yes | Time granularity. Supported: DAY |
since | date (YYYY-MM-DD) | Yes | Start date of the metrics range |
until | date (YYYY-MM-DD) | Yes | End date of the metrics range |
10.15 Get Flow Error Metrics
GET /v1/flows/{{FLOW_ID}}/metrics?name=ENDPOINT_REQUEST_ERROR&granularity=DAY&since=2026-06-01&until=2026-06-10
Retrieves error-specific metrics for a flow endpoint.
10.16 Get Flow Encryption
GET /v1/flows/encryption
Retrieves the current flow encryption configuration (public key info).
10.17 Get Flow Encryption Configuration
GET /v1/flows/encryption
Alias endpoint to retrieve the full flow encryption configuration details.
10.18 Set Flow Encryption Configuration
POST /v1/flows/encryption
Sets or updates the business public key used for end-to-end flow encryption.
Request Body:
{ |
|---|
"business_public_key": "-----BEGIN PUBLIC KEY-----\n<base64-public-key>\n-----END PUBLIC KEY-----" |
} |
Field | Type | Required | Description |
|---|---|---|---|
business_public_key | string | Yes | PEM-formatted RSA public key for flow encryption |
10.19 Set Flow Encryption Copy
POST /v1/flows/encryption
Copies/replicates the flow encryption configuration. No JSON body required.
11. WhatsApp Marketing Messages API
Endpoints for sending template-based marketing messages.
11.1 Send Template Marketing Message
POST /v1/marketing-messages
Sends a simple template-based marketing message to a recipient.
Request Body:
{ |
|---|
"to": "16315552222", |
"type": "template", |
"template": { |
"name": "hello_world", |
"language": { |
"code": "en" |
} |
} |
} |
Field | Type | Required | Description |
|---|---|---|---|
to | string | Yes | Recipient phone number in E.164 format (without +) |
type | string | Yes | Message type. Must be template |
template.name | string | Yes | Name of the approved WhatsApp message template |
template.language.code | string | Yes | BCP-47 language code for the template (e.g. en, en_US) |
11.2 Send Template Marketing Message With Components
POST /v1/marketing-messages
Sends a template marketing message with dynamic component parameters (e.g. body text variables).
Request Body:
{ |
|---|
"to": "16315552222", |
"type": "template", |
"template": { |
"name": "order_update", |
"language": { |
"code": "en_US" |
}, |
"components": [ |
{ |
"type": "body", |
"parameters": [ |
{ |
"type": "text", |
"text": "Amit" |
} |
] |
} |
] |
} |
} |
Field | Type | Required | Description |
|---|---|---|---|
to | string | Yes | Recipient phone number |
type | string | Yes | Must be template |
template.name | string | Yes | Template name |
template.language.code | string | Yes | Language code |
template.components | array | No | Array of component objects for dynamic variable substitution |
components[].type | string | Yes | Component type: header, body, button |
components[].parameters | array | Yes | Array of parameter objects |
parameters[].type | string | Yes | Parameter type: text, image, document, video |
parameters[].text | string | Conditional | Text value (required when type is text) |
12. Error Responses
{ "code": "error_code", "message": "Human readable description", "details": {} } |
|---|
HTTP Status | Code | Description |
|---|---|---|
400 | invalid_request | Malformed body or missing required field |
401 | unauthorized | Missing or invalid API key |
401 | invalid_api_key_format | Key does not match expected format |
403 | forbidden | Key lacks permission for this action |
404 | phone_number_not_found | Phone number not found or inactive |
422 | validation_error | Request fields failed validation |
429 | rate_limit_exceeded | Too many requests - back off and retry |
502 | meta_api_error | Upstream Meta Graph API error |
503 | service_unavailable | Temporary outage - retry with backoff |
13. Rate Limits
Operation | Limit |
|---|---|
POST /v1/messages | 80 requests / second per phone number |
All other calls | 100 requests / minute |
X-RateLimit-Limit: 80 X-RateLimit-Remaining: 72 X-RateLimit-Reset: 1714986120 |
|---|
On 429, wait until X-RateLimit-Reset. Use exponential backoff for 5xx errors.