Overview
A voice call is asynchronous. You dispatch it, it runs for a minute or two without you, and then there is an outcome to collect. This page is the shortest complete path through that lifecycle: place a call, learn how it ended, read what was said. Authentication is a separate story. If your agent already has an API key, you are ready. If it does not have one and there is no human around to paste one in, see Connect your AI agent first.Send your key as
Authorization: Bearer YOUR_API_KEY. A bare Authorization: YOUR_API_KEY with no prefix is also accepted. x-api-key is not read and does not authenticate.Prerequisites
- A Bland API key, exported as
BLAND_API_KEY. - A phone number to call, in E.164 format (
+15551234567). - Optionally, a URL Bland can reach, if you want the outcome pushed to you instead of polling for it.
The lifecycle
1
Place the call
POST /v1/calls dispatches the call and returns immediately with a call_id. It does not wait for the call to finish.Response
max_duration (in minutes) bounds how long you can be waiting. Set it deliberately: it is the upper bound on your own wait loop.2
Learn how it ended
Two ways, and you should pick one on purpose rather than defaulting to the second.Push. Add a Poll on a fixed interval (5 seconds is plenty) and stop when
webhook to the request body. When the call ends, Bland POSTs the full call object to that URL, transcript included. Nothing to poll.webhook alone gives you the post-call payload. webhook_events is optional on top of it, and streams progress during the call (call covers connected, transferred, and ended). See Post call webhooks for the payload shape and Webhook signing for verifying it is really us.Poll. If you have no URL Bland can reach, GET /v1/calls/{call_id} returns the current state of the call.completed is true. Do not tighten the loop hoping to finish sooner: the call takes as long as the call takes.The fields that tell you what happened:3
Read the transcript
Same endpoint, once
completed is true. If you took the push path, this payload already arrived at your webhook and you can skip the request entirely.concatenated_transcriptis the whole conversation as one string. Use it when you are going to feed the call to a model.transcriptsis the same content as an array of turns, each withtext,user(user,assistant,robot, oragent-action), andcreated_at. Use it when you need turn boundaries or timing.summaryis a short model-written recap generated when the call ends.recording_urlis present only if you passedrecord: true.
completed flips may still be filling in.Push or poll?
Poll
You are a hosted agent with no inbound URL: a chat assistant, a sandboxed runtime, a laptop behind NAT. There is nowhere for Bland to deliver to, so
GET /v1/calls/{call_id} on an interval is the right answer, not a workaround.Subscribe
You have any reachable URL: a server, a serverless function, a tunnel. Set
webhook and stop polling. You get the outcome the moment it exists instead of one poll interval later, and the payload already contains the transcript.webhook at the URL the forwarder prints, and your local handler receives the real post-call payload.
Next steps
Call recipes for agents
Voicemail, proper nouns, and escalating to a human.
Connect your AI agent
How a bot gets its own API key and phone number.
Send Call API reference
Every parameter
POST /v1/calls accepts.Bland MCP Server
The same operations as MCP tools, with nothing to install.
Docs for agents: llms.txt