Skip to main content
FlowIQ answers WhatsApp calls in the inbox, or with its own voice AI. The Calling API lets you do it yourself instead: your server hears about each call the moment it rings, answers it with its own audio (your voice agent, a call centre, an IVR), and FlowIQ keeps the call in the customer’s chat history.
WhatsApp calling must be switched on for your number first: Update Calling Settings with "status": "ENABLED", or Settings, Integrations, WhatsApp in FlowIQ. WhatsApp requires a verified business and a messaging limit of 2,000 or more.

Endpoints

Events arrive on your webhook as the call event.

Authentication and limits

Use your organisation API key (Settings, API Keys) as a Bearer token. The key decides which number you act on; you never pass an organisation id. Limits per key: 240 reads and 60 actions a minute. Every response carries organization_id and an X-Request-Id; errors carry a stable code; POST and PATCH accept an Idempotency-Key. See Conventions.

Three ways to answer

Set it for the number with Update Calling Settings. With api you can also answer any single call by stream: Accept Call with stream instead of sdp.

Answer incoming calls with your own server

  1. Register a webhook for the call event (or all): Create Webhook.
  2. Take the calls away from FlowIQ: PATCH /v1/calling/settings with {"answered_by": "api"}. The FlowIQ inbox stops ringing and FlowIQ’s voice AI stops picking up. Calls still show in the customer’s chat. Switch back any time with "flowiq".
  3. When a customer calls, your webhook receives kind: "call", call.event: "connect" and WhatsApp’s SDP offer in call.session.sdp.
  4. Answer: create an SDP answer for that offer with your WebRTC stack and send it with Accept Call. Pre-accept first if you want the audio to flow the moment you accept.
  5. The call runs between WhatsApp and your media server. Audio never passes through FlowIQ. End it with End Call; when either side hangs up you receive call.event: "terminate" with the duration.
With answered_by set to api, nobody answers if your server does not. Callers hear it ring out.

Stream the audio to your own voice agent

The simplest way to put an AI voice agent on WhatsApp: no WebRTC, no SDP. FlowIQ answers the call and opens a WebSocket to you with the caller’s audio; you send audio back.
  1. Point the number at your server: PATCH /v1/calling/settings with {"answered_by": "stream", "stream": {"url": "wss://agent.example.com/flowiq", "format": "pcm16_16k", "headers": {"Authorization": "Bearer …"}}}. Formats: pcm16_16k (default), pcm16_8k, pcm16_24k, mulaw_8k.
  2. When a customer calls, FlowIQ connects to your URL (with your headers, plus X-Flowiq-Call-Id and X-Flowiq-Organization-Id), answers the call, and streams.
  3. The socket speaks JSON, shaped like Twilio Media Streams, so a voice agent written for Twilio works with little change (with mulaw_8k, usually unchanged):
Calls streamed this way show answered_by: "stream" in the call history. The call ends when the caller hangs up (you receive stop), when you send hangup or close the socket, or after 60 minutes.
Audio over the stream is uncompressed PCM (or µ-law): about 32 KB/s per direction at 16 kHz. One socket per call.

Call a customer

WhatsApp only lets you call people who have given you permission.
  1. Check: Get Call Permission tells you whether you may call now (can_start_call) and how many requests and calls you have left.
  2. Ask: within 24 hours of the customer writing to you, Request Call Permission sends them an Allow calls button. Outside that window, send an approved template that has a call permission request with Send Template. Their answer arrives on your webhook as kind: "call_permission".
  3. Call: Start Call with your SDP offer. WhatsApp rings the customer; when they answer, your webhook gets call.event: "connect" with their SDP answer in call.session, and kind: "call_status" events track ringing, accepted and rejected.

Or use SIP

Voice platforms that speak SIP (most voice-agent and contact-centre products do) can take the calls without any WebRTC code: set calling.sip with Update Calling Settings and WhatsApp sends every call straight to your SIP server.
With SIP on, WhatsApp sends calls only to your SIP server. FlowIQ then receives no call events at all: no call webhooks, nothing in the FlowIQ inbox, no FlowIQ voice AI, and the call endpoints above stop working for that number. Turn SIP off to go back.

The call object

Call ids contain characters such as = and /: URL-encode them when they go in a path (encodeURIComponent). Calls that never got an end event from WhatsApp (a lost webhook) are closed by FlowIQ: missed after 3 minutes ringing, completed after 35 minutes in progress, with end_reason: "no_end_event".