2026-10-05
- Numbers and IVRs are in the public API. See
IVRs and numbers.
- Numbers:
GET /dids,GET /dids/{id}(new),POST /dids,PATCH /dids/{id},DELETE /dids/{id}. - IVRs:
GET /ivr-flows,POST /ivr-flows,GET /ivr-flows/{id}(the definition),PATCH /ivr-flows/{id},DELETE /ivr-flows/{id},POST /ivr-flows/{id}/publish.
- Numbers:
- The IVR designer in a popup.
POST /ivr-flows/{id}/designer-sessionanswers a one-time URL that opens FireTone’s designer on one IVR, with no FireTone sign-in. The designer postsivr.saved,ivr.publishedandivr.closedto the page that opened it. POST /calls/ivrrings a number and runs an IVR’s published revision for whoever answers. It answers202likePOST /calls/ai, supports?dry_run=true, and shares the limit on calls placed (60 a minute per key).- A call request gains
flow_id, andkindcan beivr_call. - A new API key preset, IVRs & numbers: numbers and IVRs, placing calls, and the lists a number or a step points at.
2026-09-30
-
A module that is off has no API. The operations of an optional module
(AI agent, Outbound, Tickets) now answer the same way everywhere:
403 module_disabledwhile the module is switched off or outside the licence;404on a server built without it.
POST /calls/aiandGET /virtual-agent-profiles, which went on answering before; without the module in the build they answer404 module_not_installed. -
Each server’s API description lists only what it serves.
/api/v1/openapi.jsonand/api/v1/openapi-public.jsonleave out the operations of modules the server does not run. Every such operation carriesx-modulenaming its module, and the reference here says which module it needs. A client generated from your server’s own description has no methods that can only fail. -
A call record gains
client_trunk_id: the client trunk (a client’s own PBX) that sent the call. It is absent on every other call.GET /cdrsalso gains it as a filter. -
GET /calls/activegains paging and filters:limit,offset,sort,order,q, and the filtersstate(RINGING,ACTIVE, …),directionandorganisation_id. Withoutlimitit still answers every call, as before. -
GET /conference-rooms/{id}/sessionsgainssince(sessions started at or after an instant) andlive(only sessions still running), withsort,orderandq.
2026-09-25
- Notes to the phone.
POST /calls/{uuid}/infosends a note to the phone(s) on a live call as SIP INFO;POST /extensions/{id}/messagesends one to a person’s device as SIP MESSAGE, with or without a call. The note is the FireTone app’s own format:application/json,title,body,level(info|warning|alert),ack, and every other field a row.GET /calls/{uuid}/infosandGET /extensions/{id}/messagesread back what was sent and when the person acknowledged it. Two webhook events,call.info.sentandcall.info.acked. Organisations gaincall_info_urlandcall_info_secret: a URL asked on every answered call what the phone should show. Conference rooms tell every phone in them who joined or left. Every listing carries a receipt per phone told (recipients, with each person’sacked_at) and keeps a send that reached nobody asstatus: failedwith its reason. See Messages to the phone.
How the API changes
- The public API is
/api/v1. Operations in the public document don’t change incompatibly withinv1. New fields, new events and new optional parameters can appear at any time, so ignore what you don’t recognise. - An incompatible change means a new version. The old one keeps working for at least six months after the new one is announced here.
- Endpoints outside the public document are the panel’s own interface and can change without notice.
2026-09-24: which switch carried a call
- A call record gains
fs_node_id: the switch node that carried the call. The column has existed since the call record did and was never written, which with one node was obvious and with two is the first question about any call. Absent on every call recorded before today, and on a call the control plane could not attribute to a node. OnGET /cdrs,GET /cdrs/{uuid}and the export. GET /cdrsgainsnode_idas a filter: only the calls one switch carried.
2026-09-23: conference rooms, and who spoke
- Conference rooms join the public API. Creating and editing rooms, their default members and PIN exemptions, dialling somebody in, a room’s sessions and recordings, and running a room while it is up — mute, kick, lock, record, end — are all in the public document now and change only as versioned changes. They were served and documented before this; what changes today is the commitment. See Conference rooms.
GET /conferences,GET /conferences/{room}andGET /conferences/by-call/{uuid}describe their answers. The document said204with no body for all three, copied from the controls beside them. They are reads and always returned a body: the room, its members and whether you may control it. A client generated before today has a void return type for them and should be regenerated.- A transcript turn gains
speaker: who said it, when several people could have. It carries a name on a conference session a virtual agent sat in, and is empty on an ordinary call, where the caller is the caller. OnGET /conversations/{id}andGET /cdrs/{uuid}/conversation. - Extensions gain
codec_string: the codecs that extension offers, in order, chosen one by one. Empty means its codec profile decides. GET /extensions/{id}— the single read beside the list.- A new webhook event,
conference.minutes: a virtual agent that sat in a room wrote the session’s minutes. It carries the session, the room, who was there, the minutes themselves and where they were sent. One per session in which minutes were written.
2026-09-20: capacity refusals, and a call’s currency
503 node_busyonPOST /callsandPOST /calls/ai, withRetry-After: 30: the call was not placed because the node has no room right now — it is at its channel limit, the machine is loaded, or every AI session it allows is in use. Nothing rang and nothing was billed; send the same request again. This is deliberately not422, which still means the request itself is wrong.- Call records gain
currency: the ISO 4217 code thatsell_amount,cost_amountandmarginare in. It is absent on calls recorded before this date — the field existed and was never filled. - With
margin:read, call records also gaincost_currency,cost_amount_original,fx_rateandcost_unconverted: what the carrier charged in its own currency, the exchange rate applied, and whether a rate was missing. Whencost_unconvertedistrue,marginis not a margin — it is one currency subtracted from another — and must not be shown as money.
2026-09-15: the public API
- Integration keys:
- owned by the organisation, with presets;
- a compulsory IP allowlist;
- per-key rate limits;
Idempotency-Key.
- Calls:
- click-to-call by
from(extension, agent or login email); POST /calls/aifor an AI agent to call someone;referenceand signedcallback_urlon every call;?dry_run=true;GET /calls/{uuid}and/call-requests/{id}.
- click-to-call by
- Campaigns:
- contacts loaded with your references and variables;
- start, pause, resume and stop;
- per-contact results to
result_callback_url, withGET /campaigns/{id}/results.
- Contacts and data:
GET /contacts/lookup;PUT /contacts/by-reference/{ref};GET /cdrs/export.
- Webhooks:
- durable delivery, retried for about 15 hours and switched off after three days of failures;
- redelivery;
- new events:
call.missed,voicemail.received,recording.ready,conversation.completed,callback.requested,ticket.created,ticket.updated,contact.created,campaign.contact.completed,campaign.completed,csat.submitted.
- The Developer section in the panel: console, callback inbox, request log and test numbers.