# WhatsApp Voice Calling

Conversation API supports the following WhatsApp messaging entry points for voice calling:

- Sending call permission requests
- Sending call buttons
- Receiving related event callbacks


SIP (Session Initiation Protocol) is a standard way for systems to set up, manage, and end voice calls over IP networks.
In practice, SIP connects platforms, including WhatsApp Calling, to your telephony stack (for example, PBX or contact center)
so voice sessions can be routed to your business environment.

With this model, you can support both:

- **Business-initiated calls**, where your business starts the call (typically after required user permission has been obtained).
- **User-initiated calls**, where the user starts the call from WhatsApp (for example, by tapping a call button).


For the current alpha strategy, the supported architecture is customer-owned SIP. **This is the only model we can document
and support in this phase**. The customer owns the SIP infrastructure, provides the SIP endpoint details during onboarding,
and Meta connects directly to that SIP environment for signaling and media.

Sinch handles onboarding/configuration and forwards the relevant WhatsApp call lifecycle and permission-reply events to the customer webhook platform.

For more background on WhatsApp Calling and SIP onboarding, see Meta's documentation for [Cloud API Calling](https://developers.facebook.com/documentation/business-messaging/whatsapp/calling).

## Alpha architecture (current scope)

The details of the current scope of the alpha architecture are below:

- Customer owns and operates the SIP infrastructure and telephony platform.
- Customer provides SIP server details (hostname, port, TLS, credentials, and related configuration) during Sinch-supported onboarding.
- Meta connection is configured with the customer SIP endpoint and establishes the SIP session and media path directly with the customer's SIP environment.
- Sinch handles onboarding/configuration support and forwards the relevant call lifecycle and permission-reply events to the customer webhook platform.
- Sinch does not own or proxy the media path in this phase.


### Configuration flow

The configuration process is illustrated below:

```mermaid
flowchart LR
    C[Customer] -->|Share SIP details: host, port, TLS, credentials| S[Sinch onboarding / configuration]
    S -->|Add customer SIP settings to Meta| M[Meta WhatsApp Calling]
    S -->|Provide Meta master password back to customer| C
```

### Webhook event flow

The webhook event flow is illustrated below:

```mermaid
flowchart LR
    U[WhatsApp user] -->|Reply to call permission request / start call / end call| M[Meta WhatsApp Calling]
    M -->|Calling lifecycle + permission reply events| S[Sinch Conversation API]
    S -->|Forward events| W[Customer webhook platform]
```

### Call flow (SIP signaling and media)

The call flow is illustrated below:

```mermaid
flowchart LR
    CUST[Customer] -->|Call permission request / call button| S[Sinch Conversation API]
    S -->|Send message to Meta| M[Meta WhatsApp Calling]
    U[WhatsApp user] -->|Click call button / accept permission| M
    M -->|Direct SIP signaling + RTP media| SIP[Customer-owned SIP infrastructure]
    SIP -->|Voice app / PBX / contact center| V[Customer telephony platform]
```

## Supported Conversation API scenarios

With the WhatsApp channel, you can use Conversation API to:

- Send a **template** call permission request;
- Send a **free form** call permission request;
- Send a **template** call button message;
- Send a **free form** call button message;
- Optionally receive permission reply, call connect, and call terminate events on your `EVENT` webhook.


Note the following:
- A call permission request is used when your business wants to place a **business-initiated call** to the user.
- A call button message is used when you want the user to place a **user-initiated call** to your
business from WhatsApp.
- Outside the WhatsApp [customer service window](https://community.sinch.com/t5/WhatsApp/What-is-a-customer-service-window/ta-p/6858), you must use an [approved WhatsApp template](https://community.sinch.com/t5/WhatsApp/What-is-a-message-template-and-why-are-they-necessary/ta-p/6857).


## Sending a template call permission request

To send a template-based call permission request, use a Conversation API [`template_message`](/docs/conversation/api-reference/conversation/messages/messages_sendmessage#messages/messages_sendmessage/t=request&path=message&oneof=5/template_message) and reference
an approved WhatsApp template whose interaction type in Meta is `call_permission_request`.

Below is an example payload:

```json
{
  "app_id": "01KX1DEK870THTWCNENESBW5DP",
  "recipient": {
    "identified_by": {
      "channel_identities": [
        {
          "channel": "WHATSAPP",
          "identity": "555XXXXXXXXX"
        }
      ]
    }
  },
  "message": {
    "template_message": {
      "channel_template": {
        "WHATSAPP": {
          "template_id": "calls_permission_request_test",
          "language_code": "en"
        }
      }
    }
  }
}
```

The actual header, body, footer, and call permission interaction are defined in the approved Meta template. If your
template contains variables, populate them the same way as other WhatsApp templates. See our documentation on [template messages](/docs/conversation/channel-support/whatsapp/template-support/) for more information.

## Sending a free form call permission request

To send a free form call permission request during an open [customer service window](https://community.sinch.com/t5/WhatsApp/What-is-a-customer-service-window/ta-p/6858), use a
[`channel_specific_message`](/docs/conversation/api-reference/conversation/messages/messages_sendmessage#messages/messages_sendmessage/t=request&path=message&oneof=0/channel_specific_message) with `message_type` set to `call_permission_request`.

Below is an example payload:

```json
{
  "app_id": "01KX1DEK870THTWCNENESBW5DP",
  "recipient": {
    "identified_by": {
      "channel_identities": [
        {
          "channel": "WHATSAPP",
          "identity": "555XXXXXXXXX"
        }
      ]
    }
  },
  "message": {
    "channel_specific_message": {
      "WHATSAPP": {
        "message_type": "call_permission_request",
        "message": {
          "body": {
            "text": "test"
          }
        }
      }
    }
  }
}
```

The body text is optional, but Meta recommends including context so the recipient understands why your business wants
permission to call.

## Sending a template call button message

To send a template-based call button, use `template_message` and reference an approved WhatsApp template whose button
type in Meta is `voice_call`.

Below is an example payload:

```json
{
  "app_id": "01KX1DEK870THTWCNENESBW5DP",
  "recipient": {
    "identified_by": {
      "channel_identities": [
        {
          "channel": "WHATSAPP",
          "identity": "555XXXXXXXXX"
        }
      ]
    }
  },
  "message": {
    "template_message": {
      "channel_template": {
        "WHATSAPP": {
          "template_id": "call_button_test",
          "language_code": "en_US"
        }
      }
    }
  }
}
```

This message invites the user to start a voice call to your business from WhatsApp. As with other WhatsApp templates,
the button definition itself is managed in Meta when the template is created and approved. See our documentation on [template messages](/docs/conversation/channel-support/whatsapp/template-support/) for more information.

## Sending a free form call button message

To send a free form call button during an open [customer service window](https://community.sinch.com/t5/WhatsApp/What-is-a-customer-service-window/ta-p/6858), send a `channel_specific_message` with `message_type` set to `voice_call`.

Below is an example payload:

```json
{
  "app_id": "01KX1DEK870THTWCNENESBW5DP",
  "recipient": {
    "identified_by": {
      "channel_identities": [
        {
          "channel": "WHATSAPP",
          "identity": "555XXXXXXXXX"
        }
      ]
    }
  },
  "message": {
    "channel_specific_message": {
      "WHATSAPP": {
        "message_type": "voice_call",
        "message": {
          "body": {
            "text": "test"
          },
          "ttl_minutes": 100,
          "display_text": "Voice Call",
          "payload": "test"
        }
      }
    }
  }
}
```

Use the message fields as follows:

| Field | Description |
|  --- | --- |
| `body.text` | Required text shown together with the call button. |
| `ttl_minutes` | Time-to-live for the call button CTA. Defaults to `10080` (7 days). |
| `display_text` | The text shown on the WhatsApp call button. Defaults to `Call now`. |
| `payload` | Optional tracking value returned in calling events as `cta_payload`. |


## Receiving calling events

Conversation API can transcode the relevant WhatsApp calling callbacks and deliver them to your `EVENT` webhook as
`contact_event.channel_specific_event`.

Alpha scope note:
In the current customer-owned SIP model, webhooks are optional and informational. They can be used for permission, connection, and
termination tracking. They are not required to establish the SIP call. The actual SIP signaling and RTP media path is
established directly between Meta and the customer's SIP infrastructure, not via a Sinch-managed media bridge.

### Call permission reply event

When a user accepts or rejects a call permission request, you receive a `whatsapp_call_permission_reply_event`.

| Field | Description |
|  --- | --- |
| `response` | The user's decision. Expected values are `accept` or `reject`. |
| `is_permanent` | `true` if the user granted permanent permission, `false` for temporary permission. |
| `expiration_timestamp` | Expiration timestamp for temporary permission. Omitted for permanent permission. |


Below is an example with temporary permission:

```json
{
  "app_id": "01KX1DEK870THTWCNENESBW5DP",
  "event_time": "2026-08-28T14:05:28Z",
  "project_id": "2cb92b1b-2faf-40be-9380-accec4f24f46",
  "event": {
    "direction": "TO_APP",
    "contact_event": {
      "channel_specific_event": {
        "whatsapp_call_permission_reply_event": {
          "response": "accept",
          "is_permanent": false,
          "expiration_timestamp": "2026-09-04T14:05:28Z"
        }
      }
    },
    "id": "01M14B18KSPNDA9VX89J6G5D6R",
    "conversation_id": "",
    "contact_id": "",
    "channel_identity": {
      "channel": "WHATSAPP",
      "identity": "555XXXXXXXXX",
      "app_id": ""
    },
    "accept_time": "2026-08-28T14:05:30.729904748Z",
    "processing_mode": "DISPATCH"
  },
  "message_metadata": "",
  "correlation_id": "",
  "channel_metadata": {
    "whatsapp": {
      "message_type": "interactive",
      "interactive_message_type": "call_permission_reply",
      "profile_names": {
        "555XXXXXXXXX": "John"
      },
      "sender_phone_number": "SENDER_phone_number",
      "user_profile": {
        "display_name": "John",
        "username": "john_user",
        "country_code": "BR",
        "phone_number": "SENDER_phone_number",
        "user_id": "BR.3234965106801957"
      }
    }
  }
}
```

Below is an example with permanent permission:

```json
{
  "app_id": "01KX1DEK870THTWCNENESBW5DP",
  "event_time": "2026-08-28T13:54:59Z",
  "project_id": "2cb92b1b-2faf-40be-9380-accec4f24f46",
  "event": {
    "direction": "TO_APP",
    "contact_event": {
      "channel_specific_event": {
        "whatsapp_call_permission_reply_event": {
          "response": "accept",
          "is_permanent": true
        }
      }
    },
    "id": "01M14AE3DAA8QA0XGC4C7XNXEJ",
    "conversation_id": "",
    "contact_id": "",
    "channel_identity": {
      "channel": "WHATSAPP",
      "identity": "555XXXXXXXXX",
      "app_id": ""
    },
    "accept_time": "2026-08-28T13:55:02.791959571Z",
    "processing_mode": "DISPATCH"
  },
  "message_metadata": "",
  "correlation_id": "",
  "channel_metadata": {
    "whatsapp": {
      "message_type": "interactive",
      "interactive_message_type": "call_permission_reply",
      "profile_names": {
        "555XXXXXXXXX": "John"
      },
      "sender_phone_number": "SENDER_phone_number",
      "user_profile": {
        "display_name": "John",
        "username": "john_user",
        "country_code": "BR",
        "phone_number": "555XXXXXXXXX",
        "user_id": "BR.3234965106801957"
      }
    }
  }
}
```

### Call connect event

When the user starts a WhatsApp voice call to your business (for example, if they used a call button),
you receive a `whatsapp_call_connect_event`.

| Field | Description |
|  --- | --- |
| `direction` | The call direction. For example, `USER_INITIATED`. |
| `deeplink_payload` | Payload received from a call deep link, when used. |
| `cta_payload` | Payload received from a call button message, when used. |
| `sdp_type` | Optional SDP type associated with the call session. |
| `sdp` | Optional SDP content associated with the call session. |


```json
{
  "app_id": "01KX1DEK870THTWCNENESBW5DP",
  "event_time": "2026-08-28T14:17:45.812211426Z",
  "project_id": "2cb92b1b-2faf-40be-9380-accec4f24f46",
  "event": {
    "direction": "TO_APP",
    "contact_event": {
      "channel_specific_event": {
        "whatsapp_call_connect_event": {
          "direction": "USER_INITIATED",
          "deeplink_payload": "",
          "cta_payload": "test",
          "sdp_type": "",
          "sdp": ""
        }
      }
    },
    "id": "01M14BQPMMA37HYBWA2EGARM6A",
    "conversation_id": "",
    "contact_id": "",
    "channel_identity": {
      "channel": "WHATSAPP",
      "identity": "555XXXXXXXXX",
      "app_id": ""
    },
    "accept_time": "2026-08-28T14:17:46.218428897Z",
    "processing_mode": "DISPATCH"
  },
  "message_metadata": "",
  "correlation_id": "",
  "channel_metadata": {
    "whatsapp": {
      "profile_names": {
        "555XXXXXXXXX": "John"
      },
      "sender_phone_number": "",
      "user_profile": {
        "display_name": "John",
        "username": "john_user",
        "country_code": "BR",
        "phone_number": "555XXXXXXXXX",
        "user_id": "BR.3234965106801957"
      }
    }
  }
}
```

### Call terminate event

When the call ends, you receive a `whatsapp_call_terminate_event`.

| Field | Description |
|  --- | --- |
| `direction` | The call direction. For example, `USER_INITIATED`. |
| `deeplink_payload` | Payload received from a call deep link, when used. |
| `cta_payload` | Payload received from a call button message. |
| `status` | Call result, for example `COMPLETED`. |
| `start_time` | Call start time. |
| `end_time` | Call end time. |
| `duration` | Call duration. |


```json
{
  "app_id": "01KX1DEK870THTWCNENESBW5DP",
  "event_time": "2026-08-28T14:19:04.302983983Z",
  "project_id": "2cb92b1b-2faf-40be-9380-accec4f24f46",
  "event": {
    "direction": "TO_APP",
    "contact_event": {
      "channel_specific_event": {
        "whatsapp_call_terminate_event": {
          "direction": "USER_INITIATED",
          "deeplink_payload": "",
          "cta_payload": "test",
          "status": "COMPLETED",
          "start_time": "1787926665",
          "end_time": "1787926743",
          "duration": 78
        }
      }
    },
    "id": "01M14BT39CASHZJB0Q74ZW3FFT",
    "conversation_id": "",
    "contact_id": "",
    "channel_identity": {
      "channel": "WHATSAPP",
      "identity": "555XXXXXXXXX",
      "app_id": ""
    },
    "accept_time": "2026-08-28T14:19:04.464874671Z",
    "processing_mode": "DISPATCH"
  },
  "message_metadata": "",
  "correlation_id": "",
  "channel_metadata": {
    "whatsapp": {
      "profile_names": {
        "555XXXXXXXXX": "John"
      },
      "sender_phone_number": "",
      "user_profile": {
        "display_name": "John",
        "username": "john_user",
        "country_code": "BR",
        "phone_number": "555XXXXXXXXX",
        "user_id": "BR.3234965106801957"
      }
    }
  }
}
```

## Additional Meta references

For the call transport and calling lifecycle that happen outside Conversation API message sends,
see Meta's documentation for:

- [Cloud API Calling](https://developers.facebook.com/documentation/business-messaging/whatsapp/calling)
- [Obtaining user call permissions](https://developers.facebook.com/documentation/business-messaging/whatsapp/calling/user-call-permissions)
- [Sending WhatsApp call button messages and deep links](https://developers.facebook.com/documentation/business-messaging/whatsapp/calling/call-button-messages-deep-links)
- [User-initiated calls](https://developers.facebook.com/documentation/business-messaging/whatsapp/calling/user-initiated-calls)
- [Business-initiated calls](https://developers.facebook.com/documentation/business-messaging/whatsapp/calling/business-initiated-calls)