Integrating WhatsApp Cloud API Calling into Asterisk / FreePBX / SIP

Meta’s WhatsApp Cloud API now supports Calling via SIP, so you can terminate WhatsApp calls directly into your PBX — Asterisk, FreePBX, or any SIP-capable system.

1) Prerequisites

Before you start, make sure you have:

  1. A registered WhatsApp Business Number via the Meta Cloud API (e.g., through ORENCloud, Twilio, or your provider).

  2. Calling + SIP enabled for that number (see Meta docs or your provider’s cURL setup guide).

  3. The following values from the API:

    • SIP Username – your WhatsApp Business Number (no “+”)

    • SIP Password – generated by Meta

    • SIP Server Hostname & Port – returned by the API

Note: Do not use the plus sign (+) in your SIP trunk usernames or section names. Use + only for inbound route matching if needed.


2) Enable Calling + SIP in Meta

From your provider portal or Meta API:

  1. Enable Calling for your WhatsApp Business Number.

  2. Enable SIP and record your SIP server hostname:port.

  3. Generate and copy the SIP password for this number.


3) Asterisk / FreePBX Configuration

3.1 Dialplan (Inbound Context)

Create a dedicated context to handle WhatsApp calls.

File: /etc/asterisk/extensions_custom.conf

[from-whatsapp]
exten => _.,1,NoOp(Handling WhatsApp call - tighten this in production)
 same => n,Goto(from-pstn,${EXTEN},1) ; or route to your chosen inbound context
 same => n,Hangup()

Purpose: Central place to control how WhatsApp calls are routed inside your PBX.

Security tip: Avoid broad wildcards in production. Replace _. with explicit DIDs/patterns, and route only what you expect.


3.2 PJSIP Trunk

You can manage this via the FreePBX GUI (Connectivity → Trunks → Add Trunk → PJSIP) or with custom include files. The examples below use custom files so you can scale to multiple WhatsApp numbers cleanly.

Suggested files:

  • /etc/asterisk/pjsip.custom.wageneral.conf – shared transport

  • /etc/asterisk/pjsip.custom.wanumbers.conf – one or more numbers

Ensure your main PJSIP config loads them, for example:

; In /etc/asterisk/pjsip_custom.conf (FreePBX) or pjsip.conf includes
#include pjsip.custom.wageneral.conf
#include pjsip.custom.wanumbers.conf

Shared Transport:

pjsip.custom.wageneral.conf

[whatsapp-tls]
type=transport
protocol=tls
bind=0.0.0.0:5061
cert_file=/etc/asterisk/keys/yourcert.crt
priv_key_file=/etc/asterisk/keys/yourkey.key

Use a valid, trusted certificate. Self-signed certs are often rejected.

Per-Number Blocks:

pjsip.custom.wanumbers.conf

Replace the ALL-CAPS placeholders with your actual values.

Do not include “+” in usernames or section names.

; -------- AUTH --------
[YOUR_WHATSAPP_NUMBER-auth]
type=auth
auth_type=userpass
username=YOUR_WHATSAPP_NUMBER
password=YOUR_META_GENERATED_PASSWORD

; -------- AOR --------
[YOUR_WHATSAPP_NUMBER-aor]
type=aor
max_contacts=5
qualify_frequency=10 ; this matters to keep low, don't use 0

; -------- ENDPOINT --------
[YOUR_WHATSAPP_NUMBER]
type=endpoint
transport=whatsapp-tls
context=from-whatsapp
disallow=all
allow=opus
aors=YOUR_WHATSAPP_NUMBER-aor
auth=YOUR_WHATSAPP_NUMBER-auth
media_encryption=dtls
dtls_verify=fingerprint
dtls_setup=actpass
webrtc=yes
rtp_symmetric=yes
direct_media=no
trust_id_inbound=yes
send_connected_line=false
identify_by=auth_username
user_eq_phone=yes
dtmf_mode=auto
language=en
force_rport=yes
rewrite_contact=yes

; -------- IDENTIFY (lock trunk to Meta SIP IP) --------
[identify-YOUR_WHATSAPP_NUMBER]
type=identify
endpoint=YOUR_WHATSAPP_NUMBER
match=SIP_SERVER_IP_FROM_META ;if required, but dont, since Meta's IP changes all the time

Key notes

  • Opus only: WhatsApp uses Opus. Keep other codecs disabled unless your provider says otherwise.

  • Identify: Set match= to the SIP IP(s) Meta returns to you.

  • DTLS/SRTP: The example uses DTLS with actpass. If your provider specifies different media security, apply their settings.


4) Firewall & Security

  • Allow inbound TLS 5061 and your RTP/SRTP port range (as configured in Asterisk).

  • Restrict inbound SIP to Meta’s IP ranges using your firewall and the identify match= rule.

  • Keep your SIP password secret and rotate if compromised.


5) Testing

  1. Reload Asterisk:

    • FreePBX: fwconsole reload

    • Asterisk: asterisk -rx “module reload res_pjsip.so”

  2. From any WhatsApp account, call your Business Number.

  3. Open the Asterisk console and verify routing: asterisk -rvvvvv

    • Confirm the call hits [from-whatsapp] and follows your routing.

FreePBX shortcut: Add a PJSIP Trunk in the GUI with the values above, then set the Incoming context to from-whatsapp.


Quick Troubleshooting

  • 403/401 Unauthorized: Wrong username/password or realm. Confirm the SIP username is your number without “+”.

  • 488 Not Acceptable Here: Codec mismatch — ensure allow=opus and others are disabled unless instructed.

  • TLS/DTLS errors: Use a trusted TLS cert; verify time sync (NTP); ensure media_encryption=dtls matches provider requirements.

  • No audio / one-way audio: Open RTP/SRTP ports; confirm symmetric RTP settings; check NAT configuration.


Resources