Skip to main content
WhatsApp Business Calling lets customers call your business number from the chat, and lets you call customers who have said you may. LazyApp handles the signalling: it relays the call setup to Meta, keeps call history, records and transcribes calls when you ask, and sends call.* webhooks. The audio itself runs in a browser or on your own WebRTC or SIP system, never through LazyApp.
Calling has to be switched on by Meta for each number. It needs a messaging limit of at least 2,000 customers a day, and LazyApp’s own Meta app needs calling approval. Until then, GET /v1/capabilities reports calling: false and the call endpoints answer 422 with code: capability_unavailable.

Two ways to take calls

In the inbox

While the inbox is open, an incoming call rings in the corner with Answer and Decline. To call someone, open their chat and click the phone button. If they have not allowed calls yet, LazyApp offers to send them a permission request first. You can switch on Record and transcribe before answering or calling. The browser asks for microphone access the first time.

Settings

Turn calling on, hide or show the call button, set call hours, ask for permission to call back, and set up voicemail in Connections → number → Calling. The same settings are available over the API:
calling takes Meta’s own fields: status, call_icon_visibility, call_icons.restrict_to_user_countries, callback_permission_status, call_hours, audio.additional_codecs (PCMA, PCMU), srtp_key_exchange_protocol (DTLS or SDES), voicemail and sip. SIP passwords are never returned.
The inbox softphone needs DTLS, the default. Choose SDES only for a SIP server.

Voicemail

With voicemail on, a call you decline, or that rings for timeout_seconds (5–60), is answered by WhatsApp, which plays your greeting and records a message. The recording arrives as an ordinary inbound voice note with content.voicemail.call_id. Upload the greeting (OGG/Opus, under 60 seconds) in the calling settings. Turn call hours off to use voicemail: customers cannot ring outside call hours. Each number has a call link, https://wa.me/call/<number>, shown in the calling settings. Put it on your website or in an email; opening it starts a WhatsApp call.

Permission to call

A business can only call someone who said yes. Check first:
to can also be a business-scoped user id. actions is Meta’s detail, including how many requests and calls you have left. If can_call is false, ask:
Their answer arrives as call.permission_request. WhatsApp allows one request a day and two a week per person.

Answer a call (your own client)

  1. call.received fires, and GET /v1/calls/{uuid} returns the caller’s SDP offer as session (type: offer).
  2. Create an SDP answer in your WebRTC stack and send it with pre-accept, so the media path is ready before the caller hears anything.
  3. Send the same answer with accept. Meta rejects a different one.
Decline with POST /v1/calls/{uuid}/reject.

Place a call (your own client)

Meta’s SDP answer arrives on the calls webhook; poll GET /v1/calls/{uuid} until session.type is answer and apply it. If the person has not allowed calls, the response is 422 with code: call_permission_missing. End any call with POST /v1/calls/{uuid}/terminate, even after your media path hung up: Meta prices calls from that signal.

Media requirements

Meta’s media stack is WebRTC-compatible but strict. Use Opus at 48 kHz with ptime 20, DTMF (telephone-event) at 8 kHz, and a single audio SSRC. Meta is ICE-lite, so your side takes the ICE controlling role and acts as the DTLS client. Meta provides no STUN or TURN servers.

Recordings and transcripts

Ask for a recording, a transcript, or both, per call, on accept or on a business-initiated POST /v1/calls:
Both people hear a short notice built from purpose (up to 250 characters) before recording starts. announcement_language is one of en, en_US, en_AU, en_CA, en_GB, en_IN, en_NZ, nl, fr, de, hi, it, kn, pt, es, es_ES, te, vi. About a minute after the call ends, LazyApp downloads both from Meta and sends call.recording_available and call.transcript_available. GET /v1/calls/{uuid} then reports:
Download the audio from GET /v1/calls/{uuid}/recording. It answers 409 with code: recording_pending while the download is still running, and 404 with code: no_recording when the call was not recorded.

Call history

GET /v1/calls lists calls newest first, cursor-paginated. Each call has direction, status (ringing, accepted, rejected, missed, terminated, failed), the numbers, timestamps and duration_seconds.

Pricing

Customer-initiated calls are free. Business-initiated calls are charged by Meta per six-second pulse, by the country called, with volume tiers. Meta bills them to your own Meta payment method, and LazyApp adds 0%. A call permission request is an ordinary message.