Authorization: Bearer $FIRETONE_KEY. Creating and
editing rooms needs conferences:write; running a live room needs
conferences:control; reading needs conferences:read.
Create a room
numberis 2 to 8 digits: what an extension dials, and what a caller keys when a shared “Conference” phone number asks which room. Unique within the organisation; an extension with the same digits wins.participant_pinis 4 to 10 digits, or empty for a room anyone may dial straight into.moderator_pinis optional and must differ; empty means the room has no moderator role. The PINs are returned on every read: they are invitation codes, not credentials.wait_for_moderatorholds participants on music until a moderator joins, and needs a moderator PIN.max_members0means no cap.
PUT /conference-rooms/{id}/members with the same shape
replaces the extensions rung when the room opens. A busy or unregistered
member is rung as soon as it is free while the room is up; a session’s history
(GET /conference-rooms/{id}/sessions) carries each invites row with its
state and last_reason. minutes_email on the room is where a virtual
member’s minutes are sent.
Minutes. GET /conference-rooms/{id}/sessions/{sid}/meeting (AI module;
conferences:read) is what a virtual member made of one session: minutes
(or minutes_error, why none were written), the notes it took as things
were decided, turns with each caller line’s speaker, replies_unheard
(replies the model produced that nobody had asked for, held back), and
delivered_to (the addresses the minutes were queued to). Per SESSION, not
per room: a room used three times a day has three sets of minutes. 404 when
no virtual agent sat in that session. GET /conference-rooms/{id}/meetings
is the same for every session of the room at once, one summary row per seat
(session_id, agent, state, has_minutes, minutes_error, notes,
turns), which is what the room’s page reads. The same minutes arrive as the
conference.minutes webhook event.
Extensions that need no PIN. PUT /conference-rooms/{id}/exemptions with
{"items": [{"extension_id": "…", "role": "moderator"}]} replaces the set of
the organisation’s extensions that dial the room number and are seated without
keying anything, each in its role. The room returns them as exemptions. Only
a leg the directory authenticated carries an extension, so an outside caller
can never be exempt.
GET /conference-rooms, GET /conference-rooms/{id}, PATCH and DELETE
follow the usual conventions. A room’s row carries numbers, the phone numbers
pointed at it alone, and live_members, how many are in it right now. Deleting
a room a number still points at answers 409 naming them.
To let outside callers in, point a phone number at destination
conference: with destination_id set to a room the caller is asked only for
the PIN; with none, for the room number first.
Dial somebody in
role (participant or moderator) without keying a
PIN. For an outside number send "kind": "external" and target in E.164;
it is routed and billed as an outbound call, refused without credit, and sees
the organisation’s first phone number as caller ID.
The response is 202 with {"dialling": "…"}: the call is ringing. Whether
it was answered shows in the room’s live list.
The room while it is up
Live rooms are keyed by the switch’s room name:ft-room-<room id> for a
dial-in room, ft-conf-<call uuid> for two calls merged from the Desk. That
is what lets a merged call be run with the same requests.
id is the switch’s member id, and it is what the member controls take.
can_control says whether the caller of this request may use them. 404
means nobody is in that room right now.
GET /conferences lists every room live in your scope, and
GET /conferences/by-call/{uuid} names the room a call is in, which is how the
Desk knows to show a merged call’s participants.
Inside a room the keypad also works: *1 mute yourself, *2 unmute; a
moderator has *5 lock, *7 mute everyone else, *0 end.
History and recordings
GET /conference-rooms/{id}/sessions lists every occupancy of the room,
newest first: when it ran, peak_members, who was in it with their roles and
times, the default members’ invites and how each went (above), and
has_recording with recording_bytes. A recording is played from
GET /conference-rooms/{id}/sessions/{sid}/recording/audio (recordings:listen),
a WAV with Range support, and is kept under the organisation’s recording
retention like any call recording.
Events
The live stream (see Events) carriesconference.updated with
room and an action (joined, left, locked, recording, all_muted,
ended, and the switch’s mute and talking changes), and call.conferenced
when calls are merged from the Desk. Treat them as a nudge to re-read
GET /conferences/{room}; the read is the truth.