Skip to content

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.

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:

Share SIP details: host, port, TLS, credentials

Add customer SIP settings to Meta

Provide Meta master password back to customer

Customer

Sinch onboarding / configuration

Meta WhatsApp Calling

Share SIP details: host, port, TLS, credentials

Add customer SIP settings to Meta

Provide Meta master password back to customer

Customer

Sinch onboarding / configuration

Meta WhatsApp Calling

Webhook event flow

The webhook event flow is illustrated below:

Reply to call permission request / start call / end call

Calling lifecycle + permission reply events

Forward events

WhatsApp user

Meta WhatsApp Calling

Sinch Conversation API

Customer webhook platform

Reply to call permission request / start call / end call

Calling lifecycle + permission reply events

Forward events

WhatsApp user

Meta WhatsApp Calling

Sinch Conversation API

Customer webhook platform

Call flow (SIP signaling and media)

The call flow is illustrated below:

Call permission request / call button

Send message to Meta

Click call button / accept permission

Direct SIP signaling + RTP media

Voice app / PBX / contact center

Customer

Sinch Conversation API

Meta WhatsApp Calling

WhatsApp user

Customer-owned SIP infrastructure

Customer telephony platform

Call permission request / call button

Send message to Meta

Click call button / accept permission

Direct SIP signaling + RTP media

Voice app / PBX / contact center

Customer

Sinch Conversation API

Meta WhatsApp Calling

WhatsApp user

Customer-owned SIP infrastructure

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, you must use an approved WhatsApp template.

Sending a template call permission request

To send a template-based call permission request, use a Conversation API template_message and reference an approved WhatsApp template whose interaction type in Meta is call_permission_request.

Below is an example payload:

{
  "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 for more information.

Sending a free form call permission request

To send a free form call permission request during an open customer service window, use a channel_specific_message with message_type set to call_permission_request.

Below is an example payload:

{
  "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:

{
  "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 for more information.

Sending a free form call button message

To send a free form call button during an open customer service window, send a channel_specific_message with message_type set to voice_call.

Below is an example payload:

{
  "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:

FieldDescription
body.textRequired text shown together with the call button.
ttl_minutesTime-to-live for the call button CTA. Defaults to 10080 (7 days).
display_textThe text shown on the WhatsApp call button. Defaults to Call now.
payloadOptional 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.

FieldDescription
responseThe user's decision. Expected values are accept or reject.
is_permanenttrue if the user granted permanent permission, false for temporary permission.
expiration_timestampExpiration timestamp for temporary permission. Omitted for permanent permission.

Below is an example with temporary permission:

{
  "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:

{
  "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.

FieldDescription
directionThe call direction. For example, USER_INITIATED.
deeplink_payloadPayload received from a call deep link, when used.
cta_payloadPayload received from a call button message, when used.
sdp_typeOptional SDP type associated with the call session.
sdpOptional SDP content associated with the call session.
{
  "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.

FieldDescription
directionThe call direction. For example, USER_INITIATED.
deeplink_payloadPayload received from a call deep link, when used.
cta_payloadPayload received from a call button message.
statusCall result, for example COMPLETED.
start_timeCall start time.
end_timeCall end time.
durationCall duration.
{
  "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:

We'd love to hear from you!
Rate this content: