> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# WhatsApp Calling API

> WhatsApp Business voice/video call capability management

# WhatsApp Calling API

WhatsApp Business voice/video call capability management

**Base path:** `/api/v1/whatsapp`

**Endpoint count:** 3

***

### WhatsApp Business Calling KPIs

<Note>
  `GET /api/v1/whatsapp/calling/analytics`
</Note>

Returns aggregated KPIs (totals, answered, declined, missed, failed, avg duration, total cost) plus a per-day call-volume trend over a configurable window (1-365 days, default 30).

<ParamField query="waba_id" type="string">
  —
</ParamField>

<ParamField query="phone_number_id" type="string">
  —
</ParamField>

<ParamField query="days" type="integer">
  —
</ParamField>

<RequestExample>
  <CodeGroup>
    ```bash cURL theme={null}
    curl -X GET "https://api.orbit.devotel.io/api/v1/whatsapp/calling/analytics" \
      -H "X-API-Key: dv_live_sk_your_key_here" 
    ```

    ```typescript Node.js theme={null}
    import { Orbit } from '@devotel/orbit-sdk'

    const orbit = new Orbit({
      apiKey: process.env.ORBIT_API_KEY!,
    })

    const res = await fetch('https://api.orbit.devotel.io/api/v1/whatsapp/calling/analytics', {
      method: 'GET',
      headers: {
        'X-API-Key': process.env.ORBIT_API_KEY!,
      },
    })
    console.log(await res.json())


    ```

    ```python Python theme={null}
    import os, requests

    headers = {"X-API-Key": os.environ["ORBIT_API_KEY"]}
    r = requests.get("https://api.orbit.devotel.io/api/v1/whatsapp/calling/analytics", headers=headers)
    print(r.json())
    ```

    ```go Go theme={null}
    package main

    import (
    	"bytes"
    	"net/http"
    	"os"
    )

    func main() {
    	req, _ := http.NewRequest("GET", "https://api.orbit.devotel.io/api/v1/whatsapp/calling/analytics", nil)
    	req.Header.Set("X-API-Key", os.Getenv("ORBIT_API_KEY"))

    	http.DefaultClient.Do(req)
    }
    ```

    ```ruby Ruby theme={null}
    require 'net/http'
    require 'json'

    uri = URI('https://api.orbit.devotel.io/api/v1/whatsapp/calling/analytics')
    req = Net::HTTP::Get.new(uri)
    req['X-API-Key'] = ENV['ORBIT_API_KEY']


    res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |h| h.request(req) }
    puts res.body
    ```

    ```php PHP theme={null}
    <?php
    $ch = curl_init('https://api.orbit.devotel.io/api/v1/whatsapp/calling/analytics');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
      'X-API-Key: ' . getenv('ORBIT_API_KEY'),

    ]);

    echo curl_exec($ch);
    ```
  </CodeGroup>
</RequestExample>

***

### List WhatsApp Business Call logs

<Note>
  `GET /api/v1/whatsapp/calling/calls`
</Note>

Cursor-paginated list of wa\_call\_logs rows. Phone columns are masked for viewer/billing roles; owner/admin/developer see raw E.164. The `q` search covers phone + contact name + contact email + conversation\_id columns.

<ParamField query="status" type="string">
  CSV of statuses to include. Allowed: queued, ringing, in\_progress, completed, failed, missed.
</ParamField>

<ParamField query="direction" type="string (enum: inbound|outbound)">
  —
</ParamField>

<ParamField query="waba_id" type="string">
  —
</ParamField>

<ParamField query="phone_number_id" type="string">
  —
</ParamField>

<ParamField query="contact_id" type="string">
  Restrict results to a single contact's call history. Unlike `q` (free-text search across phone, contact name, contact email, and conversation\_id), this matches on the exact contact id, so it returns only calls linked to that contact. Use it to build a per-contact call-history view. Max 64 characters.
</ParamField>

<ParamField query="start" type="string">
  —
</ParamField>

<ParamField query="end" type="string">
  —
</ParamField>

<ParamField query="q" type="string">
  —
</ParamField>

<ParamField query="cursor" type="string">
  —
</ParamField>

<ParamField query="limit" type="integer">
  —
</ParamField>

<RequestExample>
  <CodeGroup>
    ```bash cURL theme={null}
    curl -X GET "https://api.orbit.devotel.io/api/v1/whatsapp/calling/calls" \
      -H "X-API-Key: dv_live_sk_your_key_here" 
    ```

    ```typescript Node.js theme={null}
    import { Orbit } from '@devotel/orbit-sdk'

    const orbit = new Orbit({
      apiKey: process.env.ORBIT_API_KEY!,
    })

    const res = await fetch('https://api.orbit.devotel.io/api/v1/whatsapp/calling/calls', {
      method: 'GET',
      headers: {
        'X-API-Key': process.env.ORBIT_API_KEY!,
      },
    })
    console.log(await res.json())


    ```

    ```python Python theme={null}
    import os, requests

    headers = {"X-API-Key": os.environ["ORBIT_API_KEY"]}
    r = requests.get("https://api.orbit.devotel.io/api/v1/whatsapp/calling/calls", headers=headers)
    print(r.json())
    ```

    ```go Go theme={null}
    package main

    import (
    	"bytes"
    	"net/http"
    	"os"
    )

    func main() {
    	req, _ := http.NewRequest("GET", "https://api.orbit.devotel.io/api/v1/whatsapp/calling/calls", nil)
    	req.Header.Set("X-API-Key", os.Getenv("ORBIT_API_KEY"))

    	http.DefaultClient.Do(req)
    }
    ```

    ```ruby Ruby theme={null}
    require 'net/http'
    require 'json'

    uri = URI('https://api.orbit.devotel.io/api/v1/whatsapp/calling/calls')
    req = Net::HTTP::Get.new(uri)
    req['X-API-Key'] = ENV['ORBIT_API_KEY']


    res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |h| h.request(req) }
    puts res.body
    ```

    ```php PHP theme={null}
    <?php
    $ch = curl_init('https://api.orbit.devotel.io/api/v1/whatsapp/calling/calls');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
      'X-API-Key: ' . getenv('ORBIT_API_KEY'),

    ]);

    echo curl_exec($ch);
    ```
  </CodeGroup>
</RequestExample>

***

### Initiate an outbound WhatsApp Business Call (Phase 5)

<Note>
  `POST /api/v1/whatsapp/calling/calls`
</Note>

Initiate a WhatsApp Business outbound call. Walks pre-flight gates: connection lookup + access-token decrypt, country block-list (WA\_CALLING\_BLOCKED\_COUNTRIES), calling-enabled flag on the WABA, and recipient call-permission grant. Permission-missing returns 422 with code WHATSAPP\_CALLING\_NO\_PERMISSION; the dashboard surfaces a CTA to send the call-permission template first.

<ParamField body="to" type="string" required>
  Recipient phone number in E.164 format, including the leading `+` (e.g. `+14155552671`). The `+` is required — omitting it fails validation.
</ParamField>

<ParamField body="from_phone_number_id" type="string" required>
  Meta phone\_number\_id of the sender WABA number.
</ParamField>

<ParamField body="conversation_id" type="string">
  —
</ParamField>

<ParamField body="recording_consent" type="boolean">
  —
</ParamField>

<ParamField body="biz_opaque_callback_data" type="string">
  Echoed back on every webhook event for the call (correlation handle).
</ParamField>

<ParamField body="sdp_offer" type="string">
  SDP offer for browser-side WebRTC. Omit for server-bridged calls.
</ParamField>

<RequestExample>
  <CodeGroup>
    ```bash cURL theme={null}
    curl -X POST "https://api.orbit.devotel.io/api/v1/whatsapp/calling/calls" \
      -H "X-API-Key: dv_live_sk_your_key_here" \
      -H "Content-Type: application/json" \
      -d '{
      "to": "string",
      "from_phone_number_id": "string"
    }'
    ```

    ```typescript Node.js theme={null}
    import { Orbit } from '@devotel/orbit-sdk'

    const orbit = new Orbit({
      apiKey: process.env.ORBIT_API_KEY!,
    })

    const res = await fetch('https://api.orbit.devotel.io/api/v1/whatsapp/calling/calls', {
      method: 'POST',
      headers: {
        'X-API-Key': process.env.ORBIT_API_KEY!,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
      "to": "string",
      "from_phone_number_id": "string"
    }),
    })
    console.log(await res.json())
    ```

    ```python Python theme={null}
    import os, requests

    headers = {"X-API-Key": os.environ["ORBIT_API_KEY"]}
    headers["Content-Type"] = "application/json"
    r = requests.post("https://api.orbit.devotel.io/api/v1/whatsapp/calling/calls", headers=headers, json={
      "to": "string",
      "from_phone_number_id": "string"
    })
    print(r.json())
    ```

    ```go Go theme={null}
    package main

    import (
    	"bytes"
    	"net/http"
    	"os"
    )

    func main() {
    	req, _ := http.NewRequest("POST", "https://api.orbit.devotel.io/api/v1/whatsapp/calling/calls", bytes.NewBuffer([]byte(`{
      "to": "string",
      "from_phone_number_id": "string"
    }`)))
    	req.Header.Set("X-API-Key", os.Getenv("ORBIT_API_KEY"))
    	req.Header.Set("Content-Type", "application/json")
    	http.DefaultClient.Do(req)
    }
    ```

    ```ruby Ruby theme={null}
    require 'net/http'
    require 'json'

    uri = URI('https://api.orbit.devotel.io/api/v1/whatsapp/calling/calls')
    req = Net::HTTP::Post.new(uri)
    req['X-API-Key'] = ENV['ORBIT_API_KEY']
    req['Content-Type'] = 'application/json'
    req.body = {
      "to": "string",
      "from_phone_number_id": "string"
    }.to_json
    res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |h| h.request(req) }
    puts res.body
    ```

    ```php PHP theme={null}
    <?php
    $ch = curl_init('https://api.orbit.devotel.io/api/v1/whatsapp/calling/calls');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
      'X-API-Key: ' . getenv('ORBIT_API_KEY'),
      'Content-Type: application/json',
    ]);
    curl_setopt($ch, CURLOPT_POSTFIELDS, <<<JSON
    {
      "to": "string",
      "from_phone_number_id": "string"
    }
    JSON);
    echo curl_exec($ch);
    ```
  </CodeGroup>
</RequestExample>

***
