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: ••••••

Replace {{CONSUMER-WHATSAPP-ID}} with the phone number of the WhatsApp user who you are requesting call permissions from.

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

1

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" }
  ]
}
2

You will get the following response

{ "id": "<ID>", "status": "<STATUS>", "category": "<CATEGORY>" }re

Send CPR Template Message

1

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" }
        ]
      }
    ]
  }
}
2

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

1

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

2

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"
  }
}
3

If there are no errors, you will receive a successful response:

{
  "messaging_product": "whatsapp",
  "calls" : [
     "id" : "wacid.HBgLMTIxODU1NTI4MjgVAgARGCAyODRQIAFRoA", // The WhatsApp call ID
   ]
}
4

Once permission is granted, initiate a call:

Endpoint

POST /calling/calls/{phone_number_id}

Body

{
  "messaging_product": "whatsapp",
  "to": "{{recipient_phone_number}}",
  "action": "connect",
  "session": {
    "sdp_type": "offer",
    "sdp": "<<RFC 8866 SDP>>"
  }
}
5

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"
},
6

After initiating the call, you may receive these statuses:

  • RINGING: Call is ringing on the user's device

  • ACCEPTED: User accepted the call

  • REJECTED: User rejected the call

  • TERMINATE: 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.

How to get support

Error code
Description
Resolution

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?