> ## Documentation Index
> Fetch the complete documentation index at: https://docs.firetone.com.au/llms.txt
> Use this file to discover all available pages before exploring further.

# Messages to the phone

> Show a note on the phone: about this call (SIP INFO), or to the person with or without a call (SIP MESSAGE). The FireTone app's own format, with an acknowledgement when you ask for one.

A phone can be shown a **note** — a title, a line under it, a coloured tag,
and any facts you like as rows — while a call is up or, for a person's own
device, at any time. The **FireTone app** and the **Desk softphone** render
notes; a desk phone that does not understand them shows nothing. The format is
the app's ([the contract](https://github.com/remotiq/firetone/blob/main/docs/sip-notes-for-freeswitch.md)
lives in the repository), and this page is how the platform sends and receives
it.

## Two ways to send

|               | `POST /calls/{uuid}/info`                              | `POST /extensions/{id}/message`                                           |
| ------------- | ------------------------------------------------------ | ------------------------------------------------------------------------- |
| Carried as    | **SIP INFO**, inside the call's dialog                 | **SIP MESSAGE**, to the user's registered device                          |
| Needs a call? | Yes, a live one                                        | No                                                                        |
| Use it for    | Things about *this call*; what a conference room sends | Things addressed to the *person*: assignments, alerts, also during a call |
| Shown         | On that call's screen, kept with the call              | Banner on the call screen if one is up; Recents → Messages always         |
| Permission    | `calls:control`                                        | `calls:control`                                                           |

If you are not sure which, send a MESSAGE. Both take the same body.

## The note

```bash theme={null}
curl -X POST "$API/calls/$CALL/info" -H "Authorization: Bearer $FIRETONE_KEY" \
  -H "Content-Type: application/json" \
  -d '{"title":"Gate 3 opened","body":"North side, badge 4471","level":"alert","ack":true,
       "zone":"North","camera":{"id":12,"url":"https://cams.example.com/12"}}'
```

Four fields mean something to the app:

| Field   | Meaning                                                                                                                                                    |
| ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `title` | The heading, in bold. Required, up to 200 characters.                                                                                                      |
| `body`  | One or two lines under the heading.                                                                                                                        |
| `level` | `info`, `warning` or `alert` — the tag's colour. `alert` also keeps the banner up until dismissed. `warn`, `critical` and `error` are accepted and mapped. |
| `ack`   | `true` shows an **Acknowledge** button. (`ask` is accepted as the same thing.)                                                                             |

**Every other field is shown to the person as a name/value row**, in the order
sent: use short, readable names (`zone`, `ticket`, `priority`), not internal
codes. Nested objects and arrays fold and open on tap. Keep the whole note
under 4 KB — it is read on a phone and a watch; send a URL for more. Never put
a secret in one: notes are stored on the phone and shown in full.

Answers `202 {id, channel, legs?, ack}`. `id` is the platform's, and the
acknowledgement names it. A call with no phone on it (carrier to carrier,
parked) is `409`; an extension with no registered device is `409` too.

### What the phone receives

```
INFO sip:1001@acme.firet.one SIP/2.0     (or MESSAGE, From: sip:events@acme.firet.one)
Content-Type: application/json

{"id":"6f1c…","title":"Gate 3 opened","body":"North side, badge 4471","level":"alert","ack":true,
 "camera":{"id":12,"url":"https://cams.example.com/12"},"zone":"North"}
```

## From your own system, on answer

Set the organisation's **Call-info URL** (and a signing secret) in
Organisations → the tenant → *Your systems, during a call*, or `PATCH
/organisations/{id}` with `call_info_url` and `call_info_secret`. On every
answered call the platform POSTs the call's facts:

```json theme={null}
{"call_uuid":"…","direction":"inbound","caller":"+61400000000","destination":"+61280000000",
 "organisation_id":"…","extension_id":"…","agent_id":"…","team_id":"…","answered_at":"2026-09-25T04:12:09Z"}
```

with `X-FireTone-Signature: sha256=<HMAC-SHA256 of the body, keyed with the
secret>`. Answer with a **note** — the same object as above — within five
seconds and it is sent to the phone as INFO; answer `204` or an empty body to
show nothing. The URL must be `https` on a public address, as every tenant URL
is.

## From a conference room

Every phone in a room is told when someone joins or leaves, and a phone that
joins is told who is already there — as INFO on its leg, nothing to configure:

```json theme={null}
{"id":"…","title":"Kim joined · 4 in the room","level":"info","event":"member-join","member":"911012","name":"Kim","count":4}
{"id":"…","title":"4 in the room","level":"info","event":"roster","count":4,"members":[{"member":"911010","name":"Dana","role":"moderator"}, …]}
```

## The acknowledgement

A note with `ack: true` shows **Acknowledge**. When the person taps it, the
phone replies **once, the way the note came** — INFO on the same dialog, or
MESSAGE to `events@<your SIP domain>` — with:

```
Content-Type: application/json

{"ack":true,"id":"6f1c…","title":"Gate 3 opened","at":"2026-09-25T01:42:17.512Z"}
```

The platform marks the note acknowledged at `at` and your webhook receives
`call.info.acked`. **It is the person's act**: acknowledged means somebody
tapped, not that the phone received the note. A reply to an INFO note works
only while that call is up; the app tells the user when it could not be sent.

## Reading back

`GET /calls/{uuid}/infos` and `GET /extensions/{id}/messages` (`calls:read`)
list what was sent, newest first, with `acked_at` where the person
acknowledged. Kept 30 days.

## Events

| Event             | Payload                                                                                                                                                            |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `call.info.sent`  | `id`, `channel` (`info` \| `message`), `title`, `level`, `ack`, `source` (`api`, `url`, `conference`); `call_uuid` and `legs` for INFO, `extension_id` for MESSAGE |
| `call.info.acked` | `id`, `title`, `leg` (the call leg, or the replying address), `acked_at` (the person's tap), `call_uuid` when there was one                                        |

## Things to avoid

The app's own list: don't send the same note twice with different ids; don't
send a note every second (each is a banner and a kept entry); don't put
secrets in notes; don't send `text/html`; don't rely on the app being in the
foreground for a MESSAGE — for anything urgent, use a call or a push.
