sidetone

Usage

Voicemail, menus and hours

Voicemail is on for everyone from the start. Menus are data: a prompt and where each key leads. Business hours are an extension that leads somewhere else depending on the time.

Voicemail

When nobody answers, the caller gets a beep and can leave a message, up to voicemail_max_seconds long. The user's phones show a waiting message, and dialling *97 from their own phone plays the messages, new ones first: 7 deletes, # skips. "voicemail": false on a user turns it off. Users also see their messages on their own console page, and so does an administrator under Voicemail.

A mailbox holds at most 100 messages; when it is full the caller hears the error tone and no message is taken, so an outside caller cannot fill the disk. Over the API: GET /v1/voicemail, GET /v1/voicemail/{id}/audio (a WAV file), PATCH with {"heard":true}, DELETE.

By email

Give users an email and the server a way to send (Settings → Email: smtp_host, smtp_from, and usually smtp_username and smtp_password; port 587 with STARTTLS unless you say otherwise): every new message is announced to its mailbox's owner, with the recording attached as a WAV file (voicemail_email_attach). With starttls, nothing is sent if the mail server does not offer it. The Send a test button, or POST /v1/settings/test-email with {"to":"…"}, sends one now and answers with what the mail server said. The password is write-only. Delivery is best effort with a few retries; the message itself is safe in the mailbox either way.

With a transcription server set up, the email carries what the caller said as text as well.

By webhook

voicemail_webhook_url gets a JSON POST for every new message: the mailbox, the caller, the length, the call's id, and audio, a path to fetch the recording from with a token. cdr_webhook_url does the same for every finished call.

Sounds

There is no recorded speech in the binary. Greetings, menu prompts, hold music and the recording notice are yours to upload, as 8 kHz mono WAV:

$ sox welcome.mp3 -r 8000 -c 1 -b 16 welcome.wav
$ curl -H "Authorization: Bearer $TOKEN" -H 'Content-Type: audio/wav' --data-binary @welcome.wav -X PUT localhost:8080/v1/audio/welcome

Use the name as a user's greeting, a menu's prompt, a queue's music, or music_on_hold_audio. The console's Sounds page uploads and plays them, and with a speech server set up, From text… makes one from a sentence you type.

Menus

$ api -d '{"name":"main","extension":"700","prompt":"welcome","options":{"1":"1001","2":"600"},"fallback":"1001"}' localhost:8080/v1/ivr-menus

A menu plays its prompt and waits for a key. Keys lead to users, ring groups, queues or other menus, never to outside numbers, so a menu cannot be used to dial out. A caller who presses nothing, or a key with nothing behind it, goes to fallback. Point an inbound number at the menu's extension and outside callers get it; a user can dial it too.

Business hours

A schedule is an extension that leads to one place when you are open and another when you are closed. Point an inbound number at it:

$ api -d '{"name":"office","extension":"900","timezone":"Europe/London","open":"700","closed":"1001",
         "hours":[{"days":["mon","tue","wed","thu","fri"],"from":"09:00","to":"17:30"}],"holidays":["2026-12-25","01-01"]}' localhost:8080/v1/schedules
$ api -d '{"number":"+441234567890","destination":"900"}' localhost:8080/v1/dids
  • Hours and holidays are meant in the schedule's own timezone, daylight saving included, whatever clock the server runs on. Hours may run past midnight.
  • closed is typically a user with voicemail, or a menu whose prompt says when you are open. Left empty, callers are turned away.
  • Closing early today: Right now on the schedule's page, or "override":"closed", and clear it tomorrow. open_now in the answer says what callers get at this moment.

In the console, hours are a row for each day with time pickers, and holidays are picked from a calendar.

Holidays

Holiday sets keep public holidays in one place for every schedule (Holidays): a set is a list of days, each a date or, for days that never move, a month-day; a schedule observes one or several (holiday_set_ids). Change the set and every schedule that observes it follows at once.

Public holidays need not be typed. The server knows the rules for some hundred countries and regions: Holidays → a set → Import public holidays… asks for the country and the year, or five years at once, and fills the set in, substitute days included. GET /v1/holiday-calendars lists what it knows, and GET /v1/holiday-calendars/gb?year=2027 gives one year's days. They are worked out by rule inside the server, nothing is downloaded, so a day decreed for one year only is known only up to your version: look the list over. Dated days run out; the Holidays page warns four months ahead.