What is a business-initiated call?
A business-initiated call is an outbound voice call that a business places from its WhatsApp business phone number to a WhatsApp user through the WhatsApp Business Calling API on the Cloud API. It is the mirror image of a user-initiated call, where the customer taps the call icon or a call button in the chat. Here the business dials: the user's phone rings with the business's name and profile picture, and the conversation runs over WhatsApp's internet calling rather than the phone network.
The defining rule is consent. A business may call only users who have granted it call permission — by accepting a call permission request, by calling the business when callback permission is switched on in its calling settings, or by allowing calls permanently. A call to anyone else is refused with error 138006. Temporary approvals last seven days, Meta limits how many calls and requests a business can make, and repeated unanswered calls cost the permission itself, so outbound calling is built for calls the customer expects — a scheduled callback, a delivery query, a document check — not for dialling lists.
Technically the business is one end of a WebRTC call. It sends POST /{PHONE_NUMBER_ID}/calls with action: "connect", the user's number and an SDP offer. Meta returns a call ID, delivers its SDP answer and the RINGING, ACCEPTED or REJECTED statuses on the calls webhook field, and posts a terminate event with the duration when the call ends. A business with an existing contact centre can use WhatsApp Calling over SIP instead and let its PBX handle signalling and media. Under Calling API pricing these calls are billed per 6-second pulse, unlike user-initiated calls, which carry no call charge.
Key takeaways
- A business-initiated call is an outbound WhatsApp voice call from a business number to a user who has granted call permission.
- Without the user's call permission the connect request fails with error
138006, so check permission right before dialling. - The call starts with
POST /{PHONE_NUMBER_ID}/callsand an SDP offer; the answer, ringing and hang-up arrive on thecallswebhook. - Meta bills business-initiated calls per 6-second pulse at the called country's rate; calls users place to you carry no call charge.
- They need a Cloud API number with a messaging limit of at least 2,000 and are unavailable for business numbers in the US, Canada, Egypt, Vietnam and Nigeria.
Figure 1
Follow one outbound call from permission check to hang-up
- Your serversoftphone + WebRTC
- Cloud API/calls + calls webhook
- CustomerWhatsApp app
Step 10 of 10Event
Cloud APIYour server
Webhook: terminate, COMPLETED, 240 s
40 pulses
- Request — solid arrow — a call that expects an answer
- Response — dashed arrow — the answer coming back
- Event — dotted arrow — something happened and is pushed out
- Async — double head — fire-and-forget, nobody waits
Step 10 of 10: Cloud API to Your server — Webhook: terminate, COMPLETED, 240 s. 40 pulses
Why it matters
Why does a business-initiated call matter?
Some conversations need a voice: a lender checking property papers, a clinic confirming a surgery slot, a courier finding the right gate in a gated society. A business-initiated call lets that happen inside the app the customer already trusts, from a number that shows the business's name instead of an unknown mobile number that gets ignored or reported as spam. Because it needs prior permission and is metered per pulse, it rewards teams that call when the customer expects it and punishes cold dialling — unanswered calls lead Meta to withdraw the permission.
How does a business-initiated call work?
Enable calling and subscribe to calls
Switch calling on in the number's calling settings (the portfolio needs a messaging limit of at least 2,000) and subscribe your app to the
callswebhook field. Decide now whether media terminates in your own WebRTC stack or on a SIP trunk.Secure permission first
Send a call permission request inside an open window or as a template, or let users who call you grant callback permission. Right before dialling, confirm the state with
GET /{PHONE_NUMBER_ID}/call_permissions.Send connect with an SDP offer
POST to
/{PHONE_NUMBER_ID}/callswithmessaging_product,to,action: "connect"and asessionholding your SDP offer (sdp_type: "offer"). The response carries the call ID;biz_opaque_callback_datatags it with your own reference.Apply Meta's SDP answer
A
connectevent on thecallswebhook bringssession.sdpwithsdp_type: "answer". Apply it to your peer connection so audio flows when the user picks up;RINGING, thenACCEPTEDorREJECTED, arrive as call statuses.Hang up and reconcile
When your agent ends the call, send
action: "terminate"with thecall_id. Theterminatewebhook reportsCOMPLETEDorFAILED, plusstart_time,end_timeanddurationwhen the user answered — the figures to reconcile pulses against.
A business-initiated call in code
# 1. Start the call (the user must have granted call permission)curl -X POST "https://graph.facebook.com/v26.0/{PHONE_NUMBER_ID}/calls" \-H "Authorization: Bearer {ACCESS_TOKEN}" \-H "Content-Type: application/json" \-d '{"messaging_product": "whatsapp","to": "919812345678","action": "connect","session": {"sdp_type": "offer","sdp": "{SDP_OFFER_FROM_YOUR_WEBRTC_STACK}"},"biz_opaque_callback_data": "loan-4471-doc-check"}'# 200 OK# { "messaging_product": "whatsapp", "calls": [ { "id": "wacid.HBgLOTE5ODEyMzQ1Njc4FQIAEhgg..." } ] }# 2. End it from your sidecurl -X POST "https://graph.facebook.com/v26.0/{PHONE_NUMBER_ID}/calls" \-H "Authorization: Bearer {ACCESS_TOKEN}" \-H "Content-Type: application/json" \-d '{ "messaging_product": "whatsapp", "call_id": "wacid.HBgLOTE5ODEyMzQ1Njc4FQIAEhgg...", "action": "terminate" }'# 200 OK → { "messaging_product": "whatsapp", "success": true }
Send terminate even if your media stack already sent an RTCP BYE, so call state and pulses stay accurate.
Example: A document check from a Chennai home-loan desk
A Chennai home-loan lender needs borrowers to confirm details on their sale deed before disbursal. Its approved utility template ends with a call permission request: "May your loan officer call you on WhatsApp about your documents?" A borrower taps Allow on Tuesday evening. On Wednesday at 11 am the officer's softphone checks call_permissions, sees a temporary permission valid until the following Tuesday, and places the call. The borrower sees the lender's verified name, answers, and the check takes four minutes — 40 pulses at the India rate. Borrowers who declined are never dialled, and one who missed the call twice gets a chat message offering a time instead of a third call.
Common mistakes with a business-initiated call
Dialling without checking permission
A connect without valid permission fails with
138006, and temporary permissions lapse after seven days without any webhook. Querycall_permissions— or at least your storedexpiration_timestamp— right before every call.Calling until someone answers
After two unanswered business-initiated calls in a row WhatsApp asks the user to reconsider the permission, and after four it is revoked automatically. Cap retries and switch to a message after a missed call.
Treating the 200 as connected
The API response only means the call was created. Ringing, answer and rejection arrive later on the
callswebhook, and only adurationon the terminate event proves a conversation happened.Not sending terminate
If your side hangs up, call the endpoint with
action: "terminate"even when an RTCP BYE has gone out. Skipping it leaves call state wrong and pulse counts hard to reconcile.Testing media only on office Wi-Fi
Calls that connect but carry no audio usually mean missing ICE candidates or TURN relays. Test from mobile networks, and remember Opus is always on while G.711 needs transcoding.
Best practices for a business-initiated call
- Ask for permission in the message where a call makes sense ("Shall our officer call you at 11?"), not in a generic opt-in.
- Store
expiration_timestampfrom the permission reply so agents see "callable until" beside each contact. - Tag every call with
biz_opaque_callback_dataso webhooks map straight back to the ticket or lead. - Send a short message before calling so the ring is expected; answered calls keep the permission alive.
- Choose SIP if you already run a contact centre; build on WebRTC only if you want to own the media stack.
Business-Initiated Call FAQs
- Can a business call any WhatsApp user through the API?
- No. A business can call only users who have granted it call permission. Without it the connect request fails with error 138006; permission comes from a call permission request, a callback granted when the user calls you, or a permanent approval.
- How much does a business-initiated WhatsApp call cost?
- Meta charges per 6-second pulse at the rate for the called number's country, with monthly volume tiers. Part pulses round up, so a 56-second call is 10 pulses; the permission request is billed separately as a message.
- Do I need WebRTC to make business-initiated calls?
- You need WebRTC or SIP. With the calling endpoints your system exchanges SDP offers and answers and runs the audio itself; with SIP enabled on the number, your SIP server or PBX handles signalling and media and the calling endpoints are not used.
- What is the difference between a business-initiated and a user-initiated call?
- Who dials. A user-initiated call starts from the call icon or a call button in the chat, needs no permission and carries no call charge; a business-initiated call needs prior permission, is placed through the /calls endpoint and is billed per pulse.
- Can I place business-initiated calls from a WhatsApp Business app number?
- No. Business-initiated calling needs a Cloud API number. Numbers on the WhatsApp Business app, including coexistence numbers, do not get platform calling.