WhatsApp Calling Examples

Getting Started

Contact us to enable the Calling API feature

The Calling API is restricted to whitelisted accounts. Contact us to request access.

Configure/Update business phone number calling settings

Use this endpoint Configure Call Settings API to update call settings configuration for an individual business phone number.

Code sample

curl 'https://api.ycloud.com/v2/whatsapp/phoneNumbers/{wabaId}/{phoneNumber}/settings'\
-H 'Content-Type: application/json' \
-H 'X-API-Key: {{YOUR-API-KEY}}' \
-d '{
    "calling": {
    "status": "ENABLED",
    "iconVisibility": "DEFAULT"
  }
  }'

Use this endpoint Get Call Settings API to check the configuration of your Calling API feature settings. This endpoint can return information for other Cloud API feature settings.

Code sample

curl 'https://api.ycloud.com/v2/whatsapp/phoneNumbers/{wabaId}/{phoneNumber}/settings'\
-H 'Content-Type: application/json' \
-H 'X-API-Key: {{YOUR-API-KEY}}'

Calling Eligibility

To qualify for Calling API features, your business must have a messaging limit of at least 1000 business-initiated conversations in a rolling 24-hour period.

Settings calling webhooks

You need to subscribe to the following webhook events:

User-initiated calling flow

Sequence Diagram


Part 1: A WhatsApp user calls your business from their client app

When a WhatsApp user calls your business, a Call Connect webhook will be triggered with an SDP Offer, see User-initiated Calling Connect Webhook

Webhook sample

{
  "id": "evt_6757b723a5a42d369ef48480",
  "type": "whatsapp.call.connect",
  "apiVersion": "v2",
  "createTime": "2024-12-10T03:36:03.749Z",
  "callingConnect": {
    "id": "6757b723960b25543b9ecc66",
    "wacid": "wacid.HBgNNjI4MTM2MTkwNTEzMxUCABIYIEF",
    "phoneId": "461269257068831",
    "from": "+6281361905133",
    "to": "+6283138205150",
    "direction": "USER_INITIATED",
    "dialTime": 1733826430000,
    "sdpType": "offer",
    "sdp": "<<RFC 4566 OFFER SDP>>"
  }
}

Part 2: Your business pre-accepts the call (Recommended)

In essence, when you pre-accept an inbound call, you are allowing the calling media connection to be established before attempting to send call media through the connection.

Pre-accepting calls is recommended because it facilitates faster connection times and avoids audio clipping issues.

To pre-accept, make a request to the Pre-accept an inbound call endpoint.

Code sample

curl 'https://api.ycloud.com/v2/whatsapp/calls/preAccept' \
-H 'Content-Type: application/json' \
-H 'X-API-Key: {{YOUR-API-KEY}}' \
-d '{
    "phoneId": "461269257068832",
    "wacid": "wacid.HBgNNjI4MTM2MTkwNTEKKSESFF32343242SE",
    "sdpType": "answer",
    "sdp": "<<RFC 4566 ANSWER SDP>>"
}'

Note
A business uses the SDP offer from a webhook to create an SDP answer via WebRTC, then calls the pre-answer interface.

Part 3: Your business accepts the call after the WebRTC connection is made

Once the WebRTC connection is made on your end, you can accept the call.

Once you accept the call, wait until you receive a 200 OK back from the endpoint. Media will begin flowing immediately since the connection was established prior to call connect.

You can now call the Accept an inbound call endpoint to accept the call.

Code sample

curl 'https://api.ycloud.com/v2/whatsapp/calls/accept' \
-H 'Content-Type: application/json' \
-H 'X-API-Key: {{YOUR-API-KEY}}' \
-d '{
    "phoneId": "461269257068832",
    "wacid": "wacid.HBgNNjI4MTM2MTkwNTEKKSESFF32343242SE",
    "sdpType": "answer",
    "sdp": "<<RFC 4566 ANSWER SDP>>"
}'

Use this endpoint to reject a call.

Code sample

curl 'https://api.ycloud.com/v2/whatsapp/calls/reject' \
-H 'Content-Type: application/json' \
-H 'X-API-Key: {{YOUR-API-KEY}}' \
-d '{
  "phoneId": "461269257068832",
  "wacid": "wacid.HBgNNjI4MTM2MTkwNTE"
}'

Part 4: Your business or the WhatsApp user terminates the call

Both the business or the WhatsApp user can terminate the call at any time.

You call the Terminate a WhatsApp call endpoint with the following request body to terminate the call.

Code sample

curl 'https://api.ycloud.com/v2/whatsapp/calls/terminate' \
-H 'Content-Type: application/json' \
-H 'X-API-Key: {{YOUR-API-KEY}}' \
-d '{
  "phoneId": "461269257068832",
  "wacid": "wacid.HBgNNjI4MTM2MTkwNTE"
  }'

A webhook notification whatsapp-calling-terminate-webhook is sent whenever a call ends, for any reason. This includes when the WhatsApp user hangs up, or when the business sends a terminate or reject request to the endpoint.

Webhook sample

{
  "id": "evt_6757b889a5a42d369ef48481",
  "type": "whatsapp.call.terminate",
  "apiVersion": "v2",
  "createTime": "2024-12-10T03:42:01.822Z",
  "callingTerminate": {
    "id": "6757b889960b25543b9ecc67",
    "wacid": "wacid.HBgNNjI4MTM2MTkwNTE",
    "phoneId": "461269257068832",
    "from": "+6281361905133",
    "to": "+6283138205150",
    "direction": "USER_INITIATED",
    "startTime": 1733734738000,
    "endTime": 1733734771000,
    "duration": 33,
    "status": "COMPLETED"
  }
}

Note

There is about 30 to 60 seconds after the User-initiated Calling Connect Webhook is sent for the business to accept the phone call. If the business does not respond, the call is terminated on the WhatsApp user side with a "Not Answered" notification and a whatsapp-calling-terminate-webhook is delivered back to you.

Since the WebRTC connection is established before calling the Accept an inbound WhatsApp call, make sure to flow the call media only after you receive a 200 OK response back.

If call media flows too early, the caller will miss the first few words of the call. If call media flows too late, callers will hear silence.

Business-initiated calling flow

Part 1: Obtain permission to call the WhatsApp user

Obtaining call permissions from the WhatsApp user can be done in one of the following ways:

Send a call permission request message

You can request call permissions by sending the WhatsApp user a permission request, either as a free form message during an open customer service window, or by using a template message that contains the request.

  • send a free form call permission request

Code sample

curl 'https://api.ycloud.com/v2/whatsapp/messages/sendDirectly' \
-H 'X-API-Key: {{YOUR-API-KEY}}' \
-H 'Content-Type: application/json' \
-d '{
    "from": "{{BUSINESS-PHONE-NUMBER}}",
    "to": "{{CUSTOMER-PHONE-NUMBER}}",
    "type": "interactive",
    "interactive": {
        "type": "call_permission_request",
        "action": {
            "name": "call_permission_request"
        },
       "body": {
        "text": "We would like to call you to help support your query on Order No: ON-12853."
        }
    }
}'
  • send a template call permission request

Code sample(create message template)

curl 'https://api.ycloud.com/v2/whatsapp/templates' \
-H 'Content-Type: application/json' \
-H 'X-API-Key: {{YOUR-API-KEY}}' \
-d '{
  "wabaId": "{{WABA-ID}}",
  "name": "call_permission_request_template",
  "language": "en_US",
  "category": "UTILITY",
  "components": [
     {
      "type": "HEADER",
      "text": "Support of Order No: {{1}}",
      "example": {
        "body_text": [
          [
            "ON-12345"
          ]
        ]
      }
    },    
    {
      "type": "BODY",
      "text": "We would like to call you to help support your query on Order No: {{1}} for the item {{2}}.",
      "example": {
        "body_text": [
          [
            "ON-12345",
            "Avocados"
          ]
        ]
      }
    },
    {
      "type": "FOOTER",
      "text": "Talk to you soon!"
    },
    {
      "type": "call_permission_request"
    }
  ]
}'

Code sample(send message template)

curl 'https://api.ycloud.com/v2/whatsapp/messages/sendDirectly' \
-H 'Content-Type: application/json' \
-H 'X-API-Key: {{YOUR-API-KEY}}' \
-d '{
  "from": "{{BUSINESS-PHONE-NUMBER}}",
  "to": "{{CUSTOMER-PHONE-NUMBER}}",
  "type": "template",
  "template": {
    "name": "call_permission_request_template",
    "language": {
      "code": "en_US",
      "policy": "deterministic"
    },
    "components": [
      {
        "type": "body",
        "parameters": [
          {
            "type": "text",
            "text": "John Smith"
          },
          {
            "type": "text",
            "text": "order #1522"
          }
        ]
      }
    ]
  }
}'

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.

WhatsApp user grants permanent permissions

The user can also grant permanent permissions to the business at any time through their business profile.

User calling permission request webhook

This webhook is sent back after requesting user calling permissions. Lastly, the user can grant permanent calling permission to the business, which is represented in the is_permanent parameter below.

Webhook sample

{
  "id": "evt_6772458a2b4b206adc55f094",
  "type": "whatsapp.inbound_message.received",
  "apiVersion": "v2",
  "createTime": "2024-12-30T07:02:34.899Z",
  "whatsappInboundMessage": {
    "id": "6772458abeea6edef0d4f4a6",
    "wamid": "wamid.HBgNNjI4MTM2MTkwNTEzMxUCABEYEkM0Q",
    "wabaId": "188234691048809",
    "from": "+6281361905133",
    "customerProfile": {
      "name": "Erin.liu"
    },
    "to": "+6283138205150",
    "sendTime": "2024-12-30T06:33:33.000Z",
    "type": "interactive",
    "interactive": {
      "type": "call_permission_reply",
      "call_permission_reply":{
            "response":"[accept|reject]",
            "is_permanent":false,
            "expiration_timestamp": "{timestamp}",
            "response_source": "[user_action|automatic]"
       }
    },
    "context": {
      "from": "6283138205150",
      "id": "wamid.HBgNNjI4MTM2MTkwNTEzMxUCABEYEkM0Q"
    }
  }
}

Part 2: Your business initiates a new call to the WhatsApp user

Now that you have user permission, you can initiate a new call to the WhatsApp user in question.

You can now call the Initiate an outbound WhatsApp call endpoint with the following request body to initiate a new call.

Code sample


curl 'https://api.ycloud.com/v2/whatsapp/calls/connect' \
-H 'Content-Type: application/json' \
-H 'X-API-Key: {{YOUR-API-KEY}}' \
-d '{
    "from": "+62831382000",
    "to": "+6281369051330",
    "sdpType": "offer",
    "sdp": "<<RFC 4566 OFFER SDP>>"
}'

Note

Response with error code 138006 indicates a lack of a call request permission for this business number from the WhatsApp user.


Part 3: You establish the call connection using webhook signaling

After successful initiation of a new call, you will receive Business-initiated Calling Connect Webhook response that contains an SDP Answer. Critically, the webhook contains information required to establish a call connection via WebRTC.

Webhook sample

{
  "id": "evt_676e5a0d7a9cb742d02d7645",
  "type": "whatsapp.call.connect",
  "apiVersion": "v2",
  "createTime": "2024-12-27T07:41:01.554Z",
  "callingConnect": {
    "id": "676e5a0d94c533526d3c5ad5",
    "wacid": "wacid.HBgNNjI4MTM2MTkwNTEzMxUCABE",
    "phoneId": "461269257068832",
    "from": "+6283138205150",
    "to": "+6283138205150",
    "direction": "BUSINESS_INITIATED",
    "sdpType": "answer",
    "sdp": "<<RFC 4566 ANSWER SDP>>",
    "dialTime": 1735283452000
  }
}

Once you receive the Call Connect webhook, you can apply the SDP Answer recieved in the webhook to your WebRTC stack in order to initiate the media connection.

A webhook is dispatched upon the ringing event on the WhatsApp user's client device.

Webhook sample


{
 "id": "evt_676e5ab57a9cb742d02d7646",
 "type": "whatsapp.call.status.updated",
 "apiVersion": "v2",
 "createTime": "2024-12-27T07:41:28.422Z",
 "callingStatusUpdated": {
   "wabaId": "188234691048809",
   "wacid": "wacid.HBgNNjI4MTM2MTkwNTEzMxUCABE",
   "status": "RINGING",
   "recipientPhone": "+6281361905133"
 }
}

A webhook is dispatched upon the call acceptance event by the WhatsApp user.

Webhook sample

{
  "id": "evt_67724ad42b4b206adc55f099",
  "type": "whatsapp.call.status.updated",
  "apiVersion": "v2",
  "createTime": "2024-12-27T07:42:00.577Z",
  "callingStatusUpdated": {
    "wabaId": "188234691048809",
    "wacid": "wacid.HBgNNjI4MTM2MTkwNTEzMxUCABE",
    "status": "ACCEPTED",
    "recipientPhone": "+6281361905133"
  }
}

A webhook is dispatched upon the call rejection event by the WhatsApp user, triggering the call terminate webhook.

Webhook sample

{
  "id": "evt_6757b889a5a42d369ef48481",
  "type": "whatsapp.call.terminate",
  "apiVersion": "v2",
  "createTime": "2024-12-10T03:42:01.822Z",
  "callingTerminate": {
    "id": "6757b889960b25543b9ecc67",
    "wacid": "wacid.HBgNNjI4MTM2MTkwNTE",
    "phoneId": "461269257068832",
    "from": "+6281361905133",
    "to": "+6283138205150",
    "direction": "USER_INITIATED",
    "startTime": 1733734738000,
    "endTime": 1733734771000,
    "duration": 33,
    "status": "COMPLETED"
  }
}

Part 4: Your business or the WhatsApp user terminates the call

Both you or the WhatsApp user can terminate the call at any time.

You call the Terminate a WhatsApp call endpoint with the following request body to terminate the call.

Code sample

curl 'https://api.ycloud.com/v2/whatsapp/calls/terminate' \
-H 'Content-Type: application/json' \
-H 'X-API-Key: {{YOUR-API-KEY}}' \
-d '{
  "phoneId": "461269257068832",
  "wacid": "wacid.HBgNNjI4MTM2MTkwNTE"
  }'

When either the business or the WhatsApp user terminates the call, you receive a whatsapp-calling-terminate-webhook

Webhook sample

{
  "id": "evt_6757b889a5a42d369ef48481",
  "type": "whatsapp.call.terminate",
  "apiVersion": "v2",
  "createTime": "2024-12-10T03:42:01.822Z",
  "callingTerminate": {
    "id": "6757b889960b25543b9ecc67",
    "wacid": "wacid.HBgNNjI4MTM2MTkwNTE",
    "phoneId": "461269257068832",
    "from": "+6281361905133",
    "to": "+6283138205150",
    "direction": "USER_INITIATED",
    "startTime": 1733734738000,
    "endTime": 1733734771000,
    "duration": 33,
    "status": "COMPLETED"
  }
}

FAQ

FAQs

Error Code

Meta Error Code