Live calls

Watch calls while they are in progress: who is ringing, who is connected, and where each call has got to in its routing plan.

After this page you can watch traffic arrive in real time, tell a call that is being placed from a call that is talking, and read capacity off the board when a buyer is being skipped. Live calls shows every call in the workspace that has not ended yet.

It is the screen to have open when a campaign goes live, when a buyer says their phones are quiet, and in the ten minutes after you change a routing plan. It is on Live calls in the console, and on GET /api/v1/calls/live.

What is on the board

Three tiles, then a row per call. The tiles are On the phone (routing, ringing or talking), Talking to a buyer (a buyer's leg has answered) and Still being placed (choosing a target, or ringing one) — the first is the sum of the other two.

StatusThe row saysMeaning
routingWorking through the routing plan — nobody has been dialled yet.The gates have passed and the plan is being resolved. Usually under a second.
reservedHolding a line at BlueSky Legal — Intake before dialling.A slot has been taken at the target so nobody else can use it while we ring.
ringingRinging BlueSky Legal — Intake — attempt 1.A target's line is ringing. attemptNo says which attempt this is.
waitingHolding — no buyer was free when the call arrived.The caller is on the line with nobody available yet.
in_progressTalking to a buyer.Connected. The timer is talk time, which is what the duration threshold is measured against.

Each row carries the elapsed timer, the caller and the tracking number they dialled, the campaign and the publisher — or Your own media — and the target and buyer the call is with right now. The router rewrites those two on every dial, so they follow the call down the plan rather than showing where it started. Clicking a row opens the same waterfall a finished call has, filled in as far as the call has got.

Below the list, By campaign and By buyer group the same calls, which is the fastest way to see that one buyer is holding nine of your eleven live calls.

Caller numbers are hidden until you ask

A live board is the one screen that gets left open on a wall. The workspace owns these calls and may see every digit — but not by default, and not because somebody walked past. Numbers are masked to their last four until you turn Show caller numbers on, and the toggle is per person and per visit.

How fresh it is

RefreshEvery five seconds. The console re-polls; the answer is never cached, because a live board from ten seconds ago reads as current and is not.
The clockThe timers run in the browser, anchored to the instant the answer was cut. Without that, every timer on the board would jump five seconds at a time and read as frozen in between.
How far backCalls that started in the last six hours and have not ended. A row still ringing after that is a row the housekeeping missed, not a call.
How manyAt most 200, newest first. A board with more than two hundred live calls is a report, not a board.
What it ignoresWhatever the call log is filtered to. A call in progress on a campaign you have filtered out is still in progress.

Reading capacity from it

The board is the live picture of every concurrency cap you have set. A target's concurrency cap counts exactly the calls shown here as connected to it, so when a target is being skipped with concurrency, these are the calls holding its slots.

  • Group by buyer. If one buyer holds most of the board, the next caller will be skipped with concurrency or buyer_capped — see Reason codes.
  • A slot comes back the moment a call leaves the board. There is nothing to reset and nobody to tell.
  • A row stuck on ringing for thirty seconds is a target that answers slowly. Compare that with the campaign's ring time: if the ring time is shorter, you are paying for ring and failing over before they pick up.
  • Rows appearing and vanishing in a second are calls the gates refused. They will be in the call log as unrouted with the reason — the board is not where to diagnose those.

The same board, as an API

GET /api/v1/calls/live is the endpoint behind it, and it takes no filters at all — that is what keeps it cheap. It needs a key with calls:read.

One poll
curl -s "https://api.buy3.io/api/v1/calls/live" \
  -H "Authorization: Bearer $BUY3_API_KEY"
200 OK
{
  "live": [
    {
      "id": "0b9f6c1e-52a4-4a0e-9f0a-3d1c7e8b2a11",
      "ref": "CA-482137",
      "status": "in_progress",
      "startedAt": "2026-09-20T14:03:11.000Z",
      "answeredAt": "2026-09-20T14:03:19.000Z",
      "elapsedSeconds": 96,
      "talkSeconds": 88,
      "callerNumber": "+14155550142",
      "callerState": "CA",
      "dialedNumber": "+18885550100",
      "campaign": { "id": "6a2d1f0e-8b7c-4c55-a1d3-0e9f8a7b6c5d", "name": "Acme Health — Inbound" },
      "publisher": { "id": "c4e1a2b3-9d8f-4f6e-b5a4-1c2d3e4f5a6b", "name": "Northwind Media" },
      "target": { "id": "a9b8c7d6-e5f4-4a3b-9c2d-1e0f9a8b7c6d", "name": "Acme Health — Dallas floor" },
      "buyer": { "id": "f1e2d3c4-b5a6-4978-8a9b-0c1d2e3f4a5b", "name": "Acme Health" },
      "attemptNo": 2
    },
    {
      "id": "1c8e7d6f-4a3b-4c2d-9e1f-0a9b8c7d6e5f",
      "ref": "CA-482138",
      "status": "ringing",
      "startedAt": "2026-09-20T14:04:41.000Z",
      "answeredAt": null,
      "elapsedSeconds": 6,
      "talkSeconds": 0,
      "callerNumber": "+12025550188",
      "callerState": "DC",
      "dialedNumber": "+18885550100",
      "campaign": { "id": "6a2d1f0e-8b7c-4c55-a1d3-0e9f8a7b6c5d", "name": "Acme Health — Inbound" },
      "publisher": null,
      "target": { "id": "d4c3b2a1-9e8f-4d7c-b6a5-4f3e2d1c0b9a", "name": "BlueSky Legal — Intake" },
      "buyer": { "id": "b2a1f0e9-8d7c-4b6a-9584-3f2e1d0c9b8a", "name": "BlueSky Legal" },
      "attemptNo": 1
    }
  ],
  "count": 2,
  "connected": 1,
  "at": "2026-09-20T14:04:47.512Z"
}
FieldMeaning
count, connectedHow many calls are live, and how many have a buyer on the line.
atThe server's clock when the answer was cut. Anchor your own timers to it.
elapsedSecondsSince the call arrived.
talkSecondsSince the buyer answered. 0 on a call nobody has answered.
statusOne of routing, reserved, ringing, waiting, in_progress.
target, buyerWho it is ringing or talking to right now. Both null until a target is chosen.
publishernull for your own media.
attemptNoWhich attempt is ringing, counting from 1.
callerNumberIn E.164. null when the caller withheld it — mask it yourself if your board is on a wall.
The answer is sent Cache-Control: no-store. Do not put it behind a cache of your own.
// A board of your own. Poll, do not hammer: five seconds is what the
// console uses and is fast enough for a phone call.
const KEY = process.env.BUY3_API_KEY;

async function tick() {
  const res = await fetch("https://api.buy3.io/api/v1/calls/live", {
    headers: { Authorization: "Bearer " + KEY },
  });
  if (res.status === 429) return;                    // over the limit; skip this tick
  const body = await res.json();
  if (!res.ok) throw new Error(body.code + ": " + body.error);

  // `at` is the server's clock when the answer was cut. Anchor your timers to
  // it and count forward locally, or every figure jumps five seconds at a time.
  const cutAt = new Date(body.at).getTime();
  for (const call of body.live) {
    const elapsed = call.elapsedSeconds + Math.round((Date.now() - cutAt) / 1000);
    console.log(call.ref, call.status, elapsed + "s", call.target?.name ?? "—");
  }
}

setInterval(() => void tick(), 5000);

Worked example: the launch that went quiet

You set a campaign live at nine and by 09:20 the board is empty. Three questions, in this order:

  1. Is anything arriving at all? An empty board and an empty call log for the same window means no calls reached your numbers — a publisher problem, or a number pointing at the wrong campaign. Nothing on this page will help.
  2. Are rows appearing and vanishing? Then calls are arriving and the gates are refusing them. Open the log filtered to outcome=unrouted and read the reason code: an empty wallet, a campaign that is not live, hours set in the wrong time zone.
  3. Are rows sitting on ringing and then disappearing? Calls are arriving and nobody is answering. Open one and read its attempts and their SIP results480 on every target inside their own hours is a buyer who is not there.

Each answer sends you somewhere different, and the board's value is that it tells you which of the three you have inside a minute rather than after a morning of reports.

Next steps