For developers
Follow a call, steer it and get the result
Once you've placed a call, use its ID (cal_…) to see how it's going, give the AI new instructions while it's on, hang up, and read the outcome, answers, summary and transcript.
How to check a call's status
curl https://voice.binaryelements.com/v1/calls/cal_7h2kq9m4x8pz3vd61wtn \
-H "Authorization: Bearer $BE_VOICE_KEY"
The reply is the call, as returned when you placed it, with status, answered_at, ended_at and duration_sec filled in as it goes. Once it has ended, hangup_cause says how the line was cleared.
| Status | Means |
|---|---|
queued | The phone is ringing. |
in-progress | Answered: the conversation is on (or the person is being put through to someone). |
completed | Answered and finished. |
no-answer | Nobody answered within the ring time. |
busy | The line was busy. |
failed | The call couldn't be connected. |
canceled | You hung up before it was answered. |
To list recent calls, use GET /v1/tenants/{account_id}/calls?limit=50 (1 to 200, newest first). The list is under data.
How to steer a live call
While the AI is talking with the person, you can give it a new instruction: something you've just learned, a change of plan, an extra question.
curl https://voice.binaryelements.com/v1/calls/cal_7h2kq9m4x8pz3vd61wtn/steer \
-H "Authorization: Bearer $BE_VOICE_KEY" \
-d '{"instruction": "The 8-12 Friday slot has just been taken. Offer 12-5 or Monday morning instead."}'
HTTP/1.1 202 Accepted
{"status": "instruction passed to the agent"}
- Plain words. Send one
instruction, 1 to 2,000 characters, written as you'd say it to a colleague on the call. - The person doesn't hear it. The AI gets it as a note from your business.
- At a natural moment. If nobody is talking, the AI acts on it at once. Otherwise it goes with the AI's next reply, never mid-sentence.
- In the transcript. It appears as a line with
"speaker": "instruction", so you can see when it was given. - Any AI conversation. Steering works on any call your AI agent is on, not only calls your app placed.
| Reply | Why |
|---|---|
409 not_live | There's no conversation to steer right now: the phone is still ringing, the person is being put through to someone, or the call has ended. |
422 steer_busy | Eight instructions are already waiting to be used. Try again in a moment. |
422 invalid_instruction | The instruction is empty or longer than 2,000 characters. |
How to hang up
curl -X POST https://voice.binaryelements.com/v1/calls/cal_7h2kq9m4x8pz3vd61wtn/hangup \
-H "Authorization: Bearer $BE_VOICE_KEY"
The reply is 202 with {"status": "hangup requested"}, and the line is cleared straight away, mid-sentence if need be. A call that is still ringing ends as canceled. A call that has already ended answers 409 call_ended. To have the AI wrap up politely instead, steer it: "Thank them and end the call now."
How to get the result
curl "https://voice.binaryelements.com/v1/calls/cal_7h2kq9m4x8pz3vd61wtn/result?wait=60" \
-H "Authorization: Bearer $BE_VOICE_KEY"
{
"call_id": "cal_7h2kq9m4x8pz3vd61wtn",
"status": "completed",
"final": true,
"from": "+61370000000",
"to": "+61400000000",
"answered_at": "2026-10-10T05:12:11.204Z",
"ended_at": "2026-10-10T05:13:25.872Z",
"duration_sec": 74,
"outcome": "completed",
"result": {
"outcome": "completed",
"answers": {"window": "Friday 12-5", "gate_code": "Side gate, code 4411"},
"skipped": {"other_day": "not needed: Friday works"},
"note": "Sam asked the driver to ring on arrival."
},
"summary": "Sam confirmed delivery of the hot water unit on Friday between 12 and 5. Side gate code 4411; ring on arrival.",
"transcript": [
{"speaker": "caller", "text": "Hello?"},
{"speaker": "agent", "text": "Hi, it is Alex from Harbour Plumbing, about your hot water delivery."},
{"speaker": "instruction", "text": "The 8-12 Friday slot has just been taken. Offer 12-5 or Monday morning instead."},
{"speaker": "agent", "text": "Would Friday between 12 and 5 suit you?"}
],
"metadata": {"order": "A1002", "job": "job_48213"}
}
What's in the result
finaltrueonce nothing more will change: the call has ended and its summary is written, usually a few seconds after hang-up. While it'sfalse, the transcript is the conversation so far.outcome- How it ended. The AI's outcome (
achieved,not_achieved,completed,partial, or one of your own). If the AI didn't name one, how the conversation ended:caller_hangup,timeout(the longest call was reached) ortransfer. If nobody answered, the call's status:no-answer,busy,failedorcanceled. Empty while the call is on. result.answers- Each question's answer under its key, checked against its type. Dates are YYYY-MM-DD; a choice is one of your choices.
result.skipped- Questions the person wouldn't or couldn't answer, with why.
result.details- The fields of your own outcome, if it lists any.
result.note- Anything else the AI thinks you should know, including why a goal wasn't met.
result.callback- If the person asked to be called another time:
at(a time with its offset) andwhenas they said it. result.opt_outtrueif they asked not to be called again. Their number is now on your do-not-call list.summary- Two or three sentences on the call, written after it ends (shaped by
summary_instructions). transcript- Every line, with
speakercaller(the person rung),agent(the AI) orinstruction(your steering). metadata- Your own references from when you placed the call.
result is null when the AI didn't end with an outcome, for example when nobody answered or the person hung up first.
Waiting for the result
Pick whichever suits your app:
- Webhook (best). Give a
callback_urlwhen you place the call. The final result arrives there as a signedcall.resultevent, once. See Webhooks. - Long-poll.
GET …/result?wait=120holds the request until the result is final or the wait (0 to 120 seconds) runs out, then answers with what's known. Iffinalis stillfalse, ask again. Set your HTTP client's timeout a little longer thanwait. - Live view.
GET …/resultwithoutwaitanswers at once with the transcript so far: handy for showing the conversation as it happens, every second or two.
