WhatsApp Business Calling media relay
The WhatsApp Business Calling model explains the capability: who may call whom, how permission works, and how calls are billed. This page goes one layer deeper into the question a customer hits when they diagnose “the call connects, but there is no audio”: where does the media go, and what decides whether it gets wired at all? The short answer: signalling and media take different paths. The call is set up over Meta’s Cloud API, while the audio leg is bridged between Meta’s WebRTC (DTLS-SRTP) side and your plain-RTP side by a relay — rtpengine — that the API programs over rtpengine’s NG-control protocol. If the relay host is not configured, everything except the audio still completes: the call record, the billing, the webhooks. That is a signalling-only call, and it is the expected behavior — not a crash — in that configuration. You read this page when you are enabling calling, diagnosing dead audio, or deciding whether the media leg of your deployment is wired at all.The seven components and the role each plays
Of the seven, four are always on: Meta Cloud API, the calling API pre-flight, webhook fanout, and the wallet check. Two are conditional: the relay pair (host + NG-control endpoint), which is bound by configuration, and recording, which is per-call.
The relay pair is the part a customer most often cannot reason about, because “unset” looks identical to “broken” from the outside: the call exists, the webhooks flow, the bill arrives, and there is simply no audio. The rest of this page is about that pair.
Where signalling ends and media begins
The configuration surface is deliberately thin — one variable binds the relay:
These are operator values, not tenant settings — mirrored into the API’s environment from the platform’s own secret store. You do not manage them from the dashboard.
Signalling-only is the name for the unbound state. It is not an error the call can recover from mid-call; it is a property of the deployment: the API was given no NG endpoint, so no
offer/answer ever reached rtpengine, so the RTP legs were never bridged. The call lifecycle is designed to survive that — a relay program failure degrades rather than aborts the call, by design, so provisioning the media gateway cannot break signalling while it is unreachable.
Below is the media path as a diagram. The dashed segment on the left is Meta’s WebRTC/DTLS-SRTP side; the solid segment on the right is the plain-RTP side your SIP endpoint terminates on; the box in the middle is the relay that copies packets between them:
The bottom two edges are the control plane; the top two are the media plane. A request on the control plane (offer, answer, delete) is what turns the top edges from an intention into a bridged pair of RTP legs.
Inbound: WhatsApp to the SIP endpoint
The inbound direction rings from the WhatsApp client into your number, and the accept step is when the two legs get programmed — marking where signalling hands off to media: The twoNG offer / NG answer steps are the entire media story. Everything above them is HTTPS and SIP; everything below them is packet forwarding. If the relay is unbound, the sequence runs unchanged except those two steps are skipped — and the media flows note never becomes real.
Outbound: SIP endpoint to the WhatsApp client
The outbound direction mirrors it, with the wallet pre-flight in front and Meta’s round-trip to originate: Same split: the call cannot start without the wallet and permission pre-flight, the call cannot carry audio without the relay program step, and the call always ends with the metering stamp and the webhook.Failure semantics per layer
Each layer degrades differently, and the differences are the reason “calls connect but no audio” is a configuration diagnosis rather than a crash report:
The design posture is consistent: media-plane failures degrade to signalling-only; signalling-plane and money-plane failures refuse the call outright. A relay outage never produces a half-billed call, and a billing refusal never produces a half-wired relay.
For the operator side of wiring the relay, the guide’s media relay section has the exact env-var table and the no-op contract.
How this differs from PSTN voice
If you already run PSTN voice on the platform, the model above has three sharp edges that PSTN does not:
The relay handoff is also the reason the optional SDP override field (
sdp_offer on the initiate-call request) is an escape hatch, not a mainstream path: it matters only when you control your own audio leg explicitly.
A worked call-receipt trace
This is the shape a reconciling consumer sees — one inbound call, wired, answered, terminated, stamped. The join key on the payload is thewa_call_log_id; the persisted row and every retry of the webhook both carry it, so either side is enough to reconcile:
whatsapp.call.received at ring, whatsapp.call.accepted (inbound) or whatsapp.call.connected (outbound), then whatsapp.call.terminated, all signed with the same HMAC scheme as the rest of the platform (Webhooks → Security).
See also
- WhatsApp Business Calling model — the capability model this page drills into, including the lifecycle webhook list.
- WhatsApp Business Calling guide — the step-by-step endpoint walkthrough, including the env-var table for the relay.
- Media planes — how the platform separates control and media planes generally; this page is the WhatsApp-specific instance of that split.
- Wallets, credits, and charges — the metering model the wallet pre-flight depends on.