Blue Reacher
Calling and AI agents8 / 55

Calling and AI agents

What FaceTime calling from the API does, what it never does, and how to wire a reply-YES call flow with a person on the line or an AI voice agent on your own telephony.

The short version

The Calls API places FaceTime audio calls from your iMessage line, and a person always starts them. Your code prepares the call. Someone signed in to Blue Reacher opens the confirmation link and presses Start call. Nothing dials before that.

No route, request field or MCP tool dials on its own, and no route streams call audio to your server. That is by design and it is not on the roadmap to change.

You canYou cannot
Prepare a call from code or an AI agent and hand the link to a personDial without a person pressing Start call
Follow the whole call lifecycle on webhooksStream or bridge live call audio to your server (no SIP, WebSocket or WebRTC leg)
Get the transcript, a summary and the recording link after the callAnswer an incoming call from the API
Hand an answered call to a teammatePut an AI voice agent on a FaceTime call
Cancel a prepared call or end a live oneQueue a second call on a line while one is waiting

Live keys need Calling switched on for the workspace, which your account manager does, and a key with calls:write. Test keys (brk_test_) get simulated calls on every calling route.

How a call runs, end to end

  1. Your code calls POST /v1/calls with the lead's number. The answer carries a confirmation_url that is valid for five minutes.
  2. You put that link in front of a person: a Slack message, a CRM task, a push notification.
  3. The person opens it, signs in to Blue Reacher if they are not already, checks the line and the masked destination, and presses Start call.
  4. The call runs as FaceTime audio from your line, in the Blue Reacher app in their browser.
  5. call.ringing, call.answered, call.completed, call.missed and call.failed arrive on your webhook, each carrying your client_reference.
  6. With recording and transcripts switched on, call.transcribed delivers the transcript, a summary and the recording link about a minute after the call ends.

If nobody presses Start call within five minutes, the call becomes expired, call.expired fires, and the line is free again.

The reply-YES pattern

The flow most teams want: a lead replies YES to "want a quick call?", and a rep calls them inside a minute, from the same number the lead has been texting.

  1. Your inbound webhook sees the YES reply.
  2. Your backend prepares the call, using the inbound message id as the Idempotency-Key so a retried webhook never prepares twice.
  3. It posts the confirmation_url to your team's Slack channel with the lead's name.
  4. The first rep to tap it places the call.
  5. call.answered or call.missed updates your CRM. call.transcribed adds the notes.
  6. On call.expired, text the lead a booking link instead, or prepare the call again.
// Inbound webhook handler: the lead replied YES
const res = await fetch("https://api.bluereacher.com/v1/calls", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.BLUEREACHER_KEY}`,
    "Content-Type": "application/json",
    "Idempotency-Key": inbound.message_id,
  },
  body: JSON.stringify({
    to: inbound.from,
    contact_name: lead.name,
    client_reference: lead.crm_id,
  }),
});
const call = await res.json();

if (res.ok) {
  await fetch(process.env.SLACK_WEBHOOK_URL, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ text: `${lead.name} said YES. Call now: ${call.confirmation_url}` }),
  });
} else if (call.error_code === "line_busy") {
  // Another call is waiting on this line. Retry after it starts or expires,
  // or prepare on a second calling line.
}

One prepared call holds its line until it is started, cancelled or expires, so a team taking many YES replies at once should run more than one calling line, or cancel calls nobody picked up.

AI voice agents

A FaceTime call has no audio interface for software, so an AI voice agent cannot place or speak on one through Blue Reacher.

When you want an AI agent to make the call, run it on your own telephony provider, any SIP or programmable voice platform your agent already supports, and show your Blue Reacher number as the caller ID. The lead sees the same number they have been texting with. Ask your account manager to verify the number as caller ID with your provider. That call is a regular phone call, not FaceTime.

Two rules for AI calls:

  • Call only people who asked for the call. In the US, the FCC treats an AI-generated voice as an artificial voice under the TCPA, so the call needs the person's prior express consent, and prior express written consent when it is telemarketing. A YES reply to a message that says an AI assistant will call is a clean consent record.
  • Keep the calling pattern conversational: one call to each person who asked, not a list dialed top to bottom.

None of this is legal advice; run your program past counsel before scaling it.

Behaviour you can rely on

Checked against the live API on 5 October 2026.

BehaviourDetail
Confirmation windowFive minutes from created_at, then expired. An unconfirmed call never rings
One waiting call per lineA second prepare on the same line answers 409 line_busy until the first is started, cancelled or expires. Cancelling frees the line at once
Strict request bodyAny field outside to, line_id, contact_name and client_reference is refused with 400 invalid_request, naming the field
IdempotencySame Idempotency-Key and body returns the original call. Same key, different body answers 409 idempotency_conflict
Default lineline_id can be left out when the key has a default line
Cancel and endDELETE /v1/calls is safe to repeat and returns the call as it stands
TransferOnly on an answered, live call; otherwise 409 call_not_answered
Rate limitPOST /v1/calls and POST /v1/calls/transfer share 10 a minute per key, and refused requests count toward it
MCPlist_calling_lines, prepare_call, get_call_status and end_call behave exactly like the REST routes. No MCP tool dials

Errors

Statuserror_codeWhen
400invalid_destinationto is missing or not E.164
400invalid_requestA field the route does not take, such as auto_start
400invalid_call_idcall_id is not a UUID
400call_id_requiredGET /v1/calls without call_id or direction=inbound
404line_not_foundline_id is not a calling line in this workspace
404call_not_foundNo call with that id for this key
409line_busyA prepared call is already waiting on this line
409idempotency_conflictThe Idempotency-Key was used with a different body
409call_not_answeredTransfer on a call that is not live
429rate_limitedOver 10 prepares and transfers a minute

The full list for every route is on Errors.

On this page