How to Handle Outbound Calls
This guide explains how a business can initiate a WhatsApp voice call to a user, following consent and compliance requirements.
In this documentation, you will learn:
How to collect CPR
Before starting a call you need to collect CPR with either a text or template message. The following steps describe how to do so using a template message:
Collect CPR with a text message
You can also use the following request to send a single interactive message to get a CPR from the end-user:
GET
https://waba-v2.360dialog.io/calling/permissions/{{CONSUMER-WHATSAPP-ID}}
--header 'D360-API-KEY: ••••••
The user will have the following view:

Collect CPR using a template message
To personalize the request, you can alternatively use a template message to send a call permission request:
Create CPR Template Message
Create CPR template
You can use the endpoint
POST
/{WABA_ID}/message_templates
Adapt you request body using the following example
{
"name": "sample_cpr_template_test",
"language": "en",
"category": "MARKETING",
"components": [
{
"type": "BODY",
"text": "We would like to call you about Order {{1}} containing {{2}}. Can we call you?",
"example": { "body_text": [["ON-12345", "Avocados"]] }
},
{ "type": "FOOTER", "text": "Talk to you soon!" },
{ "type": "CALL_PERMISSION_REQUEST" }
]
}
Send CPR Template Message
To send the template message, you can use the endpoint:
POST
/{PHONE_NUMBER_ID}/messages
Request body
{
"messaging_product": "whatsapp",
"to": "{{recipient_phone_number}}",
"type": "template",
"template": {
"name": "sample_cpr_template_test",
"language": { "code": "en" },
"components": [
{
"type": "body",
"parameters": [
{ "type": "text", "text": "ON-12345" },
{ "type": "text", "text": "Avocados" }
]
}
]
}
}
When the user responds to the CPR you will receive the following webhook with the status:
GRANTED
: End-user accepted the request and you can now start the call.REJECTED
: End-user rejected the request. A new request can be sent.REVOKED
: The permission expired or was withdrawn by the end-user.
Webhook example:
{
"event": "call_permission_status",
"status": "GRANTED | REJECTED | REVOKED",
"waba_id": "<WABA_ID>",
"recipient": "<phone_number>"
}
CPR rules:
A permission is valid for 7 days.
Max 2 CPRs per 7 days per user.
Max 5 business-initiated calls per 24h per user.
Permission auto-revoked after 4 unanswered calls.
How to Initiate a Call
Enable Callback Permission Status in call settings
When callback_permission_status
is enabled, the user automatically provides call permission to your business when they place a call to you.
The call permission request expires when any of the following occurs:
When the consumer interacts with a subsequent new call permission request to the business
7 days after the permission was accepted or declined by the consumer
7 days after the permission was delivered if the consumer does not respond to the request
Initiate the Call
Once permission is granted, you can initiate the call.
Endpoint:
POST
https://waba-v2.360dialog.io/calling/call
--header 'D360-API-KEY: ••••••'
{
"messaging_product": "whatsapp",
"to": {recipient-phone-number},
"action": "connect",
"session": {
"sdp_type": "offer",
"sdp": "<<RFC 4566 SDP"
}
}
After successful initiation of a new call, you will receive Call Connect Webhook response that contains SDP Answer from Cloud API.
Your business will then apply the SDP Answer from this webhook to your WebRTC stack in order to initiate the media connection.
{
"entry": [
{
"changes": [
{
"field": "calls",
"value": {
"calls": [
{
"biz_opaque_callback_data": "TRx334DUDFTI4Mj", // Arbitrary string passed by business for tracking purposes
"session": {
"sdp_type": "answer",
"sdp": "<RFC 8866 SDP>"
},
"from": "13175551399", // The business phone number placing the call (caller)
"connection": {
"webrtc": {
"sdp": "<RFC 8866 SDP>"
}
},
"id": "wacid.HBgLMTIxODU1NTI4MjgVAgARGCAyODRQIAFRoA", // The WhatsApp call ID
"to": "12185552828", // The WhatsApp user's phone number (callee)
"event": "connect",
"timestamp": "1749196895",
"direction": "BUSINESS_INITIATED"
}
],
"metadata": { // ID and display number for the business phone number placing the call (caller)
"phone_number_id": "436666719526789",
"display_phone_number": "13175551399"
},
"messaging_product": "whatsapp"
}
}
],
"id": "366634483210360" // WhatsApp Business Account ID associated with the business phone number
}
],
"object": "whatsapp_business_account"
},
After initiating the call, you may receive these statuses:
RINGING
: Call is ringing on the user's deviceACCEPTED
: User accepted the callREJECTED
: User rejected the callTERMINATE
: Call ended for any reason
{
"entry": [
{
"changes": [
{
"field": "calls",
"value": {
"statuses": [
{
"id": "wacid.HBgLMTIxODU1NTI4MjgVAgARGCAyODRQIAFRoA", // The WhatsApp call ID
"type": "call",
"status": "[RINGING|ACCEPTED|REJECTED]", // The current call status
"timestamp": "1749197000",
"recipient_id": "12185552828" // The WhatsApp user's phone number (callee)
}
],
"metadata": { // ID and display number for the business phone number placing the call (caller)
"phone_number_id": "436666719526789",
"display_phone_number": "13175551399"
},
"messaging_product": "whatsapp"
}
}
],
"id": "366634483210360" // WhatsApp Business Account ID associated with the business phone number
}
],
"object": "whatsapp_business_account"
}
Troubleshooting
If you face errors, make sure to check in the following table the possible resolutions. If you can't find your issue, please contact our support team for more.
138006
No approved call permission
Request CPR before initiating a call
138010
CPR expired
Ask user again for permission
138011
Too many CPR requests
Respect 2 per 7d limit
138012
Business call limit exceeded
Wait 24h or reduce attempts
138014
Invalid SDP
Ensure SDP complies with RFC 8866
Last updated
Was this helpful?