Skip to content
Discuss your operation
VICIdial, Asterisk, SIP

WhatsApp SIP to VICIdial: an Implementation Pattern and Verification Plan

Meta can deliver a WhatsApp call to Asterisk. VICIdial still needs a secure trust boundary, a real DID route, and proof that signaling, media, agent delivery, and reporting all survive end to end.

Three contact-center operators facing a schematic WhatsApp calling and server display

A WhatsApp SIP connection looks like another carrier until the first real call exposes the differences. The business server's public certificate decides whether Meta delivers an inbound INVITE. Digest authentication and a maintained source ACL decide whether Asterisk should trust it. Number normalization decides whether VICIdial finds the DID. ACK routing and SRTP decide whether a connected call stays connected.

This guide works through those boundaries in order. It is written for VICIdial administrators and telephony engineers with shell access to Asterisk and administrator access to VICIdial. It is not a beginner SIP tutorial.

Choose the call direction before configuring anything

Inbound

User-initiated call

A WhatsApp user calls the business number. Meta sends a TLS SIP INVITE to Asterisk. Asterisk authenticates and identifies Meta, then sends the normalized destination into a VICIdial DID and inbound group.

Outbound

Business-initiated call

VICIdial selects a permitted destination. Asterisk sends an INVITE to wa.meta.vc, receives a 407 challenge, and retries with the Meta-generated SIP credential.

Architecture and trust boundaries

There are two boundaries. Meta knows SIP and WhatsApp identity; it does not know the generated contexts, DIDs, campaigns, queues, or reports inside VICIdial. Asterisk must bridge those worlds without turning a public TLS listener into an open trust boundary.

Prerequisites and compatibility checks

  • A WhatsApp Business phone number on Cloud API, with Calling and SIP enabled through an app in Live mode, the required messaging permission, and a healthy can_receive_call_sip status.
  • An explicit signaling choice: while SIP is enabled, calling-related Graph API endpoints do not work and calling webhooks are off unless SIP webhook delivery is enabled.[1]
  • The Meta-generated SIP password stored outside Git, tickets, screenshots, browser code, and public logs.
  • A public DNS name and trusted certificate whose subject covers that exact SIP hostname. Meta does not support mTLS for this boundary.[1]
  • Asterisk PJSIP with TLS, Opus, and the chosen SRTP mode available. This guide uses SDES; Meta defaults to DTLS, so both sides must agree.[1]
  • A maintained Meta SIP network ACL, firewall access to TLS 5061, and the local RTP range.
  • An existing working VICIdial inbound route to inspect rather than a guessed context name.
  • A maintenance window, rollback copy, and a test path isolated from live campaigns.

Verify the certificate before debugging dialplan logic:

openssl s_client -quiet \
  -verify_hostname voice.example.com \
  -connect voice.example.com:5061

Build the Meta-facing PJSIP endpoint

The following is an illustrative, self-contained adaptation of Meta's Asterisk example. It makes inherited endpoint behavior visible and separates inbound authentication from outbound authentication. Confirm every option against the Asterisk version actually installed.[2]

[transport-whatsapp-tls]
type=transport
protocol=tls
bind=0.0.0.0:5061
cert_file=<PUBLIC_CERTIFICATE_CHAIN>
priv_key_file=<PRIVATE_KEY>
ca_list_file=<TRUSTED_CA_BUNDLE>
verify_server=yes
allow_wildcard_certs=yes
external_media_address=<PUBLIC_IP>
external_signaling_address=<PUBLIC_IP>
local_net=<PRIVATE_CIDR>

[sdes_endpointtemplate](!)
type=endpoint
transport=transport-whatsapp-tls
context=from-whatsapp
acl=meta_whatsapp_sip
disallow=all
allow=opus,ulaw,alaw
direct_media=no
rtp_symmetric=yes
force_rport=yes
rewrite_contact=no
media_use_received_transport=yes
media_encryption=sdes

[whatsapp](sdes_endpointtemplate)
auth=whatsapp-inbound-auth
aors=whatsapp
from_user=<BUSINESS_NUMBER_WITHOUT_PLUS>
from_domain=voice.example.com
outbound_auth=whatsapp-outbound-auth

[whatsapp]
type=aor
contact=sip:wa.meta.vc;transport=tls

[whatsapp-identify]
type=identify
endpoint=whatsapp
match_header=X-FB-External-Domain: wa.meta.vc

[whatsapp-inbound-auth]
type=auth
; userpass is broadly compatible with older deployments; current Asterisk may
; internally convert it to digest. Verify the supported auth_type locally.
auth_type=userpass
username=<BUSINESS_NUMBER_WITHOUT_PLUS>
password=<META_SIP_PASSWORD>

[whatsapp-outbound-auth]
type=auth
auth_type=digest
username=<BUSINESS_NUMBER_WITHOUT_PLUS>
password=<META_SIP_PASSWORD>
realm=*

rewrite_contact=no matters because Meta documents a failure where modified Record-Route headers prevent ACK or BYE from following the dialog. The call can answer and carry audio, then fail around 32 seconds.[2]

Route calls through VICIdial

Inbound: Meta to an existing VICIdial DID

First inspect a working inbound carrier and the generated dialplan. Do not paste a plausible context name from an article.

asterisk -rx 'dialplan show' | less
asterisk -rx 'dialplan show <EXISTING_VICIDIAL_INBOUND_CONTEXT>'

Then keep the custom boundary narrow:

[from-whatsapp]
exten => _+<BUSINESS_NUMBER_WITHOUT_PLUS>,1,NoOp(Inbound WhatsApp call)
 same => n,Goto(<EXISTING_VICIDIAL_INBOUND_CONTEXT>,<VICIDIAL_DID>,1)
 same => n,Hangup()

The DID format must exactly match the value configured in VICIdial. Normalize once at this boundary. Confirm the route preserves VICIdial call logging, queue delivery, disposition, and recording behavior.

Outbound: a dedicated, permission-gated carrier path

Meta's route does not use conventional SIP REGISTER. Asterisk sends the destination to wa.meta.vc and answers Meta's digest challenge.[1] Therefore, pjsip show registrations is not a health test for this route.

[from-vicidial-whatsapp]
exten => _+X.,1,NoOp(Permission-gated outbound WhatsApp call)
 same => n,Dial(PJSIP/whatsapp/sip:${EXTEN}@wa.meta.vc;transport=tls)
 same => n,Hangup()

Use a dedicated local carrier prefix only after checking the existing dialplan for collisions. The actual VICIdial carrier string and campaign assignment are local design decisions. Do not connect this route to a campaign unless the application queries Meta's current permission immediately before dialing, requires start_call.can_perform_action, and matches the returned WhatsApp identity to the normalized destination.

Change a running server safely

A reload is a mutation, not a validation command. Before touching a running dialer:

  1. Back up the active PJSIP, dialplan, ACL, certificate references, and VICIdial carrier definition.
  2. Check whether port 5061 is already bound and whether the target include is generated.
  3. Confirm the required modules and codecs with module show like pjsip, module show like srtp, and core show codecs.
  4. Inspect active calls and drain or isolate the change during a maintenance window.
  5. Load the smallest possible include change. A transport may require a controlled restart because transport reload support varies.[4]
  6. Verify the endpoint, ACL, context, TLS listener, and existing non-WhatsApp routes immediately.
  7. Rollback if existing carriers fail, the endpoint cannot load, authentication loops, media is absent, or the test call cannot clear cleanly.
asterisk -rx 'pjsip show transports'
asterisk -rx 'pjsip show endpoint whatsapp'
asterisk -rx 'dialplan show from-whatsapp'
asterisk -rx 'core show channels concise'

Failure signatures that reveal the broken boundary

No INVITE reaches Asterisk

Check: DNS, TLS listener, public certificate chain, hostname match, Meta SIP settings, and firewall.

401 or 407 repeats

Check: Meta-generated password, fully normalized business-number username, From domain, and auth association.

Asterisk receives it, VICIdial does not

Check: endpoint identification, inbound digest, ACL, destination format, generated context, DID, and inbound group.

One-way or silent audio

Check: SDP, SRTP mode, Opus availability, NAT, advertised media address, and RTP firewall. Meta expects the business side to send the first SRTP packet for both directions.[1]

Call fails around 32 seconds

Check: ACK and BYE routes. Preserve Meta's Record-Route headers and inspect rewrite_contact=no.[2]

Call works but reporting is wrong

Check: whether the custom route passed through VICIdial's normal logging boundary, used the intended lead, and completed disposition and recording policy.

How to verify the integration

A loaded endpoint is not proof. Treat each row below as an acceptance gate.

BoundaryPass conditionEvidence to retain
EligibilityCalling, SIP, geography, identity match, unexpired permission, and start_call.can_perform_action pass immediately before dialingRedacted settings and runtime permission decision
TLSMeta validates the business server's public hostname and certificate chain; Asterisk validates wa.meta.vc on outbound TLSCertificate verification results for each direction
Inbound trustDigest, endpoint identification, and maintained Meta ACL all passRedacted SIP challenge and ACL match
Outbound authInitial INVITE receives 407; authenticated retry is acceptedRedacted SIP dialog
MediaTwo-way audio remains stable beyond the ACK timeout windowRTP/SRTP statistics and human confirmation
VICIdialExpected DID, inbound group, agent, lead, disposition, and recording policy are usedRedacted VICIdial records
HangupBoth sides clear normally when either side ends the callBYE and channel cleanup
RegressionExisting carriers, campaigns, agents, and inbound groups still workPre/post smoke results

What remains environment-specific

  • Asterisk and VICIdial versions, loaded modules, and generated include ownership
  • certificate, CA bundle, network ACL, NAT, and RTP range
  • actual VICIdial inbound context, DID, inbound group, carrier prefix, and campaign mapping
  • permission storage, normalized WhatsApp identity matching, operating hours, and call caps
  • recording notice, retention, access, opt-out, and local legal requirements
  • maintenance, monitoring, rollback, and incident ownership

Those values are the implementation. Replacing them with plausible examples would make this article easier to copy and less safe to use.

FAQ

Is WhatsApp SIP the same as a conventional PSTN trunk?

No. Meta provides SIP signaling for WhatsApp Business Calling. Asterisk must terminate that signaling securely, then map calls into VICIdial routing, queues, reporting, and recording.

Do outbound WhatsApp calls require user permission?

Yes. A working SIP route is not permission to call. Before every business-initiated call, validate current Meta calling permission and confirm that it belongs to the same normalized WhatsApp identity as the destination.

Does this route use SIP REGISTER?

Not for the Meta route shown here. Meta challenges a business-initiated INVITE with digest authentication and sends user-initiated INVITEs to the configured TLS server. A registered status for another carrier does not prove this route works.

Why can a call connect and then drop after about 32 seconds?

A common cause is broken ACK or BYE routing after Record-Route headers are changed. Meta documents preserving its route headers and using rewrite_contact=no for this Asterisk failure mode.

Can I paste this configuration into any VICIdial server?

No. The Meta-facing PJSIP objects are a self-contained pattern, but certificate paths, Asterisk capabilities, generated include files, ACL names, VICIdial contexts, DIDs, and carrier strings must be discovered and tested on the target installation.

Sources

  1. Meta, SIP Configuration Guide for WhatsApp Business Calling Updated 26 Jun 2026.
  2. Meta, Asterisk using SIP integration example Updated 21 May 2026.
  3. Meta, Cloud API Calling Updated 26 Jun 2026.
  4. Asterisk, PJSIP configuration sections and relationships
  5. Meta, obtain and check user call permissions

Need a deployment plan tied to your actual VICIdial server?

We can review compatibility, routing, permission enforcement, security controls, acceptance evidence, and rollback before a production change.

Talk through the integration Review VICIdial optimization