Business-Initiated Calls

Place outbound voice calls to WhatsApp users. POST /calls with action: connect, SDP offer/answer flow, call status webhooks (RINGING/ACCEPTED/REJECTED), terminate webhook with duration, biz_opaque_callback_data tracking.

Overview

Business-initiated calls (BIC) let your business place outbound voice calls to WhatsApp users. The user must have granted you call permission first — see Call Permissions. Permissions can be temporary (7 calendar days) or permanent.

BIC is not available when the business phone number's country is United States, Canada, Egypt, Vietnam, or Nigeria. The recipient can be in any country where Cloud API is available.

Prerequisites

  • Subscribe your app to the calls webhook field.
  • Calling enabled on the business phone number (see Calling Configuration).
  • Approved call permission from the recipient — error 138006 if absent.
  • Valid payment method on the WABA. UIC is free, but BIC is per-pulse billed (see Pricing).
  • Business phone number country in the BIC-supported list.

The Four-Step BIC Flow

  1. Obtain permission. Send a call permission request (free-form or template) and wait for the user to accept, or rely on callback_permission_status: ENABLED to auto-grant when the user calls you. See Call Permissions.
  2. POST /calls with action: connect and an SDP offer from your WebRTC stack.
  3. Apply the SDP answer Meta returns via the Call Connect webhook to your WebRTC stack to establish the media session. You'll then receive RINGING, ACCEPTED, or REJECTED status webhooks.
  4. Terminate when done — either you POST action: terminate, or the user hangs up. Either way, a Call Terminate webhook arrives.

The ACCEPTED status webhook typically arrives after the call is already established — Cloud API sends it primarily for auditing, not as a precondition for sending media.

Initiate a Call (POST /calls)

POST /<PHONE_NUMBER_ID>/calls
{
  "messaging_product": "whatsapp",
  "to": "12015550123",
  "action": "connect",
  "session": {
    "sdp_type": "offer",
    "sdp": "<<RFC 8866 SDP>>"
  },
  "biz_opaque_callback_data": "0fS5cePMok"
}
FieldNotes
toRecipient WhatsApp user phone number
actionconnect for new calls. Other values: pre_accept, accept, reject, terminate (used for user-initiated calls)
session.sdp_typeoffer for BIC
session.sdpRFC 8866 SDP — OPUS only, 48 kHz media clock, 8 kHz DTMF clock, ptime 20ms, single SSRC. See API Reference → Media Path Guidelines
biz_opaque_callback_dataOptional. Up to 512 chars. Echoed back in subsequent webhooks for tracking

Success response — note the wacid. prefix (WhatsApp Call ID, distinct from wamid. for messages):

{
  "messaging_product": "whatsapp",
  "calls": [
    { "id": "wacid.HBgLMTIxODU1NTI4MjgVAgARGCAyODRQIAFRoA" }
  ]
}

Rate limit: 10,000 new calls per 24 hours per business phone number.

biz_opaque_callback_data

An arbitrary string (up to 512 chars) that you pass into the call and that comes back unmodified in subsequent webhooks. Cloud API doesn't process it — it's purely for your own correlation (tying a call to a CRM record, an outbound campaign, etc.).

It's available on:

  • The Call Connect webhook (BIC)
  • The Call Terminate webhook (BIC and UIC if you accepted with one)
  • The Call Status webhook for RINGING/ACCEPTED/REJECTED

Set it on POST /calls with action: connect (BIC) or action: accept (UIC). It can't be added later.

Terminate a Call

POST /<PHONE_NUMBER_ID>/calls
{
  "messaging_product": "whatsapp",
  "call_id": "wacid.HBgLMTIxODU1NTI4MjgVAgARGCAyODRQIAFRoA",
  "action": "terminate"
}

Always call terminate even if you sent an RTCP BYE in the media path — this ensures accurate billing. You don't need to call it when the user hangs up; you'll just receive the Call Terminate webhook.

Success response:

{ "success": true }

Call Connect Webhook (SDP Answer)

Arrives near-real-time after a successful POST /calls connect. Apply the SDP answer to your WebRTC stack to start media flow.

{
  "object": "whatsapp_business_account",
  "entry": [
    {
      "id": "102290129340398",
      "changes": [
        {
          "field": "calls",
          "value": {
            "messaging_product": "whatsapp",
            "metadata": {
              "display_phone_number": "15550001234",
              "phone_number_id": "123456789012345"
            },
            "calls": [
              {
                "id": "wacid.HBgLMTIxODU1NTI4MjgVAgARGCAyODRQIAFRoA",
                "to": "12015550123",
                "from": "15550001234",
                "event": "connect",
                "direction": "BUSINESS_INITIATED",
                "timestamp": "1749196895",
                "biz_opaque_callback_data": "0fS5cePMok",
                "session": {
                  "sdp_type": "answer",
                  "sdp": "<<RFC 8866 SDP>>"
                }
              }
            ]
          }
        }
      ]
    }
  ]
}

Call Status Webhook (RINGING / ACCEPTED / REJECTED)

Mirrors the messaging-status webhook envelope but with type: "call":

{
  "object": "whatsapp_business_account",
  "entry": [
    {
      "id": "102290129340398",
      "changes": [
        {
          "field": "calls",
          "value": {
            "messaging_product": "whatsapp",
            "metadata": {
              "display_phone_number": "15550001234",
              "phone_number_id": "123456789012345"
            },
            "statuses": [
              {
                "id": "wacid.HBgLMTIxODU1NTI4MjgVAgARGCAyODRQIAFRoA",
                "type": "call",
                "status": "ACCEPTED",
                "timestamp": "1749197000",
                "recipient_id": "12015550123",
                "biz_opaque_callback_data": "0fS5cePMok"
              }
            ]
          }
        }
      ]
    }
  ]
}

status is one of RINGING, ACCEPTED, REJECTED. A REJECTED status is followed by a Call Terminate webhook. ACCEPTED typically arrives after media is already flowing.

Call Terminate Webhook

Arrives whenever the call ends — user hangs up, you call action: terminate or action: reject, network failure, etc.

{
  "object": "whatsapp_business_account",
  "entry": [
    {
      "id": "102290129340398",
      "changes": [
        {
          "field": "calls",
          "value": {
            "messaging_product": "whatsapp",
            "metadata": {
              "display_phone_number": "15550001234",
              "phone_number_id": "123456789012345"
            },
            "calls": [
              {
                "id": "wacid.HBgLMTIxODU1NTI4MjgVAgARGCAyODRQIAFRoA",
                "to": "12015550123",
                "from": "15550001234",
                "event": "terminate",
                "direction": "BUSINESS_INITIATED",
                "timestamp": "1749197480",
                "status": "COMPLETED",
                "start_time": "1749196900",
                "end_time": "1749197480",
                "duration": 580,
                "biz_opaque_callback_data": "0fS5cePMok"
              }
            ],
            "errors": [
              { "code": 138019, "message": "Call setup failed" }
            ]
          }
        }
      ]
    }
  ]
}
FieldNotes
statusCOMPLETED (call was answered) or FAILED
start_time, end_time, durationOnly present when the other party picked up. duration is in seconds.
errorsPresent only on failed calls — see Troubleshooting → Calling Error Codes

Limits

LimitDefault
New BIC calls per business phone number10,000 / 24h
Connected BIC calls per business + user pair100 / 24h (sandbox: relaxed)
Connected BIC calls per business + user pair (per pricing tier)5 / 24h on the lowest-volume tier
Concurrent inbound calls per phone number1,000
Consecutive unanswered BIC calls before "reconsider" system message2 (sandbox: 5)
Consecutive unanswered BIC calls before permission auto-revoked4 (sandbox: 10)

A connected call resets unanswered counters and call-permission-request rate limits between that business and that user.

Common Errors

CodeMeaningFix
138000Calling not enabledConfigure call settings (see Calling Configuration)
138001Receiver uncallable (not on WhatsApp, hasn't accepted ToS, or unsupported client)Confirm with recipient
138002Concurrent calls limit (1,000) reachedThrottle inbound capacity
138003Duplicate call — one is already ongoing with the receiverWait for current call to end
138005Call rate limit exceededReduce sending rate
138006No approved call permission foundSend permission request first (Call Permissions)
138012BIC daily limit hit (100 connected calls / 24h)Wait for next-call timestamp in error_data
138013BIC not available for this business phone number countryCheck availability list
138014Calling temporarily disabled (low quality)Improve outreach quality, wait for restriction expiration
138017Permission request can't be sent — permanent permission already existsJust place the call directly

Full error reference and SIP-specific errors are on Calling Troubleshooting.

Related

  • Cloud API CallingVoice calling on WhatsApp Business Cloud API: VoIP via WebRTC or SIP, business-initiated and user-initiated calls, prerequisites, availability, and integration patterns.
  • Call PermissionsObtain permission to call WhatsApp users: temporary (7-day) and permanent permissions, three ways to obtain (free-form request, template request, callback auto-prompt, business profile), get permission state endpoint, permission reply webhook.
  • Call Buttons & Deep LinksDrive WhatsApp calls from messages and links: voice_call interactive messages, voice_call template buttons, wa.me/call/<number> deep links with biz_payload tracking.
  • Calling PricingHow Meta bills WhatsApp Calling: free user-initiated calls, per-pulse business-initiated billing, volume tiers, customer service window interaction, call permission request charges, billing prerequisites.
  • Calling TroubleshootingWhatsApp Calling errors and fixes: full error code table (138000-138023), SIP-specific status codes, media-flow timeouts, audio clipping causes and mitigations (SDES, pre-accept), quick triage guide.
Browse more docsStart Free Trial