BitVoice manual

An open-source phone system in one program, set up entirely in the web interface: extensions, queues, conference rooms, the staff portal, hosted organisations, and the public-safety lab track.
76 chapters · 63 figures · 39 thousand words · BioDream LLC

Contents

  1. Part 1. Getting started
    1. 1. Getting started
    2. 2. How mature each part is
    3. 3. Extensions
    4. 4. Connecting phones
    5. 5. Skinny phones and MGCP gateways
    6. 6. Telephony cards
    7. 7. Trunks
    8. 8. Call routing
    9. 9. PIN sets
    10. 10. Caller ID lookup
    11. 11. Emergency calls
    12. 12. Sites and office 911
    13. 13. Health
    14. 14. Settings
  2. Part 2. Where calls go
    1. 15. Call flow
    2. 16. Ring groups
    3. 17. Queues
    4. 18. Outbound dialer
    5. 19. Sounds: prompts, languages and hold music
    6. 20. Menus (auto attendant)
    7. 21. Dial-by-name directory
    8. 22. Dial-in (DISA)
    9. 23. Voice bots (AudioSocket)
    10. 24. Day/night toggles
    11. 25. Schedules
    12. 26. Scripts (JavaScript and Lua)
    13. 27. AI receptionist, voicemail triage and asking
    14. 28. Voicemail
    15. 29. Callbacks
    16. 30. Call links and website calling
  3. Part 3. Everyday calling
    1. 31. Feature codes, forwarding and speed dials
    2. 32. The staff portal
    3. 33. Conference rooms
    4. 34. Paging and overhead speakers
    5. 35. Hot desking
    6. 36. Hotel and wake-up calls
    7. 37. Contacts on every phone
    8. 38. Calendars and do not disturb
    9. 39. Mobile apps
    10. 40. Video calls
    11. 41. Fax: sending and receiving, fax machines and analogue phones
    12. 42. Inbox: web chat, WhatsApp and Messenger
    13. 43. Business texting (SMS)
    14. 44. Transfer briefings
  4. Part 4. Customers and insight
    1. 45. Live calls
    2. 46. Call history
    3. 47. Customer timeline
    4. 48. CRM: caller cards and call logging
    5. 49. Call insight for supervisors
    6. 50. Call recording and card payments
    7. 51. Recording consent
    8. 52. Call quality
    9. 53. Costs and budgets
    10. 54. Caller ID reputation and branded calls
    11. 55. Spam protection and STIR/SHAKEN
  5. Part 5. Running BitVoice
    1. 56. Administrators
    2. 57. Single sign-on
    3. 58. Security
    4. 59. Changes, backups and import
    5. 60. Updates
    6. 61. Several servers as one phone system
    7. 62. Where the data is kept (SQLite or PostgreSQL)
    8. 63. Hosting other organisations
    9. 64. Codecs and sound
    10. 65. Microsoft Teams (Direct Routing)
    11. 66. Import
    12. 67. Configuration as code
    13. 68. Asterisk compatibility (AMI and ARI)
    14. 69. Archive
    15. 70. Legal holds
    16. 71. Metrics: Prometheus, OpenTelemetry, Grafana, SNMP and call records
    17. 72. Call generator
    18. 73. SIP trace
  6. Part 6. Public safety: the lab track
    1. 74. 911 calls (the 911 profile)
    2. 75. Radio dispatch console
    3. 76. NG911 Core Services (ECRF, ESRP, LVF, BCF, LIS, logging)
Part 1

Getting started

From a new install to a working phone system: extensions, phones, a phone company, where calls go, emergency calling from your offices, and how to tell everything is ready.

Chapter 1

Getting started

In the web interface: /

BitVoice is a complete phone system in one program: the exchange that phones sign in to, the menus and queues callers move through, voicemail, recording, conference rooms, faxes, and the connections to phone companies. Everything is set up in the browser, on the screens this manual describes. There is no configuration file to edit and nothing else to install.

WHO CONNECTSWHERE CALLS GODesk phonesYealink, Poly, Grandstream, SnomBrowsers and appsWebRTC, iOS, AndroidPhone companiesSIP and IAX2 trunksESInet and radio911 calls, P25, RoIPBitVoiceRoutes and menusQueues and roomsRecords and logsConverts codecsKeeps 911 workingPeople who answerextensions, ring groupsVoicemail and AItranscripts, receptionistCAD, CRM, Teamsevents, caller cardsRecordshistory, recordings, faxes
Figure 1. Where BitVoice sits: phones and carriers on one side, people and systems on the other

What you need

The first start

Start BitVoice and open the address it prints (on a desktop it opens the browser itself). The web interface is HTTPS only, on this computer too. Until you install a certificate of your own (Settings, Certificate), BitVoice uses one it made itself, so the browser warns once: choose to continue to the site. The setup wizard asks four things: the organisation's name and country, the first administrator's password, the first extensions, and your phone company if you have one. The country sets the emergency numbers, the tones callers hear and the way phone numbers are written.

The first hour

Extensionsone per person1Phonesconnect each one2Trunkyour carrier3Call routingwhere calls go4Healthwhat is missing5Every step has a page in the menu; Health lists anything still missing, emergency calling first.
Figure 2. The first hour: five steps from a new install to a working phone system
  1. Extensions: one per person or desk. Each has a number and a SIP password. Open Extensions (chapter 3)
  2. Phones: connect a desk phone, softphone or the browser phone to each extension. Open Phones (chapter 4)
  3. Trunk: your phone company account, so you can call outside numbers and be called. Open Trunks (chapter 7)
  4. Call routing: where calls from outside go (a person, a ring group, a menu), and which trunk outside calls use. Open Call routing (chapter 8)
  5. Health tells you what is still missing, emergency calling first. Open Health (chapter 13)

Then make a test call: from any phone dial *43, the echo test. You hear yourself back, which proves sound works both ways.

Installing it in one command

On a Linux server (Ubuntu, Debian, RHEL, Fedora, Alpine with systemd) or a Mac:

curl -fsSL https://raw.githubusercontent.com/BioDream-LLC/bitvoice/main/deploy/install.sh | sh

On Windows, in PowerShell:

irm https://raw.githubusercontent.com/BioDream-LLC/bitvoice/main/deploy/install.ps1 | iex

It downloads the latest release for the computer, checks it against the release's SHA-256 sums and BioDream's release signature (with OpenSSL 3, which current Linux, macOS and Git for Windows have), and installs it as a service that starts by itself:

Run the same command again to upgrade (or use Updates (chapter 60)). sh -s -- --version v0.1.5 (after the pipe) picks a release; --uninstall removes the program and service and keeps the data, --purge removes the data too. On Windows, save the script and run .\install.ps1 -Version v0.1.5, -Uninstall or -Purge. For a server kept off the internet, copy the release's archive and SHA256SUMS into a folder and set BITVOICE_FROM to it.

Where it runs

BitVoice runs on Linux, macOS and Windows.

SystemHow to start itWhere its data is
Linux./bitvoice (or the systemd service in the release)~/.config/BitVoice
macOS./bitvoice~/Library/Application Support/BitVoice
Windowsdouble-click bitvoice.exe%APPDATA%\BitVoice

On Windows, keep the window it opens while you use BitVoice (closing it stops BitVoice), and when Windows asks whether it may use the network, allow private networks so phones can connect. -data puts the data anywhere else; -https and -sip choose the addresses and ports.

The ports it uses

PortWhat for
5060 UDP and TCPSIP: phones and trunks
5061 TCPSIP over TLS (encrypted signalling)
4569 UDPIAX2 trunks, only once one is set up
1720 TCPH.323 trunks, only once one is set up
2000 TCPSkinny (SCCP) phones, only when switched on
2727 UDPMGCP gateways, only when switched on
10000–20000 UDPthe sound of calls (RTP), set in Settings
8443 TCPthis web interface, HTTPS only (plain HTTP to it is sent on to HTTPS)

If another phone system already has 5060, BitVoice takes the next free port and Health says so.

Everything in the web interface

Every setting has a screen, and every screen has a chapter here. Nothing needs a configuration file, a command line or a second tool. For automation, the same screens are a REST API, and the configuration can follow a file in Git (Configuration as code (chapter 67)), but neither is ever required.

What BitVoice is for

BitVoice is first a phone system for offices and contact centres, and a hosted phone service for providers: everything in the first five parts of this manual. The 911 answering-point profile, the radio dispatch console and NG911 Core Services are a separate lab and design-partner track (Public safety (chapter 74)): they are off the menu until switched on in Settings, and not certified for live use. Emergency calls from your own phones are not part of that track; they work on every phone system from the first start.

Finding your way

Chapter 2

How mature each part is

How far each part has been proven, plainly. Field-tested: run against real systems over a real network (Amazon EC2, the internet, real providers' services). Checked against a reference: tested against an independent implementation or the standard's own data. Software-tested: BitVoice's own tests and browser tests only, not yet with real equipment or accounts. Lab: public-safety parts, not certified.

AreaMaturityWhat it rests on
SIP trunks: registration, calls in and out, caller ID, busy, keys (RFC 4733)Field-testedAsterisk as the carrier across the internet on EC2; MOS 4.4. No commercial carrier account tried yet
Desk phones over SIPField-testedAsterisk as a desk phone across the internet. Real Yealink, Poly or Grandstream handsets not tried yet
Browser phone (WebRTC)Field-testedfrom outside to EC2; Chromium browser tests with sound both ways
Two servers, one PostgreSQL, failoverField-testedkill -9 and planned stop on EC2: the call carries on, the provider line moves
One-command installField-testedUbuntu 24.04 (x86, Arm), Debian 12, Amazon Linux 2023, Windows Server 2022, macOS; back after a reboot
CapacityField-tested200 calls at once, no loss, on c7g.large, c7i.large, t4g.small, an M4 and the Lightsail nano
FreePBX migration (Import)Field-testeda real FreePBX 17.0.33 backup (70 MB) imported whole; others from FreePBX's own formats
AI transcripts, summaries, receptionistField-testeda real model through OpenRouter
Archive to S3, secrets from AWS Secrets ManagerField-testedreal AWS, our own SigV4
SNMP monitoring and trapsField-testednet-snmp's snmpwalk and snmptrapd
Let's EncryptField-testedissues and renews the public demo's certificate
Machine images (AWS) and configuration as codeField-testedan EC2 image built by deploy/cloud/build-images.sh from Ubuntu 24.04: each server from it starts new; deploy/terraform with OpenTofu 1.13 (create, change, no drift, destroy). Azure images not tried
IAX2 trunksChecked against a referenceAsterisk 23
H.323 trunksChecked against a referenceH323Plus 1.28 (its simph323 playing and recording WAV files) on EC2: calls both ways with Fast Connect and G.711, each end hearing the other's tone, MOS 4.39; call set-up also with Asterisk's chan_ooh323 (whose own sound is broken in Asterisk 22)
SIP over WebSocketChecked against a referenceJsSIP and SIP.js
Codecs: GSM, G.726, iLBC, MP3 hold musicChecked against a referenceffmpeg, the RFC 3951 reference program and minimp3, sample for sample
Codecs: G.711, G.722, Opus, G.729, AMR, SpeexSoftware-testedown round-trip tests; Opus and G.729 through their pinned Go libraries; Opus calls with the Android app
ISDN PRI and BRI, T1/E1Checked against a referencelibpri (Asterisk's), both sides; and on EC2 through the real DAHDI 3.4 kernel driver (two spans wired together in the kernel, Asterisk 20's chan_dahdi as the phone company): calls both ways with numbers and names, all 23 channels at once, MOS 4.39. No physical card or line yet
MFC-R2, E&MChecked against a referenceOpenR2; MF tones by our own tests. No real card or line tried
SS7 (ISUP, MTP, link sets of several links with changeover)Checked against a referencelibss7 (Asterisk's chan_dahdi library), ITU and ANSI. No real carrier link tried
Fax (T.30, T.38)Software-testedown tests between BitVoice ends; no fax provider or gateway tried
Provisioning: Yealink, Poly, Grandstream, Snom, Fanvil, Cisco, Mitel, Sangoma, Algo, CyberDataSoftware-testedthe vendors' documented formats; not on real handsets
Skinny (SCCP) phones, MGCP gatewaysSoftware-testedown tests; no Cisco phone or gateway tried
Microsoft Teams Direct RoutingSoftware-testedown tests; no Teams tenant tried
Hotel (FIAS)Software-testedown tests; not against Opera
Texting, WhatsApp, Messenger, web chatSoftware-testedstand-ins for each provider's API
CRM caller cards, Azure Blob, Azure Key VaultSoftware-testedstand-ins
iPhone and Android appsField-tested (Android)Android: a Google Pixel 11 (Android 17) in AWS Device Farm against BitVoice on EC2 with a Let's Encrypt certificate: paired by link, rang, answered from the notification, called out; Opus, MOS 4.1, about 5% of packets lost between the phone lab and the server. iPhone: Simulator only; push wake-up needs our own Apple and Firebase accounts
911 profile, radio console, NG911 Core Services, caller videoLabNENA's schemas and sample data, Wireshark, spandsp, OpenSSL, ExifTool, ffmpeg, a NIST P25 capture; never on a live ESInet, P25 system or PSAP CAD, and not certified
P25 Phase 2 half-rate voice (AMBE+2)Not offeredpatented until 2028
Ed448 signatures (NENA)Not offerednot in Go's standard library, and BitVoice writes no cryptography of its own; Ed25519 is used
SS7 signal transfer (STP), SCCP/TCAPNot offereda PBX is an end point; number portability and toll-free lookups are the carrier's
MFC-R2 China variantNot offeredOpenR2's own China variant disagrees with itself, so there is nothing sound to test against
ALI over PAM or E2Not offeredthrough a gateway; BitVoice speaks the request-and-text ALI links
Chapter 3

Extensions

In the web interface: /extensions

An extension is a number for a person or a desk. Phones sign in with the extension number and its SIP password; calls to the number ring every phone signed in as it, at once.

100 dials 101Forwarding?all, busy, no answerDo not disturb?then voicemailRings 101every phone, appsFollow-memobile, other deskNo-answervoicemail or other
Figure 3. A call between two extensions

Adding an extension

  1. Open Extensions (chapter 3) and press Add extension. The next free number and a strong SIP password are filled in.
  2. Enter the person's name (shown on other phones when they call) and email (for voicemail by email).
  3. Fill in the 911 location: the site, floor and room. It is sent with emergency calls.
  4. Choose what happens If nobody answers: voicemail by default, or another extension, a group or a menu.
  5. Save. The extension can sign in at once.

The fields

FieldWhat it does
Number2 to 8 digits; no other extension, group, queue, room or feature code may have it
SIP passwordwhat the phone signs in with; at least 12 characters; Generate makes a new one
Ring forseconds before If nobody answers happens (25 by default)
Outside caller IDthe number shown on calls out; empty uses the trunk's
Can call outside numbersoff keeps the phone to internal calls and emergency numbers
Record callswhen Settings records only selected extensions
Hot deska shared phone that becomes whoever signs in at it
Encrypt calls to this phonemedia encryption (SRTP); use it with TLS so the keys stay private
Departmentgroups this extension's call costs

Follow-me, pickup and intercom

Each person's own call handling is in its own box on the extension:

Forwarding right now

Below the settings, Forwarding right now shows and changes what the person set from their phone or the staff portal: do not disturb, and forwarding of every call, of calls while busy, and of calls not answered. These are live state, not configuration: changing them makes no revision.

What is connected

Connected devices

An extension that is open shows every device signed in as it: the phone's make and model, how it connects (UDP, TCP, TLS or the browser) and since when. The address and port to give a phone are shown there too.

Chapter 4

Connecting phones

In the web interface: /phones

Any SIP phone or app works: point it at this server's address and port 5060, with the extension number as user and its SIP password. Desk phones from the four big makers are set up automatically instead, so nobody types a password into a phone's keypad.

Yealink, Poly,Grandstream, Snom1. where is my file? (DHCP 66)2. HTTPS: extension, password, keysBitVoice3. registersSigned in as its extensionBLF keys, time zone, codecs, all set
Figure 4. Provisioning: a desk phone fetches its settings by itself

Automatic set-up (provisioning)

  1. On Phones (chapter 4) press Add phone and enter the phone's MAC address (on a sticker underneath) and the extension it belongs to.
  2. Choose the make: Yealink, Poly, Grandstream (including the HT analog adapters), Snom, Fanvil, Cisco, Mitel, Sangoma, Algo or CyberData.
  3. Tell the phone where BitVoice is: in your DHCP server, set option 66 to the provisioning address shown on the screen, so every phone on the network finds it by itself; or type the same address in the phone's own web page, under auto provisioning.
  4. Restart the phone. It fetches its file over HTTPS, signs in, and its line keys show who is on the phone.

HTTPS or plain HTTP. Phones fetch their file over HTTPS when they can. Some older phones cannot use HTTPS at all, and many do not trust the certificate BitVoice made itself; for those, the screen also shows a plain http:// address on the same port. Plain HTTP is only for these files: every other page still goes to HTTPS. Over plain HTTP the phone's SIP password crosses the network unencrypted, so keep it to a trusted office network, or install a certificate from an authority and switch on HTTPS only for phones.

The file carries the extension, its password, the time zone, the codecs, busy lamp keys and the address of this server. Provisioning is protected by a user name and password the phones are given once.

MakeModels testedWhat it gets
YealinkT3x, T4x, T5xaccount, BLF keys, time, codecs
PolyVVX, Edge Ethe same, in Poly's own format
GrandstreamGRP, GXP, HT802/814account per port on adapters
SnomD7xxaccount, keys, time

These makes are provisioned too, with files written from each maker's documented format but not yet tried on their devices (the Phones screen marks them untested):

MakeModelsFile the device asks for
FanvilX and V seriesits MAC address .cfg
Cisco6800, 7800, 8800 multiplatform (3PCC), SPA adaptersits MAC address .xml (enterprise firmware needs the multiplatform firmware first)
Mitel (Aastra)6800, 6900 SIPits MAC address .cfg, in capitals
SangomaS-seriesthe Fanvil-format file
Algopaging speakers, strobes, adaptersalgop and its MAC address .conf
CyberDataspeakers, intercoms, paging adaptersits MAC address .xml

Each gets its account, the server (and the backup server, with several servers), the transport and encryption, and the voicemail number where it has one. Set Algo and CyberData speakers' extensions to Overhead speaker so calls to them are answered at once.

Phones without provisioning

Softphones and other makes take the same three things: server (this computer's address, port 5060, or 5061 with TLS), user (the extension number) and password (its SIP password). Health lists phones that tried a wrong password; after a few tries the address is banned for a while (see Security (chapter 58)).

The browser phone

The phone icon at the bottom of every screen makes this browser a phone for an extension, with your microphone and speakers. It uses WebRTC: the sound is encrypted end to end, and it works through most firewalls without any setting.

Other WebRTC softphones (SIP over WebSocket)

Softphones and web apps built on JsSIP, SIP.js and similar libraries speak SIP over WebSocket (RFC 7118). Switch on SIP over WebSocket in Settings (chapter 14) and point them at wss://<this server's name>:<web port>/ws, with the extension number as the user and its SIP password. BitVoice ends their WebRTC sound itself (ICE, DTLS-SRTP, Opus or G.711), so they reach every phone, trunk and feature as desk phones do: calls both ways, keys pressed, hold, transfers by the other party, busy lamps and message-waiting. Settings shows how many are connected.

The WebSocket needs no sign-in of its own: the softphone signs in with SIP, and failed sign-ins and too many requests are counted for its own address, as for any phone. A softphone page served from another site must trust this server's certificate (use Let's Encrypt), and current Chrome asks the user before a public web page may reach a server on the local network.

Tested with two independent libraries, JsSIP 3.13 and SIP.js 0.21: two softphones of each register, call each other and hear each other through BitVoice. Other softphones (Linphone's web client, Zoiper's) speak the same protocol but have not been tried.

TURN, for networks that block UDP

Some networks (hotels, guest Wi-Fi, strict company firewalls) let no UDP out, or hide computers behind NATs WebRTC cannot get through. For those, switch on TURN server in Settings (chapter 14): BitVoice then runs its own TURN server (RFC 8656) on port 3478 (UDP and TCP) and, with this server's certificate, on port 5349 over TLS. Browser phones, the staff phone and call links are given short-lived credentials for it, and use it when they cannot reach the media ports directly; the sound is still encrypted end to end, and BitVoice relays it only to its own addresses, so nobody can use it to reach anything else.

Open the TURN port, the TLS port and the relay ports (49152 to 49407 unless you change them) in the firewall. TURN over TLS needs a certificate browsers trust for the name they use, such as one from Let's Encrypt (chapter 14): until there is one, BitVoice does not offer it to browsers (they would try it, fail and wait), and offers it as soon as the certificate arrives; set its port to 443 on a server with a spare address to get through firewalls that allow only HTTPS.

The staff phone

Open #/phone on any computer or mobile browser: people sign in with their extension and SIP password, without an administrator account. It is a full phone: dial, answer, hold, transfer and the keypad. For their own forwarding and voicemail they use the staff portal at #/me (see The staff portal (chapter 32)).

The mobile apps

The BitVoice apps for iPhone and Android are paired from the extension's page with a QR code. Calls wake the app through Apple's and Google's push services, so it rings even when it is closed.

Chapter 5

Skinny phones and MGCP gateways

In the web interface: /desk-phones

Phones and gateways that do not speak SIP can still be used. Skinny phones and MGCP gateways (under Calls) takes two older protocols:

Each Skinny phone or MGCP line is one more device of its extension: it rings with the extension's other phones, calls out as the extension, and shows in the extension's devices. The page shows each one's state.

What works

Hold, transfer and conference are done from the extension's other phones for now, and a Skinny phone's second line is not used.

Security

Neither protocol has passwords. Skinny phones are accepted only from the local network and only when listed; MGCP commands are obeyed only from the gateway's address (or, without one, from the local network). Keep both ports off the internet.

Chapter 6

Telephony cards

In the web interface: /cards

A telephony card in the BitVoice computer (Digium, Sangoma, OpenVox and other cards with Linux DAHDI drivers) can carry analogue phones and phone company lines. A separate program, bitvoice-dahdi, drives the card and joins its ports to BitVoice over the computer's own network connection, so BitVoice itself never touches the kernel driver and a card problem cannot stop the phone system.

Setting it up

  1. Install the DAHDI drivers and set the ports up as usual in /etc/dahdi/system.conf (fxoks=1-4 for ports with phones, fxsks=5-8 for ports with lines, and the country's tones in loadzone and defaultzone), then run dahdi_cfg.
  2. In Telephony cards (under Calls) switch on Use telephony cards. A token is made; copy it into a file only root can read, such as /etc/bitvoice/cards.token.
  3. Add each port by its DAHDI channel number: a phone port (FXS, a phone, fax or door phone plugged in) with its extension, or a line port (FXO, a phone company line) with the line's number. Choose A-law for Europe and most of the world, µ-law for North America and Japan.
  4. For lines, add a trunk with the protocol Telephony card lines on Trunks, and route numbers to it as to any trunk; inbound routes match each line's number.
  5. Start bitvoice-dahdi -server https://127.0.0.1:8443 -token-file /etc/bitvoice/cards.token as a service user that may open /dev/dahdi. It is in the Linux download beside bitvoice. The page shows whether it is running and each port's state; changes reach it within ten seconds. A channel another program still holds (or one dahdi_cfg has not set up yet) is tried again every two seconds, so the order things start in does not matter.

What works

Digital lines: T1 and E1 PRI

A T1 (23 calls at once) or E1 (30) line run as primary rate ISDN plugs into a digital card (Digium/Sangoma TE-series, OpenVox D-series and the like). BitVoice speaks the PRI itself (Q.921 on the D-channel, and Q.931 call control), so every call comes in with the number dialled and the caller ID, goes out with the extension's caller ID, and the phone company says when the far end answers, rings or is busy.

  1. In /etc/dahdi/system.conf, set the span up for PRI as usual (span=1,1,0,esf,b8zs, bchan=1-23, hardhdlc=24 for a T1; span=1,1,0,ccs,hdb3,crc4, bchan=1-15,17-31, hardhdlc=16 for an E1), and run dahdi_cfg.
  2. Under Digital lines on Telephony cards (chapter 6), add the span: T1 or E1, its first DAHDI channel, whether BitVoice is the PBX on the phone company's line (the usual) or the network (another PBX connects to BitVoice as if to the phone company), and the switch type the phone company gave you.
  3. Add the card trunk on Trunks if there is none yet, and inbound routes for the numbers (DIDs) the phone company sends.

Calls out take a PRI first, the analogue lines after; a busy number, a wrong number or no free channel comes back as busy, not found or unavailable, as the network says. The page shows whether each span's D-channel is up and how many of its channels are in calls. T1 channels set up with robbed-bit signalling (fxsks, fxoks) work as the analogue ports above.

Names, forwarding and transfers. A caller's name comes in with the call (from the Display element, or on National ISDN-2 from the name the network sends as a facility) and phones show it; calls out send the extension's name the same way. The number a call was forwarded from comes in as its redirecting number (BitVoice passes it on as SIP's Diversion, with the reason: busy, no answer, unconditional), and when an extension's forwarding sends a call back out on the PRI, the extension's number goes with it as the redirecting number, so the far end and the phone company know whose call it is. When an outside call is answered, BitVoice tells the network the number that answered (the connected number).

Switch on Transfers through the phone company on a span (user side, National ISDN-2, 5ESS, DMS-100 or EuroISDN) and when someone transfers a caller on that line to another number on the same line, BitVoice asks the network to join the two calls itself: Two B-Channel Transfer on National ISDN-2 and 5ESS lines, Release Link Trunk transfer on a Nortel DMS-100, explicit call transfer (the caller held, then joined) on EuroISDN. A DMS-100 gives a transfer identifier only to calls BitVoice places, so there one of the two calls must be a call out (the usual case: a caller forwarded or transferred to an outside number). Both channels are freed as soon as the network has joined them. The line needs the service (ask the phone company for "two B-channel transfer" or "ECT"); if the network refuses, the transfer still works, through BitVoice, using both channels as before. On a span where BitVoice is the network side, another PBX may ask BitVoice to join two of its calls; BitVoice declines (it is not a switch), and the PBX keeps the calls itself.

Trying it without a card

DAHDI's own dynamic spans can stand in for a card: two spans joined inside the kernel, BitVoice on one and another PBX (Asterisk's chan_dahdi, say) as the phone company on the other. Load dahdi, dahdi_dynamic and dahdi_dynamic_loc, and in /etc/dahdi/system.conf:

dynamic=loc,1:0,24,0
dynamic=loc,1:1,24,0
bchan=1-23
dchan=24
bchan=25-47
dchan=48

Leave the last number (timing) at 0 on both: DAHDI's own timer then drives them. Spans that are each other's timing source tick only when the other sends, and the D-channel comes and goes. Add span 1 here as a T1 (first channel 1), and set the other PBX up as the network side on channels 25 to 48.

Basic rate ISDN (BRI)

A BRI carries two calls at once (B1 and B2) and is common in Europe for small offices; it also connects ISDN desk phones. BRI cards (Digium B410P, the HFC-based cards from OpenVox, Junghanns and others) work through DAHDI as the PRI cards do: in /etc/dahdi/system.conf the span is span=1,1,0,ccs,ami with bchan=1-2 and hardhdlc=3. Add it under Digital lines with BRI as the line type; its channels are B1, B2 and then the D-channel.

Names, forwarding, transfers on EuroISDN (explicit call transfer) and advice of charge work on a BRI as on a PRI.

E&M trunks on a T1

A T1 whose channels are set up as E&M (robbed-bit signalling: e&m=1-24 in /etc/dahdi/system.conf) gives 24 trunks, each signalled on its own: tie lines to another PBX, channel banks, and long-distance carriers' Feature Group D trunks. Under Digital lines, add a T1 and set Signalling to E&M, then:

A call out takes a free trunk, seizes it, waits for the start signal (no wink within five seconds is "no wink", and the call fails), sends the number, and is answered when the far end goes off hook (answer supervision). A call in is answered by going off hook when the extension answers.

CAMA trunks (911, lab track). A PSAP still fed by a 911 selective router over CAMA trunks sets Start signal to CAMA (911 trunk). The router seizes, BitVoice winks, and the router sends the caller's number (ANI) in MF: enhanced CAMA as KP, two information digits and all ten digits, ST; traditional CAMA as KP, one numbering plan digit and seven digits, ST. For traditional CAMA, list under Area codes for NPD 0 to 3 the area code each numbering plan digit stands for (your router's set-up sheet has them); a digit above 3 means the router could not identify the line. Each call goes to the inbound route for 911 as a 911 call, with the ANI as its callback number, and BitVoice looks its location up by that number (see 911 calls (chapter 74), Location lookup (ALI)). The information digits show on the call as CAMA (II 00).

MFC-R2 on an E1

In Latin America, parts of Asia and Africa, E1 lines are often MFC-R2 rather than ISDN: 30 circuits, each with its line signals on the A and B bits of timeslot 16 (ITU-T Q.421) and its number, the caller's category and the caller's number exchanged in compelled multifrequency tones (Q.441), forward and backward. Set the span up as CAS in /etc/dahdi/system.conf (span=1,1,0,cas,hdb3, cas=1-15:1101, cas=17-31:1101, dchan removed), then under Digital lines add an E1, set Signalling to MFC-R2 and choose the Country variant: ITU-T, Argentina, Brazil, Colombia, Czech Republic, Ecuador, Mexico, Philippines or Venezuela. Each country assigns some signals differently (what means busy, how the end of the number is told, Mexico's extra Group C); the variant holds those.

Every circuit carries calls both ways. A call in reaches the inbound routes with the number dialled and the caller's number (withheld numbers come in as anonymous); a busy extension or a wrong number is signalled back as busy or unallocated, as the variant says. A call out sends the number and the extension's caller ID, or the "number withheld" signal when the caller hides it. China's variant is not offered.

The MFC-R2 signalling is tested against OpenR2 (the R2 library Asterisk's chan_dahdi uses), in every variant offered and in both directions, including a call refused as busy; E&M against BitVoice's own simulated channels.

SS7

A carrier may hand over T1s or E1s signalled by SS7 rather than ISDN: the voice circuits carry calls, each named by a circuit identification code (CIC), and one timeslot carries the signalling link to the carrier's signal transfer point or switch, over which ISUP sets the calls up. BitVoice is then a signalling point of its own, with a point code the carrier assigns. In /etc/dahdi/system.conf set the span up as clear channels with the signalling timeslot as mtp2 or hardhdlc (timeslot 16 on an E1, 24 on a T1). Under Digital lines add the span, set Signalling to SS7 (ISUP) and give:

Link sets of several links. Spans with the same variant, point codes and network are one link set (up to 16 links): each span's signalling link is one of its links, and needs its own Link code, and every span's circuits belong to it (their CICs may not overlap). Traffic is shared between the links in service by the messages' SLS, so one call's messages keep to one link. When a link fails (the link test goes unanswered, or messages go unacknowledged), its traffic changes over to the others (Q.704: COO and COA, the messages the far end had not got sent again on another link; or, with no answer in time, by time), the calls on every span go on, and Telephony cards says how many links are in service and how this span's stands. When the link is back and tested, its traffic changes back (CBD and CBA). Only when every link is down is the link set down. Tried against libss7 with two links, one cut in the middle of a call: libss7 takes network management messages only on the link their SLS names, so a changeover message about the cut link (sent on the other, as Q.704 has it) is dropped there, and both ends change over by time instead, which works; between two BitVoice ends it goes by COO and COA.

When the link comes up, BitVoice aligns it (MTP level 2, with the emergency proving period as a single-link link set uses), proves it with the link test (SLTM/SLTA), exchanges traffic restart allowed, and resets every circuit (GRS). Calls in reach the inbound routes with the number dialled, the caller's number (withheld ones as anonymous), the number a call was forwarded from and, on ANSI, the caller's name; calls out carry the extension's caller ID and name. The carrier blocking or resetting circuits is obeyed. On dual seizure the end with the higher point code keeps the even circuits, as Q.764 says, and BitVoice takes the circuits it keeps first.

SS7 is tested against libss7 (the SS7 library Asterisk's chan_dahdi uses), ITU and ANSI: alignment, link test, traffic restart, circuit reset, calls both ways with numbers and names, release, busy and blocking; and BitVoice against itself with frames lost on the link (sent again by MTP2's error correction) and a dual seizure. Signal transfer (being an STP for others) and SCCP/TCAP (number portability lookups, toll-free translation) are not offered: a PBX is an end point, and those are the carrier's.

Advice of charge. On a EuroISDN line, switch on Advice of charge and BitVoice asks the phone company, with each call out, to say what it costs: during the call (AOC-D) and at its end (AOC-E), in money or in charging units. The last figure goes on the call's record (charged EUR 1.50 in History, and beside the call on Costs); when it is in your currency (set on Costs) it is the call's cost, instead of the figure from the trunk's rates. The phone company must offer the service on the line. SIP trunks may send the same advice, as the 3GPP AOC XML in an INFO or the BYE, and BitVoice keeps it the same way.

The PRI code is tested against libpri (the ISDN library Asterisk uses), both as the user side and as the network side, for National ISDN-2 and EuroISDN calls, names, redirecting and connected numbers, explicit call transfer, the Two B-Channel Transfer and DMS-100 Release Link Trunk requests byte for byte (with libpri's PBX joined by BitVoice as the DMS-100), and advice of charge in both directions; and on BRI, point to point and multipoint, as the terminal and as the network (TEI assignment, calls broadcast to the bus, numbers dialled digit by digit).

Not yet: caller ID shown on analogue phones or read from analogue lines, hook flash, and echo cancellation beyond what the card itself does.

Chapter 7

Trunks

In the web interface: /trunks

A trunk is your account with a phone company. It carries calls to and from outside numbers. Most are SIP trunks; an Asterisk or FreePBX server, or an IAX2 provider, can be reached with IAX2 instead.

BitVoiceREGISTER every few minutescalls out: number, caller IDcalls in: the number dialledCarrierUsername and passwordAllowed addressesCodecs, channels, rates
Figure 5. A trunk: your account with a phone company

Adding a SIP trunk

  1. On Trunks (chapter 7) press Add trunk.
  2. Enter the provider server your phone company gave you (sip.provider.com), and the port if it is not 5060.
  3. Enter the username and password, and switch on Register if the provider says to (most do).
  4. Save. Within a few seconds the trunk shows registered; if not, the reason is shown beside it.

The trunk health judge

With two or more trunks on an outbound route, BitVoice judges every 15 seconds whether each is used in its place or tried after the other trunks. A trunk moves behind the others when its provider stops answering the keep-alive checks, or when its last calls out failed one after another on the provider's side (Failed calls in a row within Within (minutes), Settings, Trunk health judge), and another trunk is working. It is not moved on a failing keep-alive alone while calls through it still get through; and when every trunk fails at once, the likelier cause is this system's own internet link, so nothing is moved. A change needs two judgements in a row (30 seconds), so a trunk never flaps. A trunk is never taken out altogether: it is still tried when the others fail, so an emergency call always has every way out. The trunk's page shows the judgement and its reasons; a call that went out another way says so in its record.

  1. Add an incoming route for your number and an outgoing route that uses this trunk (Call routing (chapter 8)).
FieldWhat it does
TransportUDP (usual), TCP, or TLS for encrypted signalling
Registersign in every few minutes, so the provider knows where to send calls
Authentication usernameonly when the provider gives a separate one
From domainthe domain in the caller's address, when the provider asks for one
Caller IDthe number shown on calls out; an extension's own caller ID wins
Also accept calls fromthe provider's other addresses or networks that send calls in
Calls at oncethe limit your plan allows; calls beyond it go to the next trunk in the route
Encrypt mediaSRTP, for providers that support it
Codecsleave it on *same as Settings*, or choose what this provider supports, best first
Rateswhat calls cost by number prefix, for Costs (chapter 53)

Cloud providers

Start from fills in Microsoft Teams Direct Routing, Amazon Chime SDK Voice Connector or Azure Communication Services, with a note on what to set on their side. Teams is described in its own chapter (Microsoft Teams (chapter 65)).

IAX2 trunks to Asterisk and FreePBX

Choose IAX2 as the protocol to join another Asterisk or FreePBX server, or an IAX2 provider. IAX2 carries signalling and sound on one UDP port, 4569, which makes it easy through firewalls.

BitVoiceone UDP port, 4569: signalling and audio togetherMD5 challenge with the shared password; call tokensAsterisk or FreePBXiax.conf: type=friend, secret=…
Figure 6. An IAX2 trunk to an Asterisk or FreePBX server

On the Asterisk side, a peer like this is all it takes:

[bitvoice]
type=friend
host=dynamic
secret=the shared password
context=from-bitvoice

IAX2 port 4569 opens only when the first IAX2 trunk is added, so an Asterisk running on the same computer keeps it until then.

H.323 trunks

Choose H.323 as the protocol for older gateways, PBXs and video-conference systems that speak H.323 but not SIP. Give the gateway's address (port 1720); calls are accepted only from it. Calls are set up with Fast Connect and G.711 (µ-law or A-law; the trunk's codec list may narrow it to one), and the sound goes straight between the gateway and BitVoice's media ports. BitVoice converts to whatever the other party uses.

H.323 here is deliberately small: no gatekeeper (RAS), no H.245 (so a gateway that will not use Fast Connect gets no call, and is told so), no video, no H.235 security. Caller ID comes from the Q.931 calling number or the caller's dialled-digits alias, the name from the display or its H.323 ID. BitVoice's H.225.0 and H.245 encoding was checked against an independent ASN.1 encoder, but not yet against gateway hardware.

What the status means

StatusMeaning
registeredsigned in; calls can come in
readydoes not register, or IAX2 waiting for calls
unreachablethe server's name is not in DNS, or nothing answers
failedthe provider refused the sign-in; the reason is shown
standbyservers share this trunk one at a time and another holds it
Chapter 8

Call routing

In the web interface: /routes

Call routing decides two things: where calls from outside go, by the number they dialled, and which trunk calls to outside numbers use.

CarrierIncoming routeby number dialledScheduleopen or closed?openclosedMenu1 sales, 2 supportRing grouprings everyone for 25 sVoicemailafter hoursif nobody answers
Figure 7. How a call from outside finds its way

Incoming routes

Each incoming route matches the number that was called (or any number) and sends the call to a destination: an extension, ring group, queue, menu, schedule, script, conference room, AI receptionist or voicemail. Numbers match in any form: +1 212 555 0100, 2125550100 and 12125550100 are the same.

Outgoing routes

Outgoing routes match what people dial, by pattern, and send it to trunks in order: if the first is down or full, the next is tried.

Dialled2125550199Emergency 911Long distance 1NXXNXXXXXXLocal NXXNXXXXXXInternational 011.matchTrunk AfirstTrunk Bif A failsN is 2–9, X is any digit, . is anything more; emergency numbers never fail for want of a pattern.
Figure 8. Outgoing routes: the first pattern that matches, its trunks in order
PatternMatches
Xany digit
Z1 to 9
N2 to 9
[1-5]one of a set
. at the endone or more further digits
NXXNXXXXXXa ten-digit North American number
1NXXNXXXXXXthe same with 1 in front
011.an international call from the US

Emergency numbers

The emergency numbers always work. A route that names the number exactly is used first; with none, every working trunk is tried in turn. A call to them is never refused for an extension's limits, a hosted organisation's limits or a missing route. Health warns when no trunk can carry them.

Chapter 9

PIN sets

In the web interface: /pin-sets

A PIN set (chapter 9) is a list of PINs an outbound route asks for before it calls out: to keep international or long-distance calls to people with a PIN, or to bill calls to clients and projects by their code.

  1. Add PIN set and list its PINs (4 to 10 digits each).
  2. Switch on Keep the PIN in the call record to write the PIN used into each call's record as its account code (the accountcode column of the CSV, syslog and PostgreSQL call record outputs, and account in the API).
  3. On Call routing (chapter 8), open an outbound route and choose the set under Ask for a PIN.

Callers dialling a number that route takes hear "Please enter your PIN, then press hash", enter it, and the call goes out. Three wrong PINs end the call, and the attempt is logged as a security event. Emergency numbers never ask for a PIN, whatever route they take, and forwarded calls and follow-me numbers are not asked either: only people dialling from a phone.

Chapter 10

Caller ID lookup

In the web interface: /lookups

Many phone companies send a caller's number but no name. BitVoice first looks in the company contacts (chapter 37); after that, an inbound route can ask a caller ID lookup (chapter 10):

Choose the lookup on an inbound route on Call routing (chapter 8) (Caller ID lookup). Phones show the name while they ring, and it goes into the call record.

A lookup never holds a call up: BitVoice waits at most its wait (1.5 seconds unless you change it, 5 at most) and then rings without a name. Answers are kept for a day (or as long as you set, or never with -1), so a regular caller is not looked up on every call; numbers the service does not know are asked again after an hour. Try it on the lookup's page asks for a number at once, with the settings as saved.

Chapter 11

Emergency calls

Emergency numbers always go out, from every extension, even ones that cannot call outside numbers. This chapter is about emergency calls made from the phones BitVoice runs: an office calling 911. Answering 911 calls is the 911 profile (chapter 74).

dials 911Emergency routenever fails for want of oneCarrierThe PSAPanswersSite, floor, roomsent as PIDF-LOAlerts on site: security desk, email listKari's Law
Figure 9. Office 911: location goes with the call, people on site are told

What BitVoice does on every emergency call

  1. Routes it, always: a route that names the number first; with none, every working trunk in turn. Limits never stop it: an extension not allowed outside calls, a hosted organisation at its call limit or suspended, a trunk at its channel limit.
  2. Sends where the caller is: with Send the caller's address on (Settings), the call carries the site's civic address, floor and room to the provider as PIDF-LO.
  3. Tells people on site (Kari's Law in the US): the extensions under Notify get a message on their phones, every open BitVoice screen shows an alert, and the addresses under Also email get an email with the caller's name, extension, site, floor and room, so someone can meet the responders at the door.
  4. Lets the call back through: for an hour after an emergency call, calls coming in are never refused, so the answering point can always ring back.

Setting it up

  1. Check the emergency numbers in Settings (chapter 14) (set by country: 911 and 933 in the US).
  2. Add every building under Sites (chapter 12), with its street address and the networks its phones use.
  3. Give every extension its site, floor and room.
  4. Make sure an outgoing route and trunk carry emergency calls; Health (chapter 13) warns when none can.
  5. Fill in Notify and Also email.
  6. Dial 933 (in the US) to hear the address your provider has.

Remote workers

A phone registering from outside its site's networks is a remote worker: their phone page asks where they are, and that address is used instead. Alerts say when it was not confirmed.

Emergency mode

A different thing: one switch that sends every incoming call to one place (an evacuation, a closure, an incident). Set where calls go, an optional code such as *55 and the extensions allowed to dial it in Settings (chapter 14); switch it on the Dashboard (chapter 1), or by dialling the code (rising tones for on, a low tone for off). A red bar shows on every screen while it is on.

Chapter 12

Sites and office 911

In the web interface: /sites

A site is a building: its street address and the networks its phones use. Sites are how an emergency call says where the caller is, down to the floor and room. In the US, Kari's Law and RAY BAUM'S Act require exactly this from business phone systems.

Head office · 1 Main St · 10.0.0.0/16floor and room from each extensionat homeAsked onceconfirms the address
Figure 10. Sites and remote workers: where a phone is, for 911

Adding a site

On Sites (chapter 12), press Add:

FieldWhat it is
Namewhat people call it: Head office
Street, City, State or province, Postal code, Countrythe civic address responders are sent to
Networksthe address ranges its phones use, such as 10.1.0.0/16; one per line

Then on each extension give its site, floor and room. Health (chapter 13) lists extensions without a location.

How a phone's place is found

  1. A phone registering from one of a site's networks is at that site, with its extension's floor and room.
  2. A hot desk carries the desk's own site, floor and room, not the person signed in (Hot desking (chapter 35)).
  3. A phone registering from outside every site's networks is a remote worker. On its first emergency-capable registration from a new place, its user is asked to confirm their address on their phone page; emergency calls then carry that address.
  4. If a remote worker never confirmed, the call still goes out, with the extension's usual site, and alerts say the address was not confirmed.

On-site alerts

With Email when someone calls 911 set in Settings, the people named there get the caller's name, extension, site, floor and room as soon as a call to an emergency number starts, so someone can meet the responders at the door. Notify extensions get a message on their phones, and every open BitVoice screen shows an alert. See Emergency calls (chapter 11).

Chapter 13

Health

In the web interface: /health

Health says whether the system is ready for calls, and if not, what to do. Each line says what is wrong in plain words and links to the screen where it is fixed. Check it after every change of any size.

What it checks

CheckWhy it matters
Emergency calls can get outa route and a working trunk carry the emergency numbers
Extensions without an emergency locationtheir 911 calls would carry no floor or room
The phone serviceSIP is listening, and on which port
Phones not connectedextensions nobody has signed in as
Trunksregistered, or the reason they are not
Menus without a recorded promptcallers would hear silence
The time zoneschedules follow it
Recordings and their keepingdisk space, and how long recordings are kept
Certificateswhen the TLS certificate runs out
Key vaultssecrets a vault cannot read
Other serverswhen several share a database, whether each is running

Problems are coloured: red stops calls (no emergency route), amber should be looked at (a phone not connected), and grey is for information.

Chapter 14

Settings

In the web interface: /settings

Settings holds everything about the system as a whole. Each section saves on its own, and every save is a revision on Changes (chapter 59).

SectionWhat is there
Systemname, country, time zone, language, the public address phones and providers see
Numbersthe echo test, voicemail and park numbers, and the emergency numbers
Codecsthe codecs phones may use, best first (Codecs (chapter 64))
Call recordingoff, every call, or selected extensions; consent rules; how long recordings are kept
Soundclean-up for voicemail and during calls
Protectionbans after failed sign-ins, trusted networks, calls per extension, premium numbers
Emergencysend the caller's address, who is notified, who is emailed, emergency mode
AIthe AI service, models, and which AI features are on (AI (chapter 27))
Single sign-onthe identity provider (Single sign-on (chapter 57))
Asterisk compatibilityAMI and ARI for programs written for Asterisk (Asterisk compatibility (chapter 68))
Mobile appsthe push service that wakes the apps
Emailthe mail server voicemail, faxes and alerts go through
Key vaultssecrets kept in AWS Secrets Manager or Azure Key Vault
Configuration from Gitkeep the configuration in step with a file in a repository
DatabaseSQLite or PostgreSQL (Database (chapter 62))
Certificatethe certificate for this interface and SIP over TLS: from Let's Encrypt, installed by hand, or BitVoice's own

Passwords and keys are never shown again once saved; leave them empty to keep them. Viewers see Settings with every secret removed.

The certificate and Let's Encrypt

BitVoice starts with a certificate it made itself, which browsers and phones warn about. For a server with a public name, switch on Let's Encrypt under Certificate: enter the names (pbx.example.com), optionally an email address, and apply. BitVoice gets a free certificate from Let's Encrypt, uses it at once for the web interface, SIP over TLS and Teams, and renews it about 30 days before it ends (Let's Encrypt certificates last 90 days or less). The status line says when it was issued, when it renews and, if it failed, why; it tries again after an hour, then less often, within Let's Encrypt's limits. Check now tries at once.

Let's Encrypt must reach the server under each name from the internet, to prove it is yours:

Other ACME authorities that need no account binding (a company's own step-ca, Let's Encrypt's staging service for tests) are chosen under Authority. Wildcard names need DNS proofs, which BitVoice does not do: install those certificates by hand. Each server of a cluster gets its own certificate.

Part 2

Where calls go

The building blocks callers move through: groups and queues, menus and schedules, scripts and the AI receptionist, voicemail, and the diagram that shows it all.

Chapter 15

Call flow

In the web interface: /flow
CarrierIncoming routeby number dialledScheduleopen or closed?openclosedMenu1 sales, 2 supportRing grouprings everyone for 25 sVoicemailafter hoursif nobody answers
Figure 11. How a call from outside finds its way

Check every situation

Check every situation, at the top of Call flow (chapter 15), tries your whole call plan in every situation it can be in, not a sample:

It lists what it finds, the worst first: a call goes nowhere (a group with nobody to ring and nowhere to go next), a loop, works, but look at it (a queue with no agents), nothing routes to it (a menu or schedule no call reaches), a branch no situation takes (a schedule that is never closed, so its closed side is never used), and emergency calls rest on one trunk (if it fails, they cannot get out). Each finding names the situations that show it: the time and which schedules were open, the toggles switched over, and the path (a call to +12125550100 → Press 2 (Billing) → No answer). Try this call fills Try a call below with that exact situation and traces it.

The same check runs on changes before they are made: a proposal from Ask in plain words and the Restore this look at an old revision both list what the change would break that works today.

Try a call

Enter who calls (an extension, or an outside number), what they dial and when, and press Try it. BitVoice follows the call exactly as it would for real, without ringing anything: the incoming route, schedules at that time, routing scripts (they run, in their sandbox), menus, groups and queues, and what happens if nobody answers. The path this call takes is marked; other ways on (a menu's keys, a schedule's other side) can be opened. Green means it works, amber means look at it (a phone not connected, a script falling back), red means the call fails there. Tick Assume every phone is connected to see the plan as designed rather than as it is right now; Arrives on picks the trunk for routes that only take one.

The diagram

The diagram shows where calls from outside go, box by box: each incoming route, then the menus, groups, queues, schedules, scripts and people it leads to.

Click a box (or Tab to it and press Enter) to change where calls go from it: a route's destination, an extension's or group's If nobody answers, a schedule's open and closed destinations, a menu's keys (add or remove keys right there), a script's fallback or a receptionist's person. Saving checks the change like any other and makes a revision. Open its full editor goes to the item's own page. Add incoming route adds a route without leaving the diagram.

Chapter 16

Ring groups

In the web interface: /ring-groups

A ring group is one number that rings several extensions: a sales team, the front desk and its back-up, everyone in the workshop.

ALL AT ONCEONE AFTER ANOTHERRing group 600the first to answer takes itRing group 6010–25 s25–50 s50–75 s
Figure 12. Ring groups: all at once, or one after another

Ringing strategies

Members who are away (in a meeting on their calendar, or with do not disturb on) are skipped; the group rings the others. Members with the mobile app are woken by a push and rung too.

If nobody answers

When nobody answers within the ring time, the call goes to If nobody answers: a member's voicemail, a queue, a menu, another group. With nothing set, it rings until the caller gives up.

Groups, queues or pickup?

UseWhen
A ring groupa few people, any of whom can take the call, and the call should ring now
A queuecallers may have to wait for someone free, and should hear their place
A pickup groupeach person has their own calls, but colleagues may answer for them
Chapter 17

Queues

In the web interface: /queues

A queue holds callers in order, with music, and rings the next free agent. It is the heart of a contact centre, and useful in any office where calls come faster than people can take them.

CALLERS WAITINGAGENTSVIP234Queue 700longest-idle agentAgent 1availableAgent 2on a callAgent 3wrap-upAgent 4pausedthey hear music and their place in linea VIP joins at the front
Figure 13. A queue: callers wait in order, agents take the next one

How calls are offered

StrategyWho is rung
Longest idlethe free agent who has waited longest since their last call
Round robineach free agent in turn, carrying on from the last one
Ring allevery free agent at once
Fewest callsthe free agent who took the fewest calls today
In order (linear)always from the top of the list: the first free agent
Randomany free agent, by chance
Weighted randomby chance, agents with a lower penalty much more often

The Queues screen is a live wallboard: who is waiting, for how long, and each agent's state.

Agents

Agents dial *45 to log in or out of every queue, and *46 to pause (a break) and resume; paused and logged-out agents are not offered calls. The wallboard has the same buttons, and shows why an agent paused.

StateMeaning
availablefree; will be offered the next caller
ringingbeing offered a call
busyon a call
wrap-upjust finished; the wrap-up time is running
pausedon a break, with the reason given
awayin a meeting or on time off, from their calendar
logged outnot taking queue calls at all

Supervisors

On Live calls (chapter 45), Supervise rings a supervisor's phone; when they answer they listen (heard by nobody), whisper (heard by the agent only) or barge (heard by both), and can switch between them during the call.

Sticky queues and VIPs

Switch on Sticky in a queue and a returning caller (one answered in the last 30 days, or as many as you set) is offered first to the agent who answered them last time, if that agent is free; if they do not answer, the queue goes on as usual. VIP callers, at the foot of Queues, go to the front of every queue they call, after any VIP already waiting, and are marked VIP on the board.

Chapter 18

Outbound dialer

In the web interface: /dialer

The outbound dialer (chapter 18) calls lists of contacts for a queue (chapter 17)'s agents: renewals, appointment reminders, collections, surveys. Each campaign has its queue, its list and its way of calling:

ModeHow it calls
Previewan agent asks for the next contact, sees its details, then calls it (their phone rings first) or skips it
Progressiveone call for each free agent
Powera set number of calls for each free agent (1 to 3)
PredictiveBitVoice adjusts the calls per agent, leaning in while few calls are abandoned and backing off as the abandon rate nears the limit
  1. Add campaign: its queue, its caller ID (the number contacts see), the hours calls may be made in a time zone, how long a contact's phone rings, how many tries and how far apart.
  2. Open Contacts and Add a list: a CSV file with a header row and a column called number (or phone); name and any other columns are shown to the agent in preview. Duplicate and malformed numbers are skipped.
  3. Record the message (in the campaign): who is calling and why, and "press 9 if you do not want these calls". It plays to a person answered when no agent is free, and, if you choose, after an answering machine's greeting.
  4. Start it. It calls only within its hours, and stops calling when it is paused or nothing is due.

People and machines. BitVoice listens to the first seconds after an answer: a long, unbroken greeting is an answering machine; a short "hello?" and a pause is a person. A machine can be hung up on (and tried again), left the message, or passed to an agent like anyone else. When in doubt, it takes the answer for a person.

Abandoned calls. A person answered when no agent is free in two seconds hears the message and counts as abandoned. With power and predictive dialling, if the share of abandoned calls over the last hundred answers goes over the campaign's limit (3% unless you change it, the US rule), the campaign dials one call per free agent until it is back under. The campaign shows its abandon rate, calls ringing and free agents live.

Do-not-call. No campaign calls a number on the do-not-call list, whatever list it came in on; anyone who presses 9 during the message is added at once. Add numbers by hand or through the API (POST /api/dnc). For the national registry (in the US, the FTC's National Do Not Call Registry: download the area codes you call as a flat file), choose the file under National registry and Import: every line with a number counts (212,5550100 as the FTC writes them, or one number a line), headings and broken lines are skipped and counted. With Replace the last import on, the previous download's numbers come off first, so a number that left the registry is callable again; numbers added by hand or by pressing 9 always stay. The registry must be refreshed at least every 31 days (US rules); the page counts the list and how much of it came from the registry. The API is POST /api/dnc/import?replace=1 with the file as the body.

Chapter 19

Sounds: prompts, languages and hold music

In the web interface: /sounds

Sounds (chapter 19) holds everything BitVoice says or plays to callers, apart from greetings and menu prompts, which are recorded where they are used.

Prompts, in every language

A prompt is one thing BitVoice says: "Please enter your PIN", "Your place in line is", the digits it reads out. The dial-by-name directory, dial-in (DISA), wake-up calls and queue announcements speak with them. BitVoice has the words of every prompt in English, Spanish, French, German, Italian, Portuguese, Dutch and Polish; numbers are read digit by digit, which sounds the same way in each.

Hold music

Hold music is grouped in classes (Calm, Jazz, Sales offers…), each a list of tracks played one after another, from the start or shuffled. Upload tracks of up to fifteen minutes in any format the browser reads; MP3 and WAV files can also be sent straight to the API (PUT /api/music/{class}/{name}), and BitVoice decodes MP3 itself (MPEG-1, 2 and 2.5 Layer III, with a decoder that gives the same samples as minimp3).

Internet radio. A class can play a stream instead of its tracks: enter an MP3 stream's address (Icecast, Shoutcast, most internet radio) under Internet radio. BitVoice connects when the first caller is put on hold with that class, plays the one stream to everyone waiting, and disconnects half a minute after the last one leaves. While the stream cannot be reached, the class's own tracks play (or the hold tone, without tracks), and the class shows why.

Who hears itWhich music
someone put on holdthe music chosen on the extension of the person holding, else the default
a parked callerthe music of the person who parked them, else the default
a caller waiting in a queuethe queue's music, else the default
a caller waiting for a conference leaderthe default

Default for everyone can be the hold tone, so nothing changes until you choose music. Choosing the hold tone on a queue or extension keeps the tone there.

Chapter 21

Dial-by-name directory

In the web interface: /directories

A dial-by-name directory (chapter 21) lets callers reach someone without knowing their number: they spell the first letters of the name on the keypad (2 for ABC, 3 for DEF, up to 9 for WXYZ) and are put through.

  1. Add directory, name it, and give it a number (411, say) or leave the number empty and use it as a menu option.
  2. Choose what callers spell: the last name (the usual), the first name, or either.
  3. Choose who is listed, or nobody to list everyone with a phone.

Callers hear "Please enter the first three letters of the person's name". One match is put through at once. Several are read out, eight at a time: each person's name, then "to call this person, press 1", 2 and so on, with 9 for more names. No match: "No one matches", and they try again (three tries).

Spoken names: record each person's name on their extension (Spoken name: record in the browser or upload a file), and the directory says it; until then it reads out the extension number. The directory's own words come from the directory prompts in Sounds (chapter 19), in its language.

Chapter 22

Dial-in (DISA)

In the web interface: /dial-in

A dial-in (chapter 22) (DISA, "direct inward system access") lets someone call in from outside, prove who they are, and call out again through the office: the call goes out with the office's caller ID, its routes and its rates, as if they were at their desk.

  1. Add dial-in, and set a PIN (4 to 10 digits), the numbers allowed to use it (Only from these numbers), or both. One of the two is required.
  2. Choose the extension the calls are made as: its outside-call permission, caller ID and outgoing routes apply. It must be allowed outside calls.
  3. Give it a number to dial inside, and send a phone number to it on Call routing (chapter 8) (choose the dial-in as the destination).

Callers hear "Please enter your PIN, then press hash", then "Please enter the number to call, then press hash", and are put through. The words come from the dial-in prompts in Sounds (chapter 19).

Chapter 23

Voice bots (AudioSocket)

In the web interface: /voice-bots

A voice bot (chapter 23) is a program of your own (an AI agent, a speech-recognition IVR, a recorder) that takes calls over AudioSocket, the simple protocol Asterisk uses: BitVoice answers the call, opens a TCP connection to the bot, and sends the call's UUID, then the caller's sound as 20 ms frames of 8 kHz 16-bit linear audio and each key pressed; whatever sound the bot sends back is played to the caller. Bots and speech-service connectors written for Asterisk's AudioSocket work with BitVoice unchanged.

  1. Add voice bot: its name, the bot's address (10.0.0.9:9092) and, optionally, a number to dial it.
  2. Choose where the caller goes if the bot cannot take the call, or breaks off (a person, a queue, voicemail): required, so no caller is ever dropped because a bot is down.
  3. Send calls to it from Call routing (chapter 8), a menu option, a schedule or a toggle.

When the bot sends an AudioSocket hang-up, the call ends; when the caller hangs up, the bot is sent one. A bot that cannot be reached within three seconds, or whose connection breaks without a hang-up, hands the caller to the fallback, and the failure is logged.

To bring a program into a call already in progress (a listening transcriber, an assistant that whispers to no one), use ARI's external media: see Asterisk compatibility (chapter 68).

Chapter 24

Day/night toggles

In the web interface: /toggles

A day/night toggle (chapter 24) is a switch for a call flow (FreePBX calls it call flow control). Calls sent to it go to its normal destination, or to the other one while someone has switched it over: the office closes early for a storm, someone dials *281 on the way out, and calls go to voicemail until it is switched back in the morning. It stays as it was left, across restarts.

  1. Add toggle, give it a code (1 to 3 digits: dialled after *28) and choose where calls go normally and when switched over. Either side may be a schedule, so a toggle can sit in front of the opening hours and override them.
  2. Choose who may switch it from a phone (nobody chosen lets any extension).
  3. Send calls to it from Call routing (chapter 8), a menu option or a schedule, like any other destination.

Switch it by dialling *28 and its code (a rising tone: switched over; a falling tone: back to normal), with the switch beside it on the Toggles page, or through the API (POST /api/toggles/{id}/state). A busy lamp key watching *281 is lit while that toggle is switched over, so the person who closes up can see it from their desk. The toggle code itself is on Feature codes (chapter 31).

Chapter 25

Schedules

In the web interface: /schedules

A schedule sends calls one way when you are open and another when you are closed. Point an incoming route at a schedule, and the schedule at the menu (open) and voicemail (closed).

Mon9–17Tue9–17Wed9–17ThuholidayFri9–17SatSunOpen: receptionClosed: voicemailTimes are in the system time zone; a holiday closes the whole day.
Figure 15. A schedule: open hours, holidays, and where calls go in each

Open hours

Each line of hours is a set of days and a time from and to. Several lines are allowed: Monday to Friday 9:00 to 17:00, and Saturday 10:00 to 13:00. Hours may cross midnight (22:00 to 06:00) for night shifts.

Holidays

Holidays count as closed all day, whatever the hours say. Add each date with a name; the name is shown on Call flow (chapter 15) when you try a call on that day.

Time zone

The time zone is the one in Settings. When the clocks change, schedules follow the local time.

Chapter 26

Scripts (JavaScript and Lua)

In the web interface: /scripts

A script decides where a call goes when menus, schedules and groups are not enough: callers from one area to one office, VIP numbers straight to a person, a decision from your own data. Or, set to Runs the whole call, it answers the call and runs it, as an Asterisk dialplan or AGI script would: prompts and speech, keys, recordings, ringing people, handing on (below). Scripts are written in JavaScript or Lua on Scripts (chapter 26).

A callfrom, to, timefunction route(call) { if (vip(call.from)) return queue('700') }Its answerFallbackon error or after 200 msScripts can never place calls, reach the network or the disk: they only choose.
Figure 16. A routing script: code decides, a fallback is always there

Safe by design

What a script sees

call has:

FieldWhat it is
from, fromNamethe caller's number and name
tothe number dialled
directioninbound or internal
trunkthe trunk it came in on
weekday, hour, minutethe time now (0 is Sunday)
dateYYYY-MM-DD

What it returns

A destination, {type, target}: type is extension, ringgroup, queue, menu, schedule, voicemail or hangup, and target is its number. Returning nothing uses the fallback. log("text") writes to the script's run list.

JavaScript

if (call.from.startsWith("212")) {
  log("New York caller")
  return { type: "ringgroup", target: "600" }
}
if (call.weekday === 0 || call.weekday === 6) return { type: "voicemail", target: "100" }

Lua

if string.sub(call.from, 1, 3) == "212" then
  log("New York caller")
  return { type = "ringgroup", target = "600" }
end
if call.weekday == 0 or call.weekday == 6 then
  return { type = "voicemail", target = "100" }
end

Using a script

Point an incoming route, a menu key or a schedule at the script, as at any destination. Test runs it with a call you describe, without placing one; the run list shows each real run with its decision, time taken and any error. The call flow (chapter 15) runs scripts too when you try a call.

Scripts that run the whole call

Choose Runs the whole call. The script then answers the call and goes from top to bottom, each step waiting until it is done:

StepWhat it does
play(name)plays a prompt from Sounds (chapter 19) in the caller's language (goodbye, digit-5...), digits:1234, or a tone: beep, confirm, error, off, hold. A prompt not recorded yet is a beep.
say(text)speaks the words with the speech service in Settings, AI (a beep without one)
collect({max, timeout, interDigit, end, say, prompt})gathers keys: at most max (32), waiting timeout seconds for the first (5) and interDigit for each next (3), until end (#). say or prompt asks first. Returns the keys, "" when none.
record({box, seconds, beep})records a message into an extension's mailbox, until # or the time; returns its seconds
wait(seconds)waits, returning a key pressed
dial(destination, ringSeconds)rings it with the caller hearing ringback. Answered: they talk and the script is done (true). Not answered: false, and the script carries on.
transfer(destination)hands the call on; the script is done
hangup()ends the call
log(text)writes to the run list

A destination is a number (an extension, ring group or queue here, else an outside number through the outbound routes; never an emergency number) or {type, target} as above. A key pressed during a sound stops it; play and say return it and the next collect starts with it. Returning a destination sends the call there.

const k = collect({ max: 1, timeout: 5, say: "Press 1 for sales, 2 for support." })
if (k === "1") return { type: "ringgroup", target: "600" }
if (k === "2") {
  if (dial("101", 20)) return
  say("Nobody is free. Leave a message after the tone.")
  record({ box: "101" })
  hangup()
}

Lua has the same steps (collect{max = 1}). Give the script a Number to dial it to call it from an extension.

Its limits keep the call safe: the script's own code may run at most a quarter of a second between two steps; a call takes at most 1,000 steps; and the whole script stops after its Longest run (10 minutes unless you say, 60 at most). When it fails, is stopped, or ends without hanging up or handing the call on, the call goes to its fallback; a caller who hangs up stops it at once. Try it runs the script with the keys you say the caller presses and lists each step, with no call placed.

Chapter 27

AI receptionist, voicemail triage and asking

In the web interface: /receptionists

AI features use the AI service set in Settings (chapter 14): an OpenAI-compatible service (OpenRouter by default) or one you run yourself. What they need is sent there, so choose a service you trust with calls; for a 911 centre, its own government cloud counts as local.

a callerAI receptionist"I’m the automated assistant"Answers a questionfrom approved factsTakes a messageor books a callbackHands over0, "a person", or a faultA personIt never stands between a caller and a person: any failure goes to the person destination.
Figure 17. The AI receptionist: answers, helps, and always hands over to a person

AI receptionist

Choose a receptionist as where calls go: a route, a menu option or an extension's If nobody answers. It says it is automated, answers only from Approved information, takes a message, books a callback (see Callbacks (chapter 29)), or transfers to A person is. Pressing 0 or asking for a person always reaches someone, and so does any problem with the AI service or the speech model: callers are never stuck with it.

Models

Model does the text work: summaries, the receptionist's replies and asking in plain words. Turning speech into text needs a model that takes audio; set it as Speech-to-text model (for example google/gemini-2.5-flash on OpenRouter) to use a text-only model for the rest, such as meta-llama/llama-3.3-70b-instruct.

Voicemail triage

With Transcribe and summarise voicemail on, each message is also marked urgent, normal or low priority, with its kind (sales, support, billing...). Urgent messages raise an alert on every administrator's screen.

Ask in plain words

On Changes (chapter 59), describe a change ("send sales calls to voicemail after 5 pm"). The AI proposes it, BitVoice checks it like any other change and shows exactly what would change. Nothing changes until you press Apply, and it becomes a revision you can restore. Passwords are never sent to the AI.

Chapter 28

Voicemail

In the web interface: /voicemail

Each extension can have a mailbox. Callers who are not answered hear its greeting and leave a message; the person hears it on their phone, reads it on the screen, or gets it by email.

not answeredGreetingyours, or a beepMessageup to 3 minutesMessage light on the phoneEmail with the sound fileTranscript, summary, urgencyDial *97 to listen from any phone, or use the Voicemail page or the staff portal.
Figure 18. Voicemail: from a missed call to a message you can read

Switching it on

On the extension, switch on Voicemail. If nobody answers is then set to the mailbox. Give it a PIN (4 to 10 digits): it opens the mailbox from another phone, and signs the person in to the staff portal and at hot desks.

SettingWhat it does
Longest message10 to 900 seconds (180 by default)
Email new messagesto the extension's email address, with the message attached
Greetingrecorded in the browser, uploaded, or recorded from the phone; without one, callers hear a beep

Listening

With AI

With Transcribe and summarise voicemail on (Settings, AI), each message is written out, summarised in a line, and marked urgent, normal or low priority with its kind (sales, support, billing). Urgent messages raise an alert on every administrator's screen. See AI (chapter 27).

Sound clean-up

Sound clean-up (Settings) removes steady background noise and evens out levels as messages are saved, so a message from a car or a busy street is easier to hear.

Chapter 29

Callbacks

In the web interface: /callbacks

People who asked to be rung back. An AI receptionist books one when a caller asks: it collects their name, the number to call (offering the one they are calling from), a good time and what it is about, reads them back, and books it only when the caller agrees. It never promises an exact time. Administrators can also add callbacks by hand.

AI receptionistor by handCallbackname, number, time, whyRing backyour phone firstIt never promises an exact time.
Figure 19. Callbacks: booked by the receptionist, rung back by a person

A new callback shows an alert on every open screen, and is emailed to the owner of the receptionist's Take messages for mailbox when that extension has an email address and email is set up in Settings.

To ring back, choose your extension and press Ring back: your phone rings first, and when you pick up BitVoice calls the number for you, with your normal routes and caller ID. Then add a note if you like and press Done (or Cancel it). Finished callbacks are kept below the open ones and can be opened again.

Part 3

Everyday calling

What people do on their phones every day, and what they set for themselves: forwarding, follow-me, pickup, conference rooms, paging, hot desks, faxes and texts.

Chapter 31

Feature codes, forwarding and speed dials

In the web interface: /codes

Feature codes are what people dial on their phones to change their own settings and reach features. They work on every phone, desk phone or softphone, with nothing set up on the phone itself. A rising tone means done; a falling tone means refused.

The codes at a glance

CodeWhat it does
*72forward every call (then the number and #, or the number straight after: *722125550199)
*73stop forwarding every call
*90 / *91forward when on a call / stop
*52 / *53forward when not answered / stop
*78 / *79do not disturb on / off
*76switch do not disturb (rising tone: now on)
*21switch follow-me on and off
*8answer a call ringing in your pickup group
** and an extensionanswer the call ringing that extension
*80 and an extensionintercom: that phone answers on its speaker
*0 and a codea speed dial
*62wake-up call: hear it, book one (four digits, such as 0630) or cancel it (star)
*68 and a digitroom status, for housekeeping in hotels
*28 and a toggle's codeswitch a day/night toggle (chapter 24) over, or back
*43the echo test
*97your voicemail
70park a call (transfer it here); 71 to 79 pick it up
*45 / *46queue agents: log in or out / pause or resume
*33 / *34sign in / out at a hot desk
*7 / *8 during a callpause and resume the recording (card payments)

Forwarding

a call to 101Every call*72 · cancel *73When on a call*90 · cancel *91When not answered*52 · cancel *53Another extensionits own settings applyAn outside numberthrough outgoing routesA group, queue or room
Figure 21. Forwarding: every call, when busy, when not answered

Forwarding to another extension uses that extension's own settings (its voicemail, its follow-me), up to four hops so two people forwarding to each other cannot loop. Forwarding to an outside number goes through the outgoing routes, as if the person dialled it, and needs the extension to be allowed outside calls.

Forwarding is live state, not configuration: setting it makes no revision, and it is kept across restarts. Extensions (chapter 3) and the staff portal show and change it too.

Do not disturb

*78 on, *79 off, *76 switches. With do not disturb on, calls go to voicemail, or to the extension's no-answer destination. Do not disturb set by hand wins over the calendar (Calendars (chapter 38)). Emergency call-backs still ring.

Follow-me

desk, 25 smobile, 20 sPress 1 to take the callso the mobile's voicemail never doespressed 1Connectedno 1 in 15 sVoicemail
Figure 22. Follow-me: the desk first, then the mobile, then voicemail

*21 switches follow-me on and off, for extensions that have follow-me numbers set (on the extension, or in the staff portal). The desk rings first for its ring time, then the follow-me numbers, one after another or all together. On an outside number with press 1 on, the person hears a tone and presses 1 to take the call; a voicemail or a silence never does, and after 15 seconds the call moves on.

Answering someone else's call

101 rings102 dials *8takes the callpickup group "Front office"** then the extensionanswers that one extension's call*8answers the oldest in your group
Figure 23. Call pickup: answer a colleague's ringing phone

Intercom

100 dials *80101auto-answer101 answers itselfAn extension can refuse intercomthen the call rings as usual
Figure 24. Intercom: the called phone answers on its speaker

*80 and an extension calls it with auto-answer: its phone answers on the speaker, and both sides talk. Yealink, Grandstream and Snom read BitVoice's Call-Info header, Poly reads Alert-Info; some phones need intercom allowed in their own settings. An extension can refuse intercom; then the call rings as usual. Door stations never take intercom.

Speed dials

*0 and a code dials a saved number: *05. The company's speed dials are on this page; each person can have their own on their extension or in the staff portal, and theirs win over the company's with the same code. Codes are 1 to 3 digits.

Changing the codes

Every code can be changed on Feature codes (chapter 31), or switched off with the word off. Two features cannot share a code, and no code may be an extension's or a group's number: BitVoice says which one clashes. The echo, voicemail and park numbers are in Settings (chapter 14).

Chapter 32

The staff portal

The staff portal lets everyone look after their own calls without an administrator: do not disturb, forwarding, follow-me, speed dials, voicemail and its greeting, their PIN, and a list of their own calls. It is at #/me on this server's address, and linked from the sign-in page.

Your phoneExtension101Voicemail PIN••••Sign inDo not disturbForwardingFollow-meSpeed dialsVoicemail and greetingYour calls
Figure 25. The staff portal: everyone looks after their own calls

Signing in

People sign in with their extension number and their voicemail PIN: the same PIN that opens their voicemail from a phone and signs them in at hot desks. An extension without a PIN cannot sign in; an administrator sets one on the extension.

Repeated wrong tries from one address lock it out for ten minutes. A portal session reaches only the person's own settings: never another extension, the configuration or anyone's recordings.

What people can do

TabWhat is there
Where calls godo not disturb; forwarding of every call, when busy and when not answered; follow-me numbers; own speed dials
Voicemailmessages to play and delete, with transcripts and summaries when AI is on; record or upload the greeting
Your callsthe person's own calls, newest first, without recordings
PINchange the PIN, giving the current one

Forwarding and do not disturb set here are the same as those set from the phone with feature codes (Feature codes (chapter 31)): whichever was set last is in force. Follow-me numbers and speed dials are part of the extension's configuration, so changing them makes a revision on Changes (chapter 59), recorded as the person's own.

Chat and presence

The portal's Chat tab lists colleagues with how they are right now: available, on a call, ringing, away (do not disturb, a meeting or time off from their calendar, with the reason) or offline (no phone connected), and the status they typed ("At lunch, back at 2"). Choose someone to message them; messages arrive at once, and a number beside a name counts the unread ones. Team rooms (Settings, Staff chat) are conversations for a group, or for everyone when a room lists no members.

Messages are only ever seen by the people in the conversation: administrators manage the rooms, never read them. Settings, Staff chat switches chat off, and sets how long messages are kept (0 keeps the newest thousand of each conversation).

Chapter 33

Conference rooms

In the web interface: /conferences

A conference room is a number people dial to all talk together. Staff dial it from their desks; outside callers reach it through an incoming route or a menu option that points at the room.

Room500violet: leader · grey: mutedDial 500, enter the PIN and #three wrong PINs and the call endsLeader PINjoins as a leader; 2 locks the roomWait for the leaderothers hear hold music until then
Figure 26. A conference room: PIN, leaders, and who is talking

Setting up a room

  1. Open Conference rooms (chapter 33) and press Add conference room.
  2. Give it a number (any free number, 500 by default) and a name.
  3. Optionally set a PIN. Callers hear a tone, enter the PIN and press #. Three wrong PINs and the call ends.
  4. Optionally set a leader PIN, different from the PIN. Whoever enters it joins as a leader.
  5. To let outside callers in, point an incoming route (or a menu key) at the room.

Choices

ChoiceWhat it does
Wait for the leadereveryone else hears the hold tone until a leader joins; when the last leader leaves, the room closes and everyone is hung up. Needs a leader PIN.
Members join mutedfor briefings and lectures: leaders talk, members listen. A member presses 1 to ask to speak, and a leader unmutes them.
Record the roomthe whole room is kept as one recording in Call history (chapter 46), unless recording is off for the whole system
Tones when people join and leaveon by default
Most people at once50 by default, up to 200

Keys during a call

While a room is in use

The page shows each room in use: who is in, who is talking (the green light), who is muted, who has asked to speak, and who is still waiting for the leader. An administrator can mute or unmute anyone, remove someone, and lock or unlock the room.

Everyone in a room hears everyone else who is not muted, mixed by BitVoice; each person's phone can use its own codec. A call record is kept for each person's call, and one for the room itself with its length and recording.

HD audio

Switch on HD audio in a room (new rooms have it on) and it is mixed at 16 kHz instead of 8: people on wideband phones (G.722, Opus, the browser phone) hear each other in HD, with the crispness of a modern call, while people on ordinary phones (G.711, mobiles through a provider) hear the same room as usual. The live view marks the room and each member who is in HD. HD needs G.722 among the codecs the phones use (it is first in the system's list, Settings, Codecs). Recordings of the room stay in telephone quality.

Video rooms

Set Video on a room and video phones (and softphones) that join it send their camera and see one picture, switched as people talk, as in Asterisk's ConfBridge:

BitVoice switches the pictures without decoding them, so it costs next to nothing, and it asks each new picture's phone for a full frame (RTCP PLI and FIR, and the SIP INFO picture-fast-update most desk phones answer) so the switch shows at once. Every member's video uses the room's video codec (H.264 unless you choose VP8); a phone without it joins with sound only. Each viewer gets one steady stream (one source, its own payload type), whoever is on screen. The live view marks who has video and who is on screen.

A grid is made differently: BitVoice gives every picture to ffmpeg on the server, which decodes them, places them in a 1280 by 720 picture at 15 frames a second, and encodes that once for everyone. Install ffmpeg (Settings, Video conversion, says whether it is found); without it a grid room follows the speaker instead, and the room's screen says so. Each picture costs processor time: on a small server, keep grids to a few rooms at once. Only members whose camera is sending are shown: someone joining without video, or whose camera stops, leaves the grid (it never freezes on a still camera), and the grid is remade within a couple of seconds when that changes, with a short pause in the picture. The tenth member and later are heard but not shown. The live view marks the grid's size and who is in the grid.

Chapter 34

Paging and overhead speakers

In the web interface: /paging

Paging speaks through many phones at once: dial a paging number, and every phone in the group answers on its speaker by itself. Use it for announcements to a warehouse, a school, a shop floor.

Setting up a paging group

  1. On Paging (chapter 34) press Add paging group and give it a number (800 by default) and a name.
  2. Choose the phones. Overhead speakers set up as extensions (kind Overhead speaker) can be members too.
  3. Optionally, a multicast address and port.

Multicast

Multicast also sends the page to a multicast address and port (239.0.1.10:5000), as G.711 µ-law, which overhead speakers and many desk phones can listen to without a call each. A group may have only a multicast address. It works on one network: routers do not pass multicast on unless they are set up to.

Paging and intercom

PagingIntercom
Who hearseveryone in the groupone extension
Talk backno, one wayyes, both ways
Howdial the group's number*80 and the extension

Phones that do not answer a page by themselves within a few seconds are left out, so one phone without auto-answer never holds a page up. Some phones need auto-answer (intercom) allowed in their own settings.

Chapter 35

Hot desking

In the web interface: /phones

A hot desk is a shared phone that becomes whoever signs in at it: for offices where people do not have fixed desks. Make one by switching on Hot desk in the extension the phone is set up as (the desk's own extension, such as 900 Desk 3).

Signing in and out

  1. At the phone, dial *33 and wait for the tone.
  2. Enter your extension and #, and wait for the tone.
  3. Enter your voicemail PIN and #. A rising tone means you are signed in; a falling tone means it was refused.

From then on, calls to your extension ring this desk as well as your other phones, and calls you make from it show your number and name and count as yours on Costs. Signing in at another desk moves you there. *34 signs you out. Five wrong tries lock the desk for ten minutes.

Managing hot desks

On Phones (chapter 4), Hot desks shows who is signed in where; administrators can sign someone in (without their PIN) or out. The codes, and a time each day when everyone is signed out, are in Settings. Sign-ins are kept across restarts.

Chapter 36

Hotel and wake-up calls

In the web interface: /hotel

Wake-up calls

Anyone can book a wake-up call: guests, night shifts, people on call. From their own phone they dial *62: BitVoice says the one set (if any), then they enter the time as four digits (0630), or press star to cancel it. On Hotel (chapter 36) an administrator books one for any extension, once or every day.

At the time, the phone rings with the system's name; answered, it hears "Good morning. This is your wake-up call." (the wake-up prompt in Sounds (chapter 19), in the guest's or extension's language). Unanswered, it is tried again (3 tries, 5 minutes apart, both set under Settings on the page), and after the last the reception extension can be rung. With several servers, only one makes wake-up calls.

Guest rooms

Switch on Guest room on the extension of each room's phone. On Hotel each room shows its guest, wake-up call and room status, with Check in and Check out buttons.

The hotel system (PMS)

Chapter 37

Contacts on every phone

In the web interface: /contacts

Contacts is the company directory: the suppliers, clients and other offices people call. Every phone lists it beside the extensions, and when one of these numbers rings in, phones and the caller card show the contact's name (when the provider sent none). A number matches however it is written: +1 212 555 0100 and 2125550100 are the same line.

Add contactImport CSVContactsnames and numbersthe phone directory+1 212 555 0100 and 2125550100 are the same line.
Figure 27. Contacts: one directory on every phone

Adding contacts

Add contact for one at a time, with as many numbers (work, mobile, home, other) as they have. Import takes a spreadsheet saved as CSV whose first row names the columns: name, company, work (or phone), mobile, home, other, email, notes. BitVoice checks the whole file first and says which lines are wrong; a contact with the same name as one there is updated rather than added twice, and Replace every contact starts the list afresh. Export downloads the list as CSV.

On desk phones

Phones set up by Phones (chapter 4) (provisioning) get the directory with no more setup:

In the browser phone

Contacts under the keypad finds a name or number and puts it ready to call.

Chapter 38

Calendars and do not disturb

In the web interface: /extensions

An extension can follow its person's calendar: during meetings and time off, its calls go to voicemail, or are forwarded (to another extension, or a mobile), instead of ringing a phone nobody will answer. Ring groups ring the others meanwhile, and in queues the agent shows as Away.

9:00 Team meeting12:00 FreeFriday: out of officeevery 5 minA call to 101during the meetingVoicemailor forwardedDo not disturb now wins over the calendar.
Figure 28. Following a calendar: no ringing in meetings

In the extension, Calendar and do not disturb, paste the calendar's private address:

Check reads it at once and lists the next busy times. BitVoice reads each calendar every five minutes. Time off (all-day events, and Outlook's "out of office") always counts; meetings count when Meetings count as busy is on; events marked free never count, nor do cancelled ones. Recurring meetings, with skipped and moved occurrences, are understood. If a calendar cannot be read, Health says so.

Do not disturb now stops the extension ringing until switched off, whatever the calendar says. The extensions list shows who is away and until when.

The private address works like a password: anyone with it can read that calendar, so it is kept with the other secrets.

Chapter 39

Mobile apps

The BitVoice apps for iPhone and Android make a mobile phone one of an extension's phones. It rings like a desk phone, on the phone's own call screen, even when the app is closed.

A call to 101BitVoicePush relayApple and Googlerings like a callthe app connects backPaired once by QR code; the code works once, for ten minutes.
Figure 29. The mobile apps: woken by a push, rung like a desk phone

Setting up push

A closed app is woken for calls by a push message. In Settings (chapter 14), Mobile apps, choose one:

PushWhat you need
Push relayBioDream's relay (with hosting or support) or your own bvpush: its Relay address, Key ID and Secret
Own appsyour own builds: for Apple, the Team ID, Bundle ID, Key ID and Key (.p8); for Google, the Firebase service account (JSON)

Set Address the apps use to this server's https address as it is reached from anywhere, not only the office.

Pairing a phone

  1. Open the extension and press Add a phone.
  2. Scan the QR code in the app. The code works once, for ten minutes.

When a call comes in

BitVoice wakes the app; it connects, rings on the phone's own call screen, and is answered like any other phone of the extension: ring groups and queues ring it with the extension's other phones. The extension's page lists its paired phones, whether each Can be woken for calls, when it was last seen and last woken, and any push problem. Unpair stops a phone ringing at once, for a lost phone.

Chapter 40

Video calls

In the web interface: /settings

When both phones in a call send video (video desk phones, softphones, video doorbells), the picture passes between them through BitVoice. Nothing to set up: it is on unless Settings → Video calls is switched off.

Video phoneH.264SRTPBitVoice relaysrenumbered if neededSoftphoneH.264The phones never learn each other’s addresses.
Figure 30. Video calls: relayed as they are

Converting video

Phones and apps that share a video codec (most use H.264) get each other's video as it is. When two parties have none in common (a desk phone with only H.264 and a browser with only VP8), switch on Convert video between H.264 and VP8 in Settings: BitVoice then offers both codecs, answers each party in its own, and converts each way with ffmpeg, which must be installed on the server (apt install ffmpeg, brew install ffmpeg; or give its path). Conversion costs about a processor core per call and adds a little delay, so it is off by default and used only when needed. Settings says whether ffmpeg was found.

Chapter 41

Fax: sending and receiving, fax machines and analogue phones

In the web interface: /faxes

Fax machines, analogue phones, door phones and old lines connect through a SIP gateway (or a telephony card in the BitVoice computer: see Telephony cards (chapter 6)): an ATA (Grandstream HT series, for one or two analogue phones or a fax), or a bigger gateway (Patton SmartNode, AudioCodes MediaPack and Mediant) for many analogue ports, an ISDN line (BRI/PRI) or old analogue lines (FXO). Each port registers to BitVoice as an extension, like a phone.

Fax machineon an adapter portCarrierT.38 or G.711Fax numberreceives and sendsPDF on the Faxes pageEmailed to a listEmail to fax: send by emailPages, size (letter or A4) and the far station’s ID are kept with each fax.
Figure 31. Fax: machines, email and PDFs

Receiving faxes without a fax machine. On Faxes, add a fax number (300, say), with the email addresses each fax goes to. Then in Call routing (chapter 8) send a phone number's calls to it. BitVoice answers as a fax machine, switches the call to T.38 and takes the fax; each fax becomes a PDF, kept on Faxes (View, PDF) and emailed. A fax that breaks off part way keeps the pages that arrived and says so. This needs a provider that supports T.38 (most do); a fax sent as sound cannot be received this way.

Sending a fax. On Faxes, Send a fax: choose the fax number it goes from, type the number to send to, write a note if you like (it becomes the first page) and add documents. Text files and pictures (PNG, JPEG, GIF) work everywhere. PDF needs poppler on the server (apt install poppler-utils, apk add poppler-utils, brew install poppler); Word, Excel, OpenDocument and RTF need LibreOffice as well. The page says which the server can do. Every page gets a header line, as fax machines print it: the time, the fax number's name, its identity and the page count. Pages are US letter in North America and A4 elsewhere, from the country in Settings.

BitVoice calls the number over your outbound routes, as an extension would, and sends at the fastest rate the line carries (14,400 bit/s, slower if the line is poor). Faxes from one fax number go one at a time. A busy number, or one that does not answer, is tried again five minutes later, three times in all. Sent faxes are listed with the received ones: Sent, Waiting to send, Failed (with Try again), or Part sent when the line broke after some pages.

Email to fax. Below the list, set up a mailbox for BitVoice to read (IMAP over TLS, port 993; for Google and Microsoft mailboxes use an app password), then Test and Save. Anyone allowed to send writes to that mailbox with the fax number in the subject (Fax 212 555 0199), or to a plus address (fax+2125550199@example.com) if the mail server takes them. Attachments become the pages and the email's own words the cover note (the signature and quoted mail are left out). It goes from the fax number that lists the sender: its Email each fax to addresses may always send, and May also send faxes by email adds others (whole addresses, or @example.com for a domain). The sender gets an email when the fax has gone through, or why it could not.

Email is easy to forge, so BitVoice faxes a message only when your mail server found it really came from the sender's domain (DKIM, SPF or DMARC, in the Authentication-Results line it adds). Other messages are dropped without a reply. Switch Accept mail the sender's domain did not vouch for on only for a mailbox no outside mail can reach.

Fax machines on gateways. BitVoice carries fax over T.38, the fax standard for the internet: when the gateway hears a fax tone it switches the call to T.38, BitVoice asks the other side (your provider, or another gateway) to switch too, and passes the fax between them. If the other side cannot do T.38, the call stays on G.711 and the fax goes as sound, which works on a good network. Live calls show fax (T.38) while a fax is going through.

For reliable faxes:

Chapter 42

Inbox: web chat, WhatsApp and Messenger

In the web interface: /inbox

The Inbox (chapter 42) holds every written conversation in one list: the chat box on your website, WhatsApp, Facebook Messenger and texts (chapter 43). Anyone signed in to the web interface can answer; the first to reply takes the conversation (anyone can hand it on with Answered by), and Close puts it away until the person writes again. Unread conversations are counted, and the list refreshes by itself.

The chat box on your website

Under Channels, switch on Web chat, choose its title, colour and first line, and put the line it shows in your site's pages:

<script src="https://pbx.example.com:8443/webchat.js" async></script>

It draws a chat button in the corner of every page; visitors write (with their name if they like) and see your answers as they come. The conversation stays in their browser, so it carries on as they move between pages. List your sites under Only on these sites so the box runs nowhere else. Visitors must reach this server's address from the internet, with a certificate browsers trust (Let's Encrypt (chapter 14)). Ten new chats from one address in ten minutes is the most BitVoice takes.

WhatsApp

WhatsApp Business numbers on Meta's Cloud API. In Meta's developer site, make an app with WhatsApp, add your number, and make a system user with a permanent access token. In Channels, switch on WhatsApp and give the phone number ID and the business account ID (both from API setup), the access token and the app's app secret, then save. In the app's WhatsApp configuration, set the webhook: the callback address and verify token BitVoice shows, subscribed to *messages*.

WhatsApp lets you answer freely for 24 hours after the customer's last message; after that it accepts only message templates approved in WhatsApp Manager. The reply box then turns into a template picker: choose a template (it lists your account's templates, with their language and kind), fill in its values ({{1}}, {{2}} ...), check the preview, which is what the customer will read, and Send template. Templates the inbox cannot fill are listed greyed out with the reason: one with a picture, video or document header, a variable in its header or a button's link, named parameters, or a code button; and those not yet approved. Make templates in WhatsApp Manager; Meta reviews each one, usually within minutes.

Facebook Messenger

For a Facebook Page: in the Meta app, add Messenger, connect the page and make a page access token. In Channels, give the page ID, the page access token and the app secret; then set the webhook (the address and verify token shown), subscribed to *messages* and *messaging_postbacks*. Replies are allowed for 24 hours after the person's last message. From then until 7 days, Messenger takes replies written by a person (sent with Meta's *human agent* tag: the app needs Meta's Human Agent permission, asked for in App Review); the automatic greeting never goes then. After 7 days the inbox takes no reply until they write again.

Every webhook is checked with the app secret (Meta's signature) before BitVoice believes it, and a message Meta sends twice is kept once. Pictures, voice notes and other attachments show as what they are ("[image]"); open them in Meta's own apps.

Automatic greeting, when set, answers the first message of every new conversation at once.

Chapter 43

Business texting (SMS)

In the web interface: /texts

Send and receive text messages from your business numbers on Texts. Texts go through a texting provider. Built in: TextMagic, Twilio, SignalWire, Telnyx, Bandwidth, Vonage, Plivo, Flowroute and VoIP.ms, plus Your own webhook for any other service or a gateway of your own. Any number of provider accounts can be used at once: each number says which one carries it.

a customerTexting providerTextMagic, Twilio, …Texts pageone thread per numberTimelineDesk phonesUS numbers need 10DLC registration, guided on the Texts page.
Figure 32. Business texting: the same numbers, one conversation view

Setting up

  1. In the provider's portal, find the account's API details. The form asks for exactly what that provider calls them (Twilio: Account SID and auth token; Telnyx: an API key; Bandwidth: API user, password, account ID and messaging application ID; SignalWire: also your space address) and says where to find them.
  2. On Texts, Texting setup, add the provider with them, and save. BitVoice shows an address for received texts: set it in the provider as where received messages are sent (its callback, webhook or message URL). For VoIP.ms, add ?from={FROM}&to={TO}&message={MESSAGE}&id={ID} to the end. Delivery receipts sent to the same address are ignored. BitVoice must be reachable from the internet there.
  3. Add each number you text from (with its country code), the provider that carries it, and the extensions to tell by email when a text comes in.

US 10DLC

US carriers block texts from ordinary business numbers that are not registered. Register your brand and then a campaign with your texting provider; the checklist on Texts tracks where they stand, and warns when your sample message lacks the opt-out words carriers expect.

Conversations

Each conversation shows who it is (from Contacts), unread texts, and the thread. Enter sends; the counter shows how many texts a long message takes. When someone replies STOP, nothing more can be sent to them from that number until they reply START. Received texts also appear as a notice in BitVoice.

Chapter 44

Transfer briefings

In the web interface: /settings

So a caller never has to repeat themselves: with Brief whoever a call is transferred to on (Settings, AI), when a call is transferred, BitVoice writes a two-sentence summary of the call so far (who is calling, what they want, anything already promised) for the person it goes to. It appears on their browser phone with the ringing call, on Live calls (chapter 45), and as a text on their desk phone's screen (for phones that show SIP messages).

agent 101transfersTwo sentenceswho, what, what was promised102 ringsShown with the callbrowser, Live calls, deskThe caller never has to say it all again.
Figure 33. Transfer briefings: the next person knows already

It works the same when the AI receptionist hands a caller to a person: the briefing comes from what the caller told the assistant.

It needs the AI service and a speech-to-text model (Settings, AI), and the call's audio so far (up to five minutes) is sent to that service to be written out. A summary takes a few seconds, so it may appear just after the phone starts ringing.

Part 4

Customers and insight

Knowing who called and how it went: the live calls and history, the customer timeline, CRMs, recordings and consent, quality, costs and caller ID reputation.

Chapter 45

Live calls

In the web interface: /calls

Live calls shows every call in progress, updated as it happens: who called whom, how long it has been going, its codecs and its quality.

Live call100 Front desk → +1 212 555 0199G.722 / G.711 · MOS 4.3 · 02:14endsCall recordwho and when, how long, answered byrecording and transcriptcost, quality per leg, why it ended
Figure 34. Live calls and history: every call, while it happens and after

What administrators can do

ActionWhat it does
Hang upends the call for both sides
Open the doorfor a call from a door station
Pause recordingfor a card number: the paused stretch is silent in the recording and marked in the history (Call recording (chapter 50))
Listenhear the call silently
Whispertalk to the agent only; the caller does not hear
Bargejoin the call; everyone hears you

To listen, whisper or barge, press Supervise, choose the phone to use under From phone and press Ring me: your phone rings, and when you answer you join the call. You can switch between listening, whispering and barging while you are in it.

What else shows

When a call ends, it moves to Call history (chapter 46).

Chapter 46

Call history

In the web interface: /history

Every finished call: who called whom, when, for how long and how it ended. Sort the columns, play recordings (a pause for card numbers is marked), and download the list as CSV. How long records are kept is set in Settings, Call recording; a legal hold (chapter 70) keeps them longer.

Live call100 Front desk → +1 212 555 0199G.722 / G.711 · MOS 4.3 · 02:14endsCall recordwho and when, how long, answered byrecording and transcriptcost, quality per leg, why it ended
Figure 35. Live calls and history: every call, while it happens and after

How it was routed

Under each call's result, How it was routed lists, in plain words and in order, what decided where the call went: the incoming route that took it, whether a schedule was open or closed and the time, a toggle's side, what a routing script chose (or that its fallback took the call), the keys pressed in a menu, who was away, who had no phone connected, who did not answer, the outbound route and trunks used (and a trunk the health judge moved behind the others), the toll-fraud guard's judgement, and, for a recorded call whose parties are under different consent rules, which rule applied.

Transcripts and search

With AI on and Transcribe recorded calls switched on (Settings, AI), every recorded call is written out, with a short summary and its action items: what someone agreed or was asked to do. Each side of the call is written out separately from the recording, so the transcript shows who said what, and when. The transcript button next to a recording opens it; administrators can also transcribe a single call, or transcribe one again.

Search what was said finds calls by words from their transcripts, summaries and action items. Only recorded calls are transcribed. A transcript is deleted with its recording, and reading or searching transcripts is noted in the audit log, like playing a recording.

Chapter 47

Customer timeline

In the web interface: /timeline

The customer timeline shows everything with one phone number over the last year, newest first, so whoever picks up knows the whole story.

Call answered by Front deskVoicemail: "please call back"Text: "after 3 is fine"Callback booked by the AI receptionistNote: prefers mornings+1 212 555 0199Lee, Acme Corp
Figure 36. One customer timeline: everything about a number in one place

What it shows

ItemWith
Callswho took them, how long, and with a transcript, its summary, the recording and the transcript
Voicemailstheir summaries
Textsboth ways
Callbacksasked for, and whether done
Notesthe team's own notes

A number matches however it is written: +1 212 555 0100 and 2125550100 are the same.

Opening it

From a caller card (Timeline), from Contacts, from an incoming call in Call history, from a text conversation, or type a number at the top of Timeline (chapter 47).

Notes

Administrators can Add a note for the team: it shows on the timeline for everyone, with who wrote it and when, and can be removed.

Chapter 48

CRM: caller cards and call logging

In the web interface: /settings

Connect a customer system in Settings (chapter 14), CRM. It works with any system that has a web address, without code written for each product.

+1 212 555 0100Caller cardLee · Acme CorpGET {number}Your CRMany web addressafter the call: who, how long, summaryAnswers are kept for five minutes.
Figure 37. CRM: a card while it rings, a log after it ends

Caller cards

While a call from outside rings, Live calls shows a card: who it is (from your CRM, or the extension's name), how often they have called in 90 days, any callback (chapter 29) they are waiting for, and the summary of their last transcribed call. The browser phone shows a shorter card to the person answering: who it is, past calls and waiting callbacks, but not other people's call summaries.

For the name, set Lookup address: BitVoice asks it (GET) with the caller's number in place of {number}, sending Lookup header with its value (a vault reference works), and expects JSON with name, company, url and notes; 404 means unknown. Answers are kept for five minutes. Open in CRM link puts a link to the caller on the card. Use Look it up to try a number before saving.

Call logging

Set Call log address and Signing secret, and every call is sent there as it ends (event call.ended), again with its summary, action items and transcript once transcribed (call.summarized), and each booked callback (callback.new). Each POST carries X-BitVoice-Event, X-BitVoice-Timestamp and X-BitVoice-Signature: sha256= followed by the HMAC-SHA256, with the secret, of the timestamp, a dot and the body. A failed delivery is tried four times over about a minute; if it still fails, Health says so. Send a test event checks the address and the secret.

Chapter 49

Call insight for supervisors

In the web interface: /quality

For contact centres: evidence about how calls went, for a supervisor to listen to, never an automatic score.

How it wentagent 62%caller 38%talked over: 3 · longest: 48 s · quiet: 22 s02:14 Went well05:40 Look at: a long hold07:02 Not answered09:15 Promised: a refund by FridayTo choose calls to listen to, not to rank people.
Figure 38. Call insight: evidence for a supervisor, never a score

In a call's Transcript, How it went shows, measured from the recording's sound alone: how much each side talked, each side's longest stretch, how often each started talking over the other, how long both spoke at once, and the quiet (a long silence is often a hold or dead air).

With Note how each transcribed call went on (Settings, AI), the AI also reads the transcript and says how the caller seemed at the start and the end, and lists up to six moments: Went well, Look at (talking over the caller, a long hold, an unclear answer), Not answered (a question the caller asked that got no answer) and Promised (something someone said they would do), each with the time and the words said, so you can go straight to it. An administrator can ask for it on any transcribed call with Look at this call.

On Call quality (chapter 49), Conversations, by who took them sums the transcribed calls of the period per person: their share of the talking, their longest stretch, how often they talked over the caller, quiet time, calls that ended with the caller upset, and the moments flagged. Use it to choose calls to listen to, not to rank people.

Coaching notes are your own words on a call, at the moment they are about: under How it went, write the Moment (1:05, or leave it empty for the start) and the Coaching note, and press Add note. Notes are listed in the order of the call with who wrote them and when; administrators write and remove them, viewers read them with the transcript, and adding or removing one is noted in the audit log. They go with the recording, so its retention and legal holds cover them too. Coaching notes on Call quality counts them per person.

Chapter 50

Call recording and card payments

Recording is set in Settings (chapter 14), Call recording: off, every call, or only the calls of extensions marked Record calls. Recordings play from Call history (chapter 46), and with AI on they are written out and summarised.

A call is answeredrecording is onConsent ruleby the other party’s regionAnnounce, then recordtwo-party consent regionsRecord with a beep every 15 sDo not record*7 pauses and *8 resumes the recording while a card number is read out
Figure 39. Recording with consent: announce, beep, or not at all

Telling people

Some places need everyone on a call to be told it is recorded: Announce, Beep and rules by region are in Recording consent (chapter 51).

Card payments (PCI DSS)

Card numbers must not be kept in recordings. Before a caller reads one out, the person on the extension presses *7; *8 resumes. Pause recording on Live calls (chapter 45) does the same. The paused stretch is silent in the recording and listed in the call history, so an auditor can see where and for how long.

Conference rooms

A room with Record the room on is kept as one recording of the whole room (Conference rooms (chapter 33)).

How long things are kept

Settings sets how many days recordings, call history and voicemail are kept; older ones are deleted within the hour. Anything under a legal hold (chapter 70) is kept whatever its age. The archive (chapter 69) can keep copies elsewhere.

Administrators and viewers can play recordings and read transcripts; only administrators can transcribe a call, or transcribe it again. Playing a recording or reading its transcript is noted in the audit log.

Chapter 52

Call quality

In the web interface: /quality

How calls sounded over the last day, week, month or 90 days, from the sound BitVoice itself received on each side of each call. Phones are grouped by their site (chapter 12) (or "no site"), and calls from outside by the provider's line they came in on.

Each calljitter, loss, delayMOS score1 bad · 4.4 bestBy site, carrierand hour of dayDiagnosis"loss on the office link 2–3 pm"
Figure 41. Call quality: from packets to a plain diagnosis

Each place shows its calls, its average score (MOS, out of 5: above 4 is good, under 3.6 sounds poor), the share of sound packets that never arrived, and jitter (uneven delay). Below that, BitVoice says what is wrong in plain words, for example "Packet loss on Head office's network: 3.2% of the sound never arrived, mostly between 14:00 and 16:00", with what to check. The bar chart shows the sound lost by hour of the day.

The diagnosis compares the two halves of the same calls: the sound from the site's phones and the sound from the provider the same calls went through. When the other half arrived clean, the loss is on this place's side, and it says so; when both halves lost sound, the place is not to blame alone and it points at what the calls share, this system's own internet link. If every place loses sound at once, the cause is likewise what they share. How this was worked out lists the reasons, step by step (the call-quality rulebook, see Security (chapter 58), "How BitVoice decides"). Places with fewer than three calls are not judged. Per-call quality is also in Call history (chapter 46) (the Quality column) and, while calls are live, on Live calls (chapter 45).

Chapter 53

Costs and budgets

In the web interface: /costs

BitVoice prices each call from what your provider charges, and shows the month's spend by department, person and trunk, with the most expensive calls.

A call out+44 20 …, 7 minTrunk rate+44: 0.02 a minuteCost0.14By personBy departmentBy trunkAlerts: a budget passed, or far more calls to one place than usual (toll fraud).
Figure 42. Costs: every call priced, budgets watched

Prices

On Trunks (chapter 7), open a trunk and its Call prices. Each price covers numbers that start with some digits, as the number is sent to the provider (digits only, so 44 for the UK, 1900 for US premium rate); the longest match wins, and a price with no digits covers every other number. Give the price per minute, any charge per answered call, the billing step (60 seconds for whole minutes, 6 or 1 for finer) and any minimum. Calls in, per minute is for toll-free numbers you pay to receive. What would it cost checks a number before anyone dials it. The currency is set on Costs.

A call's cost is fixed when it ends, with the prices of the time; changing a price does not change past calls. Costs says how many answered calls out had no price.

Departments and budgets

Give extensions a Department (in the extension). On Costs, add a budget for every call or for one department: an alert appears in BitVoice, and is emailed to the budget's address and the alert address, at 80% and again at 100% of the month.

The alarm

Calls out cost more than this in an hour raises an alarm when outgoing calls pass that amount within any hour. A sudden run of expensive calls is the usual sign of toll fraud (a stolen phone password): check Call history, then disable the extension or the trunk.

Chapter 54

Caller ID reputation and branded calls

In the web interface: /reputation

Phone companies run spam filters that can label a business number "Spam likely", or block it, and then hardly anyone answers. Caller ID reputation watches each number you call out from, from your own calls, and says in plain words how it is doing:

Numbers with fewer than 20 calls are shown as too few to judge.

Your outgoing numbers gives each number a name (sent as the caller's name), a reason for calling and a logo (an https:// image). On a trunk with Send branded caller ID on, the logo and reason go out as rich call data (RFC 9796 Call-Info); carriers that support branded calling show them on the called phone. Most phones show the name from the caller-name (CNAM) database instead, which your provider sets: ask them. Watch puts a warning on Health when a watched number starts to look labelled.

The page also says what to do when a number is labelled.

Chapter 55

Spam protection and STIR/SHAKEN

In the web interface: /settings

In the US and Canada, the provider a call starts with signs its caller ID (STIR/SHAKEN): A when it knows the caller may use the number, B when it knows the caller but not the number, C when it only passed the call on. Your provider either tells BitVoice its verdict (verstat) or passes the signed Identity header on, which BitVoice then checks itself: the signature, that it is under a minute old, and that it names the numbers of this call. The verdict shows as Verified, Partly verified, Unverified or Not verified on Live calls and in Call history.

A call inIdentity, verstatCheckedsignature, age, numbersVerified: ringsNot verified: rings as "Spam?"Failed or blocked: refusedwhat happens to each is set in Settings
Figure 43. Spam protection: the caller ID is checked before it rings

In Settings, Spam protection, choose what happens when a caller ID fails verification (ring, ring labelled, or refuse), when it is not verified at all, and when the number is withheld. A labelled call rings with Spam? (or your own label) before the caller's name. Blocked numbers are refused; an entry ending in * blocks a range (+1900* is every US premium-rate number). Always allowed numbers are never refused or labelled. In Call history, the block button beside a caller adds them to the list; refused calls are listed as Blocked.

Within an hour of an emergency call from any extension, no call is refused (blocked ones ring labelled instead), in case it is the emergency service calling back.

To check certificates against the STI authorities, paste their certificates under STI certificate authorities; without them, BitVoice checks that the call was signed with the certificate it names but not who issued that certificate.

Signing your own calls

Most providers sign their customers' calls themselves. If yours lets you sign (or you are a provider running BitVoice), switch on Sign caller ID on the trunk (Trunks (chapter 7)) and give it your STI certificate (from an STI certification authority, with your service provider code token) and its private key (P-256). Every call out through the trunk then carries a signed Identity header (ES256, as SHAKEN requires).

Part 5

Running BitVoice

Keeping it safe and running: administrators and sign-in, security, changes and updates, several servers, hosted organisations, codecs, Teams, importing, automation and the tools for finding faults.

Chapter 56

Administrators

In the web interface: /users

Administrators are the people who sign in to this web interface. Staff who only look after their own calls use the staff portal instead and need no account here (The staff portal (chapter 32)).

Roles

RoleCan
Administratorchange anything, play recordings, see every secret field's existence (never its value)
Viewersee everything, change nothing; secrets are hidden

A change of role, or of password, signs the person out everywhere at once.

Two-step sign-in

Each person turns on two-step sign-in for themselves: Set up shows a key for an authenticator app; entering the code it shows turns it on. From then on, sign-in asks for a code as well as the password. Turning it off needs the password.

Single sign-on

With single sign-on (Settings), people sign in with the organisation's account (Microsoft Entra, Google, Okta, any OpenID Connect provider), and an account is made for them the first time. See Single sign-on (chapter 57).

API tokens

Programs (Terraform, scripts) use API tokens instead of a password: made on this page, shown once, and revoked at any time. Each token is an administrator or a viewer.

Chapter 57

Single sign-on

Single sign-on lets people sign in to BitVoice with their work account, through any OpenID Connect provider: Microsoft Entra ID, Google, Okta, Keycloak and others. Leaving the organisation then removes their access here too.

browserIdentity providerEntra, Google, Okta, KeycloakBitVoicereads the groupsAdministratorViewerNot in an allowed group: refused, and noted in the audit log.
Figure 44. Single sign-on: the work account decides who gets in

Setting it up

In Settings (chapter 14), Single sign-on:

  1. Register an application with the provider, with the Redirect address shown here.
  2. Fill in for a provider sets the Issuer for the common ones; copy the Client ID and Client secret from the provider.
  3. Name the provider's Administrator groups and Viewer groups. Groups claim is where the provider puts them (groups unless set).
  4. Optionally change the Button text on the sign-in page.
  5. Switch on Use single sign-on.

How it works

Chapter 58

Security

In the web interface: /security

A phone system on the internet is attacked within hours: scanners try passwords on every SIP port, and a broken-into system runs up calls to premium numbers. BitVoice is built to stand up to that by default, in layers.

Trusted networks, bans after failed sign-insStrong SIP passwords, one per extensionTLS for SIP, SRTP for callsTwo-step sign-in, single sign-on, rolesAudit of every change, legal holdsLimits: outside calls, premium numbers, spend
Figure 45. Layers of protection

Against password guessing

Against fraud

The toll-fraud guard

Switch it on in Settings, Toll-fraud guard. Every call out of the country (by +, 00 or 011, and the places that share +1 with North America but are other countries, such as Jamaica, a classic toll-fraud destination) is then judged before it is placed:

SituationWhat it does
A call abroad to a country this extension called in the last 90 dayslets it through
A first call to that country in 90 dayslets it through and reports it
A first call there outside Business hours, or placed from outside (a dial-in, a forward)asks for the PIN asked for (with none chosen, refuses it)
More than Calls abroad in 10 minutes from one extensionrefuses it
A first call abroad while someone is guessing passwords (three failures in a row from one address, or a ban, in the last hour)refuses it
An emergency numberalways lets it through

Countries always allowed (calling codes, such as 44) and Exceptions (an extension excused until a day, for a trip) take away "first call" and "outside hours"; they never excuse many calls in a short time or an attack, because a stolen password looks approved too. If the call history cannot be read, the guard does not know whether a call is a first, and something not measured is never taken for safe: it asks for the PIN. Every judgement is listed on Security (chapter 58) with its reasons, and is on the call's record in Call history (chapter 46).

How BitVoice decides

BitVoice's judges (the toll-fraud guard, the trunk health judge, the call-quality diagnosis and the 911 caller location check) each follow a rulebook: facts that are measured, conclusions they support, the exceptions that overrule a conclusion, and the choices. How BitVoice decides, on Security (chapter 58), shows each rulebook. The rules the judges keep:

Encryption

Who can do what

Chapter 59

Changes, backups and import

In the web interface: /changes

Every saved change is a revision: numbered, with who made it, when, and a one-line summary. Nothing in the configuration is ever lost.

1setup2extensions3trunk4menu5restored 2restore revision 2: a new revision 5Compare any two side by side before restoring; nothing is lost.
Figure 46. Every change is a revision you can compare and undo

Comparing and restoring

Export and import

Changes made at the same time

Two administrators editing the same thing at once cannot overwrite each other: the second save is refused with a message to reload, and nothing is lost.

Chapter 60

Updates

In the web interface: /updates

Updating BitVoice is one click, and safe: it checks the new version, installs it beside the old one, and goes back on its own if the new one does not stay up.

Upload or fetchsigned releaseCheck signaturerefuse a bad oneStart new versioncalls hand overUp for a minute?then it is confirmedit crashed: back to the version before, automatically
Figure 47. Updates: install, check, and fall back on their own

Installing an update

  1. Download the new release and unpack it. Beside the program is its signature from BioDream: bitvoice.sig, or bitvoice.exe.sig on Windows.
  2. On Updates (chapter 60), upload the program and its .sig file.
  3. Press Install. By default BitVoice waits until no calls are in progress; you can also install at once.
  4. BitVoice restarts on the new version. With several servers, calls in progress are handed to another server and carry on.

Going back

The version you left is kept: Go back returns to it in one click. A new version that fails to start twice, or does not stay up for a minute, is replaced by the previous one by itself.

Signatures

Every release from v0.1.3 carries BioDream's release key. Such a build installs only programs signed with that key: an unsigned file, one signed by anyone else, or one changed by a single byte is refused with the signature does not match. The page says whether this build checks (Required) or not.

You runUpdates accepts
a release, v0.1.3 or lateronly programs signed by BioDream
v0.1.2 or earlier, or a build of your ownany program: with no key, a .sig file cannot be checked and is ignored
Chapter 61

Several servers as one phone system

In the web interface: /servers

Two or more BitVoice servers that share one PostgreSQL database work as one phone system:

Server AServer BPostgreSQLcalls crossA shared addressmoves to a running serverPhones register anywherecalls find themA server stopsits calls carry on elsewhere
Figure 48. Several servers as one phone system

Setting it up

  1. Move the first server's data into PostgreSQL: Settings, Database.
  2. Start each other server with the same database: bitvoice -database postgres://… (or the BITVOICE_DATABASE environment variable). It joins at once; Servers lists it.
  3. On Servers, check where each server is reached (its address and SIP port on the network the servers share), and give each a name. Servers that are each reached from the internet at an address of their own (cloud servers with public IPs, no shared address) get Its own public address too: providers and phones outside are told that one, so when a server takes over a call, the provider's sound follows it. Left empty, a server uses the public address in Settings.
  4. Tell phones how to find the servers (below).
  5. Provider lines (below).

How phones find the servers. Phones BitVoice sets up (Yealink, Polycom, Grandstream) are given another running server as their backup by themselves. For the others, Snom and phones set up by hand, use one of these on Servers:

Provider lines. In each trunk, Shared between servers says how:

When a server stops

Between servers. The servers reach each other at their SIP port over TCP, or TLS when they have a certificate (each accepts only the certificate the other published, and the sound between them is then encrypted with SRTP), and send sound to each other's media ports (UDP, the range in Settings). Calls between servers are signed with a secret they share in the database, and only accepted from a running member at its own address. A firewall between them must let those ports through.

Try it first: the lab. BitVoice comes with a lab that runs two servers, their database and test phones on one computer with Docker, each on an address of its own: deploy/lab/run.sh up builds and starts it and sets the shared address; run.sh call calls between phones on different servers; run.sh failover kills the server carrying a call through the shared address and checks the call carries on (the sound comes back in about five seconds); run.sh impaired calls from a phone on a bad link (delay, jitter and 5% loss) and checks the call quality BitVoice reports; run.sh down removes it. The servers' pages are at https://127.0.0.1:18501 and :18502 (user admin).

Chapter 62

Where the data is kept (SQLite or PostgreSQL)

In the web interface: /settings

BitVoice keeps its settings and their saved versions, users, contacts, call records, the audit log, texts, notes and transcripts in a database. Recordings and voicemail stay as sound files in the data folder.

one serverbitvoice.dbSQLite, the defaultmove, all or nonePostgreSQLone databaseRecordings and voicemail stay as sound files in the data folder.
Figure 49. Where the data is: one file, or PostgreSQL

This server's own file (SQLite, the default): a single file, bitvoice.db in the data folder, with nothing to install. Back up the data folder and you have everything.

PostgreSQL: for several BitVoice servers sharing one set of data, or for reports in tools such as Power BI, Grafana or Metabase. In Settings, Database, Move the data into PostgreSQL: make an empty database and a user who owns it, enter its address (postgres://user:password@host:5432/database), press Test, then Copy the data and restart on PostgreSQL. Everything is copied in one go (all of it or none of it) and BitVoice restarts on it; the old file stays where it was. Moving back into the server's own file works the same way. Moves are refused while calls are in progress.

Servers sharing a PostgreSQL database see each other's settings changes within five seconds. Each still answers its own phones and calls; for a second server to take over a first one's phones, the phones need both addresses (or one address that moves).

The database can also be named when BitVoice starts, with -database postgres://… or the BITVOICE_DATABASE environment variable; it is then changed there, not in Settings.

Older installations: on the first start of this version, BitVoice copies its old JSON files into the database and moves them into pre-database in the data folder.

Chapter 63

Hosting other organisations

In the web interface: /tenants

One BitVoice can host several organisations. Each one is a phone system of its own: its own extensions, numbers, trunks, routes, administrators, voicemail, recordings and call history. No organisation can see another's. They share only this server's SIP port, IAX2 port and media ports.

ONE BITVOICE SERVERMain system/own dataAcme Dental/t/acme/own usersRiverside Clinicpbx.riverside.exampleown numbersshared: SIP 5060, IAX2 4569, media portsBy domainpbx.riverside.exampleBy user nameacme.100By trunk and numbera shared provider
Figure 50. Hosted organisations: one server, separate phone systems

When to use it

The main system is an organisation too: the one this server was set up as. Its administrators manage the others.

Adding an organisation

  1. Open Organisations (chapter 63) and press Add organisation.
  2. Give its name and a short name (lowercase letters, digits and dashes). The short name is part of its web address, /t/acme/, and of its phones' sign-ins, acme.100. It cannot be changed later.
  3. Optionally give its own domain, such as pbx.acme.example, pointed at this server. Phones register to that domain, and its administrators open it in a browser.
  4. Set its first administrator: a username and a password of at least 12 characters, and its country.
  5. Optionally set limits.

The organisation starts at once with an empty phone system, ready for its administrator to set up as described in Getting started (chapter 1).

How calls find the right organisation

A requestgoes to
from a phone registering to pbx.acme.examplethe organisation with that domain
from a phone signing in as acme.100Acme, extension 100
from a provider, for a numberthe organisation whose trunk it comes from and whose incoming route has that number
anything elsethe main system

So two organisations can both have extension 100, and several can share one provider account with different numbers.

Where its data is

On SQLite, each organisation has its own folder under tenants/ in the data folder, with its own database file. On PostgreSQL, each has its own schema in the same database (tenant_acme). Backups, archives and exports are per organisation.

Limits

LimitWhat happens at it
Extensionsadding one more is refused with a message
Calls at oncenew calls are refused (503) until one ends
Storagenew recordings and voicemail are not kept
AI requests a daytranscripts, summaries and the AI receptionist stop until midnight UTC

0 is no limit. Emergency calls are never refused: an organisation at its call limit, or suspended, can still call 911 and be called back.

Opening an organisation

Open signs you in to its web interface as the provider, without its own account; it shows in its audit log as the provider. Its administrators sign in at its own address with their own accounts. Each organisation has its own sign-in cookie, so being signed in to one never signs anyone in to another.

Organisations never see this server's own screens: updates, the database, the other servers, the certificate, the SIP trace (which shows every organisation's messages), the call generator or this list.

Suspending and removing

Suspended stops sign-ins and every call except emergency calls; nothing is deleted. Remove stops the organisation and moves its folder aside (tenants/.removed-<name>-<time>), so a mistake can be undone by hand.

Chapter 64

Codecs and sound

A codec is how sound is turned into data on a call. Phones, browsers and carriers each support some; BitVoice converts between any two of its codecs when two parties differ, so everyone can talk to everyone. When both use the same codec the sound passes through untouched.

BrowserOpusDesk phoneG.722 HDDECT baseG.726ConvertsG.711 µ-law and A-law · G.722Opus · G.729 · G.726 · GSMonly when the two sides differ:same codec, passed untouchedCarrierG.711Thin linkG.729Old softphoneGSM
Figure 51. Codecs: each side speaks its own, BitVoice converts in between

The codecs

CodecSoundBandwidthUsed by
G.722HD (wideband)64 kbit/smost desk phones: the best choice between them
G.711 µ-lawtelephone64 kbit/sNorth America and Japan; every carrier
G.711 A-lawtelephone64 kbit/sthe rest of the world
OpusHD, copes with loss24 kbit/sbrowsers and the mobile apps
G.729telephone, a little rougher8 kbit/sthin links, some carriers
G.726 (40 kbit/s)telephone; carries modem tones best of the G.726 rates40 kbit/sgateways, some DECT systems
G.726 (32 kbit/s)near telephone32 kbit/sDECT bases, older gateways
G.726 (24 kbit/s)between 32 and 1624 kbit/ssome DECT systems
G.726 (16 kbit/s)rough16 kbit/svery thin links
AMR-WB (G.722.2)HD6.6 to 23.85 kbit/smobile networks' HD voice, VoLTE interconnects
AMRtelephone, mobile4.75 to 12.2 kbit/smobile networks, some carriers and gateways
iLBCtelephone, copes with loss13.3 or 15.2 kbit/solder softphones and apps
Speextelephone15 kbit/s (2.15 to 24.6)older softphones, links to other Asterisk systems
GSMrougher13 kbit/solder softphones and gateways
G.723.1rough; converted only with ffmpeg5.3 or 6.3 kbit/svery old video phones and gateways

Settings lists the codecs phones may use, best first; each trunk may have its own list. Analog adapter ports always use G.711, which faxes, modems and alarm panels need.

G.723.1 passes untouched between two parties that both use it. To let a G.723.1-only device talk to anything else, switch on Convert G.723.1 with ffmpeg in Settings and install ffmpeg (apt install ffmpeg, brew install ffmpeg): BitVoice then runs ffmpeg as a separate program for each direction that needs converting (heard at either rate, sent at 6.3 kbit/s, the rate ffmpeg's encoder makes), about 60 ms later than other codecs, and stops it a few seconds after the call. BitVoice carries no G.723.1 code of its own: the ITU's reference code has no licence that allows including it, and ffmpeg is installed and run on its own.

What converting costs

Converting takes processor time, only on calls where the two sides differ. Per call, about 0.3 ms of one core every 20 ms for Opus and 0.12 ms for G.729 (some 60 and 170 converted calls per core); G.726 and GSM cost less than G.729; G.711 and G.722 almost nothing. G.729 is sent without Annex B (no silence frames).

Sound clean-up

Sound clean-up (Settings) turns down steady background noise and evens out levels, for voicemail and, if you like, during calls.

Chapter 65

Microsoft Teams (Direct Routing)

In the web interface: /trunks

BitVoice can be the session border controller (SBC) for a Microsoft Teams tenant, so Teams users call BitVoice extensions and your phone lines, and BitVoice rings Teams users.

Teams usersapp and Teams phonesMicrosoftTLS 5061SRTPBitVoice (SBC)CarriersDesk phonesNeeds: this server’s public name, a certificate for it, and the PowerShell BitVoice shows.
Figure 52. Microsoft Teams Direct Routing: BitVoice is the SBC

What you need: a public name for this server in a domain your Microsoft 365 tenant has verified (sbc.example.com), port 5061 open both ways to Microsoft's networks 52.112.0.0/14 and 52.120.0.0/14, and a certificate for that name from a public authority. Teams users need a Phone System licence.

Steps

  1. Settings, Certificate: install the certificate and its private key (PEM). It is used at once, for this interface and for SIP over TLS, and BitVoice presents it to Microsoft.
  2. Trunks, Add, start from Microsoft Teams: enter the server's public name. The drawer says whether the certificate covers it.
  3. Copy the PowerShell the drawer shows and run it as a Teams administrator: it adds the SBC (New-CsOnlinePSTNGateway), a voice route and policy, and a dial plan rule so short extension numbers reach BitVoice as dialled; then give each Teams user the policy and their number.
  4. To ring Teams users from BitVoice, add an outbound route for their numbers through the Teams trunk.

BitVoice sends Microsoft OPTIONS every minute with the SBC name in Contact, as Microsoft requires, and tries sip, sip2 and sip3.pstnhub.microsoft.com in turn. Media is always encrypted (SRTP). Health warns when the certificate does not cover the name, is self-signed or ends soon, and when Microsoft stops answering.

This follows Microsoft's published SBC requirements and is tested against a simulated Microsoft proxy; BitVoice is not on Microsoft's list of certified SBCs.

Chapter 66

Import

In the web interface: /import

Brings extensions, ring groups, queues and trunks over from FreePBX, Asterisk or 3CX; and people, hunt and ring groups, SIP trunks, incoming numbers and dial patterns from Cisco, Avaya and Mitel. Upload the exported files, several at once (a .zip or .tar of them works too); BitVoice shows exactly what would change before anything is applied, and the import becomes a revision you can undo on Changes (chapter 59).

FreePBX, Asterisk3CXCisco, Avaya, MitelPreviewwhat would changeApplyone revisionUndoSeveral files at once, or a .zip or .tar of them.
Figure 53. Import: another system’s export, previewed before anything changes

Moving from FreePBX

The best file is a FreePBX backup: it holds everything, SIP passwords included.

  1. In FreePBX: Admin → Backup & Restore → Add Backup. Tick at least Core, Ring Groups, Queues and Voicemail (all modules is fine), save, and Run.
  2. Download the backup from its row (the file is named like 20261001-100000-1790000000-17.0.19-1234567.tar.gz).
  3. Install BitVoice on the new server and finish the setup with one extension that FreePBX does not use (say 199) and no phone line: the import brings the lines.
  4. On Import (chapter 66), drop the .tar.gz as it is. Read the preview: the warnings list everything that cannot come over.
  5. Choose Add. It is one revision on Changes (chapter 59): undo it there if anything looks wrong, and import again.
  6. Move the phones: point each at BitVoice (or provision them from Phones (chapter 4)), with the same extension number and SIP password they had.
  7. Test calls in and out, then move the carrier's registration (or the number porting) last.

Tried on a real system: a FreePBX 17.0.33 (the official Debian 12 install) with four extensions and voicemail, a PJSIP trunk that registers, two outbound routes (one with a dialling prefix), a ring group, a queue with penalties and three DIDs, backed up by Backup & Restore with every module ticked. The backup is 70 MB, nearly all of it sound files and call history: BitVoice reads it as it comes and keeps only the configuration, so a backup of up to 512 MB uploads. Everything above came over: the passwords, the voicemail PINs and email, the trunk's registration and codecs, the routes with their prefixes, the ring group's voicemail when unanswered, the queue's penalties and the DIDs to the group, the queue and the extension.

What comes over:

What does not, and is said in the preview: IVRs, time conditions, announcements, follow-me, custom trunks and contexts, caller-ID matching on routes, and outside numbers in ring groups. Build those on Menus (chapter 20), Schedules (chapter 25) and the extension's Follow me. Older backups (FreePBX 13 and before) and a plain mysqldump asterisk of the FreePBX database are read the same way.

Other systems

Where each export is:

Groups and routes. Upload them with the people file, so each group's members are found by number or by name:

Trunks from these exports come in switched off and without passwords, as the exports do not carry them. Routes go out on the imported trunk of the same name; a route whose trunk is not here is left out and said. Rotating and longest-idle ringing is closer to a queue than a ring group: the preview says so, so you can make it one.

These exports (all but a FreePBX backup) hold no SIP passwords, so each extension gets a new one; voicemail PINs, names and email addresses come over when the export has them. Cisco, Avaya H.323/DCP and Mitel phones run their maker's own software and cannot be set up by BitVoice: the import says how many were listed. Cisco phones can be re-flashed with Cisco's multiplatform (SIP) firmware; Avaya J100 and Mitel 6800/6900 phones can register to BitVoice by hand in SIP mode.

Chapter 67

Configuration as code

Everything the screens do goes through BitVoice's REST API, so anything can be scripted, kept in Git, or managed with Terraform. The API is described for tools at /api/openapi.json (/api/openapi.json).

Terraform, OpenTofuScripts, CIA Git repositoryREST APIBearer bv_…BitVoicethe same calls as the screens
Figure 54. Configuration as code: the API, Terraform and Git

API tokens

Made on Administrators (chapter 56): one per program, read only or able to change everything. Send it as Authorization: Bearer bv_.... It is shown once; revoke it when no longer needed. A token's changes show in Changes and the audit log under its name.

curl -H "Authorization: Bearer bv_..." https://pbx.example.com/api/extensions

Terraform or OpenTofu

The repository's deploy/terraform shows extensions, ring groups and routes managed with the generic REST provider: plan shows what would change, apply makes the change. The provider checks BitVoice's certificate; while BitVoice still uses its own self-signed one, either get one from Let's Encrypt (Settings, Certificates) or set bitvoice_insecure = true on a network you trust (on Linux, SSL_CERT_FILE pointing at BitVoice's certificate works too). Resources are matched by the id BitVoice gives them, so a second plan shows no changes until the file or the screens change something.

Configuration from Git

In Settings (chapter 14), Configuration from Git, BitVoice reads the configuration from a file in a repository every few minutes and either shows what differs or makes the changes. Start the file with Export for Git, which leaves out passwords; BitVoice keeps its own, so secrets never go into the repository.

Chapter 68

Asterisk compatibility (AMI and ARI)

Tools written for Asterisk can control BitVoice: CRMs, wallboards, click-to-dial buttons, call recorders' controllers. Switch it on in Settings (chapter 14), Asterisk compatibility. Tools see calls as channels named like PJSIP/100-..., as on Asterisk.

Click to dialOriginateWallboardQueueStatus, eventsAMI · TCP 5038ARI · /ari/BitVoicePJSIP/100-…PJSIP/102-…Logins are read only unless marked Can change calls.
Figure 55. Asterisk compatibility: tools written for Asterisk drive BitVoice

AMI

The manager interface on TCP port 5038 (AMI listens on: this computer only by default). Supported:

KindNames
ActionsLogin (plain or MD5 challenge), Ping, Events, Filter, ListCommands, CoreShowChannels, Status, CoreStatus, CoreSettings, PJSIPShowEndpoints, ExtensionState, ExtensionStateList, DeviceStateList, Getvar, Originate, Redirect, BlindTransfer, Hangup, Logoff
QueuesQueueStatus, QueueSummary, QueuePause, QueueAdd and QueueRemove (they sign an agent in to, or out of, all of their queues), Agents
OtherParkedCalls; ConfbridgeListRooms, ConfbridgeList, ConfbridgeKick, ConfbridgeMute, ConfbridgeUnmute, ConfbridgeLock, ConfbridgeUnlock; MailboxCount, MailboxStatus; PauseMonitor, UnpauseMonitor; UserEvent; Reload (nothing to reload: changes apply at once)
EventsNewchannel, Newstate, Hangup, DialBegin, DialEnd, Hold, Unhold, PeerStatus, ContactStatus, MessageWaiting, ConfbridgeJoin, ConfbridgeLeave, ConfbridgeEnd, UserEvent

Filter keeps only the events a regular expression matches (Event: Newchannel), or drops them with ! first, as on Asterisk. There is no Asterisk command line: Command answers with an error.

ARI

At /ari/, with basic authentication or ?api_key=user:secret:

RequestWhat it does
GET /ari/channelsthe calls in progress
POST /ari/channels?endpoint=PJSIP/100&extension=5551234ring 100, then call the number
DELETE /ari/channels/{id}hang up
POST /ari/channels/{id}/redirect?endpoint=PJSIP/102send the call to 102
/ari/endpoints, /ari/bridges, /ari/asterisk/infophones, bridges, version
/ari/eventsa WebSocket of events
POST /ari/channels/externalMedia?external_host=host:port&encapsulation=rtp&format=ulawa channel sending sound to a program by RTP (ulaw or alaw over UDP); its local port is in the channel's UNICASTRTP_LOCAL_PORT
POST /ari/channels/externalMedia?external_host=host:port&encapsulation=audiosocket&transport=tcp&format=slin&data=<uuid>the same by AudioSocket
POST /ari/bridges/{call}/addChannel?channel={id}the external media channel joins a call: it hears both parties and both hear it; with role=listener nobody hears it (for live transcription)
POST /ari/bridges/{call}/removeChannel?channel={id}it leaves the call; the two parties talk directly again

An external media channel not added to a call within a minute is closed.

ARI applications

An ARI application (Asterisk's Stasis()) runs calls from your own program. Add it under ARI applications in Settings, Asterisk compatibility: a name, an optional number extensions dial, and a fallback. Then send calls to it like any destination: an incoming route, a menu key, a schedule.

Your program connects to /ari/events?app=NAME (a WebSocket, with the login in ?api_key=user:secret). Each call reaching the application is answered and arrives as StasisStart, with the channel; the program then runs it:

RequestWhat it does
POST /ari/channels/{id}/play?media=sound:goodbye,digits:42plays prompts from Sounds (sound:), digits:, number:, tone:beep or a stored recording (recording:); PlaybackStarted and PlaybackFinished follow. DELETE /ari/playbacks/{id} stops it.
POST /ari/channels/{id}/record?name=msg1&maxDurationSeconds=60&maxSilenceSeconds=5&beep=true&terminateOn=%23records (wav) into the stored recordings; RecordingStarted and RecordingFinished. POST /ari/recordings/live/{name}/stop ends it, DELETE discards it.
GET /ari/recordings/stored, .../{name}, .../{name}/file, DELETE .../{name}the stored recordings
POST /ari/channels/{id}/dtmf?dtmf=123sends keys to the caller
GET/POST /ari/channels/{id}/variable?variable=X&value=Ythe channel's variables
POST /ari/bridges?bridgeId=room1, .../addChannel?channel=a,b, .../removeChannel, .../play, DELETEmixing bridges: everyone in one hears everyone else
POST /ari/channels/{id}/continue?extension=101lets go of the call: to that extension, ring group or queue, else the fallback
DELETE /ari/channels/{id}hangs up
POST /ari/channels?endpoint=PJSIP/101&app=NAMErings 101; answered, it enters the application
GET /ari/applicationsthe applications, whether a program is connected, and their channels

Keys pressed arrive as ChannelDtmfReceived; a caller hanging up as StasisEnd. When no program is connected the call goes to the fallback; when the program's last connection closes, its calls go there too after five seconds (time to reconnect). For call logic without a program of your own, use Scripts (chapter 26) that run the whole call; to hand the audio to a program, Voice bots (chapter 23).

Logins

Each login has a Username and Secret. Logins are read only unless marked Can change calls. Keep AMI on this computer unless the tool runs elsewhere: AMI is plain, unencrypted TCP.

Chapter 69

Archive

In the web interface: /archive

The archive keeps copies of recordings, voicemail and the configuration somewhere else: an Amazon S3 bucket (or any S3-compatible store) or an Azure Blob Storage container. If this server's disk is lost, the archive still has them.

BitVoiceevery 10 minCall recordingsVoicemailConfigurationonce a dayS3 bucket or Azure containerOnly what is new or changed is copied; nothing is deleted from the archive.
Figure 56. The archive: copies kept somewhere else

Setting it up

  1. On Archive (chapter 69), choose Where to archive: Amazon S3 or Azure.
  2. For S3: the Bucket, its Region, an optional Folder in the bucket and Endpoint (for S3-compatible stores), and an Access key ID and Secret access key. Copy the policy gives the only permission BitVoice needs, to attach to the user or role.
  3. For Azure: a Container SAS URL with write permission, and an optional Folder in the container.
  4. Choose what to copy besides the configuration: Call recordings, Voicemail, or both.

What happens

Every ten minutes BitVoice copies new recordings and messages that are not in the archive yet, and once a day a dated copy of the configuration (config/2026-10-13.json). The page shows the last run, the last success and any error.

Deleting something here (by retention or by hand) does not delete the archive's copy: set the bucket's or container's own lifecycle rules for how long the archive keeps things.

Chapter 70

Legal holds

In the web interface: /holds

A legal hold keeps call records, recordings and voicemail that a matter may need, and stops anyone deleting them, until it is released. Use it when a lawyer asks for records to be preserved.

Call recordsrecordings, voicemailUnder a hold?numbers and dates it namesKept, cannot be deletedRetention as setReleasing a hold returns what it kept to the retention settings.
Figure 57. A legal hold: kept, whatever the retention says

Adding a hold

On Legal holds (chapter 70), press Add:

FieldWhat it is
Namewhat the matter is called
Reasonwhy, for the record
Numbersthe extensions and outside numbers it covers (101, +15551234567), or Everything
From, Tothe dates it covers; empty for no limit

While a hold is on

Releasing

Release makes what the hold kept subject to the retention settings again: things older than the retention are deleted at the next clean-up. Released holds stay listed, with when and by whom, and adding and releasing holds is in the audit log.

Chapter 71

Metrics: Prometheus, OpenTelemetry, Grafana, SNMP and call records

In the web interface: /settings

Prometheus scrapes /metrics on the web address. Make an API token under Administrators (a viewer token is enough) and give it to Prometheus as its bearer token:

BitVoicePrometheusscrapes /metricsOpenTelemetrypushed each minuteGrafanathe ready-made dashboardCalls, phones, trunks, queues, packets lost, quality scores, callbacks.
Figure 58. Metrics: Prometheus pulls, OpenTelemetry is pushed
scrape_configs:
  - job_name: bitvoice
    scheme: https
    authorization: { credentials: bv_... }
    static_configs: [{ targets: ['pbx.example.com'] }]

It reads calls in progress (by state), calls ended (by direction and outcome), talk time, phones registered, each trunk's state and round trip, callers waiting and agents in each queue, sound packets received and lost, a histogram of call quality scores (MOS), and callbacks booked. Counters start again from zero when BitVoice restarts, as Prometheus expects.

OpenTelemetry: in Settings, Metrics, enter a collector's OTLP/HTTP address (and a header such as Authorization, with its value) to have the same measurements pushed every minute (or as often as you set, from 15 seconds). Push now checks the saved settings.

Grafana dashboard downloads a ready-made dashboard: import it in Grafana and pick your Prometheus data source.

SNMP

For monitoring systems that speak SNMP (Zabbix, PRTG, LibreNMS, Nagios, SolarWinds), switch on the SNMP agent in Settings. It answers SNMPv2c GET, GETNEXT and GETBULK, read only, on UDP port 161 (or another you choose: port 161 needs the right to open low ports on Linux), and only from the networks you list. Choose a community that is not public or private: it is a password that crosses the network in clear.

It serves the standard system group (sysDescr, sysUpTime, sysContact, sysName, sysLocation) and BitVoice's own values under the base OID: calls in progress and ringing, phones registered, trunks up and set up, callers waiting, calls ended, talk seconds, lost packets, average call quality, a trunk table (name, up or down, latency) and a queue table (waiting, agents, answered, abandoned). Download BITVOICE-MIB beside the settings for your monitoring to load. BioDream LLC has no enterprise number yet, so the default base OID is in Net-SNMP's experimental space; put one under your own enterprise number to keep it stable.

Traps (SNMPv2) go to each receiver you list when a trunk goes down or comes back, an emergency call is made, or a server of a cluster stops answering. SNMPv3 is not supported yet.

Call records elsewhere

Beside Call history, each record can go, as its call ends, to:

Send a test record tries the syslog server and the database with the settings saved.

Chapter 72

Call generator

In the web interface: /loadtest

The call generator places real calls with real audio into BitVoice from this computer: to see how many calls a server carries and how well, or to check after a change that calls still go where they should.

Call generatorso many a secondBitVoiceA number insidenever a trunkAnswered / failedAnswer timeAudio lost, scoreIt never calls trunks or emergency numbers.
Figure 59. The call generator: real calls, real audio, measured

Running a test

SettingWhat it is
Number to calla number inside BitVoice: an extension, a group, a queue, a menu
Calls come fromthe caller number the calls show
Answer asan extension the generator answers for itself; or nobody, when the number answers by itself (a menu, the echo test)
Callshow many in all
At oncethe most in progress together
New per secondhow fast they start
Each lasts (s)how long each talks

Reading the results

ResultWhat it says
Answered, Failedand Why calls failed, by reason
Answer time, median and 95%how long callers waited
Audio lostthe share of sound packets that never arrived
Audio scorean estimate of the sound (MOS): 4 and over is good, under 3.6 is poor
Calls in progress over timea chart of the load
Chapter 73

SIP trace

In the web interface: /trace

The SIP trace shows the messages BitVoice sends and receives, live: the first place to look when a phone will not register or a call fails, and what a provider's support desk will ask for.

Phone 100BitVoiceProviderINVITE 2125550199100 TryingINVITE +12125550199180 Ringing180 Ringing200 OK200 OKACKBYEBYE
Figure 60. A SIP trace: the messages of one call, in order

Finding a message

BitVoice keeps the last 2,000 messages in memory (nothing is written to disk, and they are gone after a restart). Type part of a number, an address or a Call-ID in the filter. Press Refresh for the newest.

Choose a message to see it in full and, beside it, the call flow: every message of the same call in order, between the phone, BitVoice and the provider, as in the figure.

Reading a trace

You seeIt usually means
REGISTER answered 401, then nothingthe phone does not have the password, or has the wrong one
REGISTER answered 403the address is banned, or the phone signs in as another extension
INVITE answered 404no route matches the number dialled (Call routing (chapter 8))
INVITE answered 403 by the providerthe provider refuses the caller ID or the number
486the other side is busy
488the two sides have no codec in common (Codecs (chapter 64))
200 OK, then BYE after about 30 secondsthe ACK never arrived: a router in between rewrites or drops messages (switch off its "SIP ALG")
A call connects but nobody hears anythingthe sound is blocked: check the public address in Settings, and the media ports in the firewall
Part 6

Public safety: the lab track

The 911 answering-point profile, the radio dispatch console and NG911 Core Services. They are a lab and design-partner track: built and tested against recorded captures, sample data and stand-ins, but not certified for live 911 or radio dispatch and not yet tried with a live ESInet, P25 system or CAD. They are off the menu until switched on in Settings. Emergency calls from your own phones (Getting started) are not part of this track: they are part of every phone system.

Chapter 74

911 calls (the 911 profile)

In the web interface: /psap

BitVoice answers 911 calls as a PSAP's call-handling system: calls from the emergency services network (the ESInet, NENA i3) arrive with the caller's location and the network's data, the call-taker sees them at once, and CAD is told when the call is answered.

ESInetBCFchecks the source911 queueby priorityCall-taker positionlocation on the map, callback number,additional data, rebid, transferCAD: ALI spill, EIDONENA i3 logevery event
Figure 61. The 911 profile: an NG911 call reaches a call-taker

Setting up.

  1. On Trunks (chapter 7), add the trunk from your ESInet provider (or the NG911 core's ESRP) and switch on From the ESInet.
  2. In Call routing (chapter 8), send its calls to your call-takers: a queue, or a ring group.
  3. On 911 calls, enter your agency ID (a domain, like psap.county.example.gov) and what CAD takes: the address and port its ALI listener is on, and its EIDO address.

When a 911 call rings, it shows on 911 calls with:

Location comes in the call (by value), or as a reference BitVoice fetches with HELD. A call with a reference has Rebid location: BitVoice asks again, for a caller who is moving or whose first fix was rough.

When a rebid changes the location, the location check says which to show first, and why: the new location as a rule; the first one when it was a precise device fix (GPS, within 100 m) less than two minutes old and the new one is rougher; and both when two locations disagree by more than their uncertainty allows, so the call-taker asks the caller. The first location stays on the call either way.

When a call-taker answers, CAD gets, each on its own so a CAD that is down never holds up the call:

Caller video and photos. On a 911 call, Send the caller a video link makes a link only this call opens: texted to the caller from the number under Text the link from, or read out. The caller opens it in their phone's browser (no app): Share live video sends the back camera live (WebRTC, WHIP: RFC 9725), and Send photos or videos sends what they have already taken, dashcam and action-camera files included. On the call:

Video never takes from the calls: each live video has its own ports, this server takes at most Live videos at once of them (4 unless set), each asked to stay under Video bit rate, and video that stops for ten seconds is ended. Callers' phones must reach this server at Link address (https) and its media ports (UDP). Files are kept Keep files and the exposure log days (blank: until deleted), held calls aside.

Recording the live video. With Record callers' live video on, the caller's live video is kept with the photos and clips as one file per stretch of video: the same pictures the phone sent, not converted, in an IVF file (H.264 or VP8 with each picture's own time), hashed as it is written. A picture damaged by a lost packet is left out rather than kept broken, and the phone is asked for a full picture to carry on from. Reveal plays it (from a copy in WebM or MP4 that ffmpeg makes, the same pictures in another container; without ffmpeg only the original downloads); Download the original gives the file the hash is of. ffmpeg, VLC and forensic video tools open the original.

Into CAD. The EIDO (NENA-STA-021) sent to CAD names each photo, clip and recording, and the live video while it lasts, as additional data by reference: urlPurpose is caller-photo, caller-video, caller-video-recording or caller-video-live, and additionalDataByReferenceUrl is the file at /m/{viewToken}/{n} or the live video at /whep/{viewToken}. BitVoice sends CAD the EIDO again when a file arrives or live video starts or stops. The links use Link address (or this server's public address); with neither, the EIDO names no media. Every fetch through them is in the exposure log. The event stream says the same (GET /api/events: call.media, call.video). BitVoice's EIDOs are checked against NENA's published EIDO schema.

Links that do not exist are guessed at no faster than sign-ins: an address that keeps trying is turned away for a while. Files from callers are served in a sandbox, never as a page of this server.

Exposure. Every reveal of a live video and every opening of a photo or clip is counted under Exposure on 911 calls: who, how often, over how many calls. It is for supervisors and the centre's wellness programme.

Video a phone sends in the 911 call itself (SIP video over the ESInet) can be watched the same way: Watch takes it as the source when no link video is live.

Calls with only a number. A 911 call that brings a callback number and no location (from a CAMA trunk, or an ESInet call whose location did not come) can be looked up: give Location lookup (ALI) the address of your ALI database's or location server's HELD interface (RFC 5985, asked by telephone number as RFC 6155 has it). BitVoice asks as the call arrives, without holding it up, and the location appears on the call when the answer comes; the call says when the lookup failed and why.

The legacy ALI link. Without a HELD server, BitVoice can ask an ALI controller, or the ALI database's data link, the old way: it sends a request and reads back the record as text, over the network (ALI link address host:port) or out of a serial port (serial:/dev/ttyUSB0?baud=9600&parity=none, with bits and stop too; a USB serial adapter works; on Linux and macOS, not Windows: there, use a serial-to-network converter and its address). Request is what to send: {ani10} the ten-digit callback number, {ani7} its last seven, {pos2} the position,  STX and  ETX ({ani10} when blank). The answer is read up to its ETX. ALI layouts differ between providers and states, so you place each field: its line, its column and its length (0: to the end of the line), from a printout of an ALI screen; Street (whole line) splits a street line into its parts, or place the parts one by one. Paste a sample record and Read the sample to see the lines with a column ruler and what each field reads; Ask asks the link itself for a number. The record's address and position become the call's location, its name the caller's name, and its class of service shows on the call. Protocols that are not a request and a text answer (PAM, E2 and other vendors' own) are not spoken: they need a gateway.

ALI spill over a serial port. ALI spill to also takes a serial port (serial:/dev/ttyS0?baud=9600), for a CAD that reads the spill from a serial cable.

The map. Under Map in the 911 settings, give BitVoice its map tiles: an .mbtiles file of raster tiles (PNG, JPEG or WebP) on this server, for a map that works with no internet (your GIS team, TileMill, gdal2tiles or a tile vendor makes one of your area), or a tile server with {z}, {x} and {y} in its address (your county's, or a commercial one: mind its terms; the public OpenStreetMap servers are not for this). Either way the call-takers' browsers fetch tiles from BitVoice only: it reads the file, or fetches from the tile server and keeps the last tiles in memory. The same map shows radio positions on the radio console. Vector tiles are not supported.

The i3 log keeps the NENA i3 events of each call (call start, answer, location, EIDO sent), one file a day. Answer times shows how many calls were answered within your goal (NENA: 90% within 15 seconds, 95% within 20), the abandoned ones, and each call-taker's average. A row a day (CSV) downloads the counts state 911 offices usually ask for (calls, answered, abandoned, within the goal and within 20 seconds, average and longest wait) for the days chosen; A row a call (CSV) lists every 911 call with when it was answered, by whom, and whether it was text. Each state has its own form: lay yours out under Report layouts.

Report layouts. New report layout lays out a report as your state or county form has it: what each row is (a day, a week, a month, an hour of the day, a call-taker, or one row in all), a total row, and the columns, in order, each with its own heading if the form words it differently: calls, answered, abandoned (a count or a share), answered within so many seconds (a count or a share; the seconds are yours, so 10 and 20 for one form and 15 and 40 for another), answered after more than so many seconds, the average and longest wait, the time within which 90% were answered, the average call length, and text calls (TTY, real-time text, text to 911). A wait counts from the call's arrival to a call-taker's answer. Choose a layout and dates and Run it to read it here, Spreadsheet (CSV) to download it, or Page to print for a plain page to print or save as PDF. Layouts are kept with the settings, so they go with a backup and into Git.

TTY calls. Deaf and hard-of-hearing callers may call 911 with a TTY (a text telephone, Baudot at 45.45 bit/s). BitVoice listens for one on every 911 call's voice, from the first moment: what the caller types appears on the call as they type it, under Text, with a pause or a new line starting a fresh line. A silent call may be a TTY waiting for you: once you answer, Reply by TTY sends text even before any has come. Type the reply and press Send: it goes to the caller as TTY tones (the call-taker's voice is muted while it plays, as TTYs take turns), in capitals, and TTY etiquette applies: end each turn with GA ("go ahead"), and SK when signing off. Characters a TTY cannot show are left out. Speech, music and touch tones are never taken for TTY text: a character counts only when every bit of it is a clean TTY tone. The conversation is kept with the call in the call history and in the i3 log (one MessageLogEvent a turn). Untick Listen for TTYs on 911 calls in the 911 settings to stop listening.

Transfers. A 911 call sent on to another PSAP keeps its location: the PIDF-LO goes with the call.

Real-time text (RTT). A phone that sends text beside its voice (RFC 4103, as VoLTE phones and NG911 calls do) has its text answered by BitVoice itself, since desk phones show none: each character appears on the call as the caller types it, and your reply goes back as text. Lost packets are made good by the redundancy RTT carries; text lost beyond it shows as �.

Text to 911. A text control centre (TCC) sends texts to the PSAP as a session with no voice (MSRP, RFC 4975, over the ESInet trunk). BitVoice answers it and it waits on 911 calls marked Text to 911, with the texts that have come; nobody's phone rings. Take this text makes you the call-taker (the answer time is counted then, and CAD gets the ALI spill and the EIDO then); reply in the box under the conversation, and End conversation when done. The TCC closing the session ends it too. A SIP MESSAGE sent inside a 911 call's dialog is taken as the caller's text the same way, and replies go back by SIP MESSAGE. Texts are taken only from trunks marked From the ESInet.

A TCC that offers the session over TLS (TCP/TLS/MSRP, msrps: paths, RFC 4975 section 14) gets it over TLS, with this server's certificate (Settings › Certificates; without one such an offer is refused). The TCC's certificate must be the one its offer names (a=fingerprint, SHA-256); when it names none, it must be traced to the PSAP Credentialing Agency roots set under Core services, if any are set. BitVoice's answer names its own certificate the same way.

The whole conversation, whichever way it came, is kept with the call in the call history and in the i3 log.

What is not here yet: passing a text session on through the NG911 core (the ESRP routes voice; a text session is answered where it arrives); the EIDO conveyance standard's own subscriptions (NENA-STA-024 WebSocket): BitVoice posts EIDOs to one address.

Chapter 75

Radio dispatch console

In the web interface: /radio

Dispatchers talk on radio channels from the same headset as their phone calls. BitVoice reaches the radios through radio-over-IP (RoIP) gateways; the radio network itself stays with whoever runs it.

P25 systemISSI or CSSIRoIP gatewayanalogue channelsEncrypted talkgroupAES-256 keysRadio consolepush to talk (hold space)patch two channelsalert tonesemergency acknowledgeunit-to-unit callsDispatcherbeside the phoneRadio logand CAD events
Figure 62. The radio console: talkgroups beside the phone

Setting up. Under Console setup, choose a console number (800, say) and add each channel: its name, the port on this server the gateway sends the channel's audio to, and the gateway's address and port for the audio going out. On the gateway: RTP, G.711 µ-law, to this server's address and that port; key the radio on voice (VOX). Each channel uses its port and the next one, outside the range phone calls use.

Joining. A dispatcher dials the console number from their desk phone, or presses Join with the browser phone. They then hear every channel's traffic mixed together; Hearing / Muted on a channel takes it out of their headset. The lamp on a channel lights while it is receiving.

Talking. Hold a channel's Hold to talk button (or focus it and hold the space bar): your voice goes to that channel only, and the channel shows TX with your extension. One dispatcher talks on a channel at a time; the button is greyed for the others while someone is talking. Nothing is sent to a channel while nobody is talking, so a voice-keyed radio is never held on the air.

Patching. Press Patch on one channel, then Patch here on another: the two hear each other (a fire channel and a mutual-aid channel, say) until you press Unpatch.

P25 talkgroups. A channel can also be a P25 talkgroup, joined directly over the ISSI (TIA-102.BACA, the interface between P25 subsystems; with Send the CSSI console PTT word on, BitVoice adds the console subsystem's word to each request). Choose A P25 talkgroup (ISSI), give the talkgroup ID, the SIP address and ID of the RFSS that is home to the talkgroup, and a port for its voice. Under This console on the P25 system, enter the WACN and system ID, the RFSS ID your P25 administrator gave this console, the unit ID dispatchers transmit as, and the SIP port the ISSI uses here; the P25 system must know this server as an RFSS at that address. The tile shows P25 while the group call is up (P25 down and the reason when it is not), and the unit ID of the radio talking, in red with EMERGENCY when it is an emergency call. Hold to talk asks the home RFSS for the channel (Asking for the channel…); your voice goes once it grants it, and if it refuses (someone with a higher priority has it) the tile says so. Voice is converted to and from IMBE, the P25 vocoder, in BitVoice.

Encrypted talkgroups. Under Encryption keys, add each traffic key your radio shop gives you: a name, the algorithm (AES-256, DES-OFB or triple DES), the key ID and the key itself in hex (TIA-102.AAAD). A key is never shown again once saved, not even to administrators, and leaving the field empty keeps it. The console hears an encrypted transmission when it has the key with that algorithm and key ID: the tile shows a lock and the algorithm next to the talking unit. Without the key the transmission is muted, never played as noise, and the tile says no key: muted. To transmit encrypted on a talkgroup, choose a key under Transmit for that channel; the tile then shows TX AES-256 (or the algorithm you chose). A full configuration export (Settings, an administrator's backup) carries the keys, so keep those files as safe as the keys.

Private calls. With the console on a P25 system, Call a radio in your position's bar calls one radio by its unit ID (turn on Emergency to call it as an emergency). The call becomes a tile of its own, Private call: unit 197, with Hold to talk like any channel and Hang up. Radios can call the console too, on the unit ID dispatchers transmit as: the call appears as a tile marked called in (in red with EMERGENCY when the radio called as one), every dispatcher hears it, and it goes when either side hangs up. Under Private calls in the console's P25 settings, give the SIP address and ID of the RFSS that is home to the radios (empty uses the first talkgroup's home) and, if private calls should be encrypted, the key to send them with.

Alert tones. Send an alert tone… on a channel sends one of: Alert 1, a steady 1000 Hz tone for 3 seconds; Alert 2, a warble between 1000 and 1500 Hz; Alert 3, 1000 Hz pulses; or a short Beep. The tone holds the channel while it plays (the tile shows tone and your extension), every dispatcher monitoring the channel hears it go out, and on a P25 talkgroup it goes once the home RFSS grants the channel.

Emergencies. When a radio transmits as an emergency (its emergency button), its tile turns red with EMERGENCY and the unit ID, the server log notes it, and CAD is told at once (below). The emergency stays raised on every console after the radio stops talking, until a dispatcher presses Acknowledge: the tile then says who acknowledged it and when, and CAD gets a radio.emergency.ack event.

Simulselect. To say one thing on several channels at once, tick select on each channel, then hold Talk on N channels in the bar above the tiles. It is all or nothing: if another dispatcher is talking on one of them, none is keyed and you are told which.

Radio positions. Radios report where they are over the radio system's data side, not the voice side the console joins: P25 location service, Motorola's LRRP or a vendor's own, collected by the radio shop's data or AVL gateway. Have the gateway (or a small script beside it) POST each report to BitVoice with an API token: POST /api/radio/locations with {"unit": 1205, "lat": 40.2633, "lon": -76.8823, "speed": 42, "heading": 90, "accuracy": 8, "at": "2026-10-15T14:05:00Z"}, or a list of up to 500 (speed in km/h, heading in degrees, accuracy in metres; all three and the time are optional). Radio positions on the console then lists each radio's last fix, with its name, and CAD gets each one as a radio.location event. BitVoice does not decode LRRP or the P25 location service itself.

Radio names. Under Radio names, name radios by their P25 unit ID (1205 is "Engine 5", say): the tile shows the name beside the unit while it talks, and the radio log and CAD's events carry it.

Radio log and recording. Turn on Record every transmission under Recording and CAD: each transmission on each channel, heard or sent, is kept as a recording with a line in the Radio log: when, the channel, who (the radio's unit, or the dispatcher's extension), how long, and whether it was an emergency, an alert tone, encrypted or a private call. A heard transmission starts with the first speech and ends 1.5 seconds after the last word. Find a unit, dispatcher or channel with the search box, and press Play to listen. Recordings are kept as long as call recordings are (Settings, Recording).

Radio data to CAD. Give CAD's address under Send radio events to CAD at (and a shared secret if CAD wants one; it is sent as a bearer token and never shown again). BitVoice then POSTs each event (radio.unit, radio.emergency, radio.emergency.ack, radio.transmission and radio.location) as JSON, {"type": ..., "agency": ..., "data": {...}}: radio.unit when a radio starts talking on a channel (its unit ID, WACN, system, the channel, emergency, encryption), radio.emergency for an emergency (tried three times if CAD does not answer), and radio.transmission for each finished transmission as it appears in the radio log. CAD can also read the log itself with GET /api/radio/log (filters: channel, q, since, until). A CAD that is down never holds up the console. P25 radios' GPS positions are not part of this: they travel over P25 packet data (location services), not over the ISSI's voice.

Not here yet: P25 Phase 2 (TDMA) voice in its own half-rate vocoder. A Phase 2 system works with the console when its ISSI talkgroups carry full-rate (Phase 1) voice or its transcoder converts them, which is common: ask your P25 administrator. A talkgroup whose voice arrives in blocks this console does not decode (half-rate voice sent untranscoded, most likely) shows Silent here on its tile while a radio talks, so nobody takes the silence for a quiet channel. Decoding it needs two things BitVoice does not have: the half-rate vocoder (AMBE+2, patented until 2028: a licence from its owner, or a licensed hardware vocoder chip), and the ISSI's half-rate voice block format (TIA-102.BACA-B, sold by TIA, not public).

Chapter 76

NG911 Core Services (ECRF, ESRP, LVF, BCF, LIS, logging)

In the web interface: /core

For a state or regional 911 authority that runs its own NG911 core: BitVoice answers LoST as the ECRF, and routes each 911 call as the ESRP to the PSAP that serves the caller.

Incoming 911with locationESRProutes the callECRF (LoST)which PSAP serves here?Policy rulesoverflow, time of dayThe right PSAPLVFvalidates addresses
Figure 63. NG911 Core Services: routing a call by where the caller is

Service areas. Export your boundaries from GIS as GeoJSON polygons (PSAP boundaries for urn:service:sos; police, fire or EMS areas for urn:service:sos.police and the others) and upload them on Core services. A polygon's name, uri and number properties are read; give a default PSAP URI for those without one. Edit an area to add the cities or counties it serves, for callers whose location is a civic address only. Try a place shows which area answers a position or a city, as a LoST query would.

The ECRF. Switch on Answer LoST queries and list the addresses that may ask (your ESInet): other elements send findService to /lost (RFC 5222) and get the PSAP's URI. A specific service (sos.police) is answered from its own areas first, then from sos. A place none of your areas covers can go to the Forest guide (RFC 5582: the national directory of ECRFs): a recursive query is asked there on the asker's behalf and its answer returned (both servers listed in the answer's path), any other query gets a redirect to it, and a query that has already passed through this ECRF is refused as a loop.

The ESRP. List the PSAPs: each one's URI (as the areas name it), the trunk that reaches it and its overflow PSAP, and choose the default PSAP. Then send the ESInet's incoming 911 calls to ESRP in Call routing (chapter 8). Each call goes to the PSAP for its location (from this server's areas, or an outside ECRF by LoST), with its location and the service it asked for carried on; when that PSAP does not take it, to its overflow; without a location, or from a place no area covers, to the default. Each decision is in the i3 log on 911 calls (chapter 74).

Policy rules. Once the ECRF has picked a PSAP, the rules under Policy rules are checked in order and the first whose conditions all hold decides: send the call to another PSAP, or refuse it as busy. A rule can look at the service (fire calls only, say), the PSAP the ECRF chose, a schedule (while the night shift's centre is closed), calls with no location, calls the BCF marked suspicious, and the trunk the call came in on. Each decision is in the i3 log as a RouteLogEvent naming the rule.

Border control (BCF). With Check calls from the ESInet on, every call from an ESInet trunk is checked first: addresses under Always refuse are turned away, and so is an address that starts more calls a minute, or holds more calls at once, than you allow (a telephony denial-of-service attack sends floods of calls from a few sources). Refused calls get 503 with Retry-After. Turn on let the call through marked suspicious to send such calls on instead and let a policy rule decide (to a centre that screens them, or refused); a real caller in a flood is then not lost. Border control: latest lists what was refused or marked. Check STIR/SHAKEN signatures checks the signed caller ID (the Identity header) of every call that carries one, against the STI roots set under Call screening in Settings: a call whose signature fails goes through marked suspicious, for a policy rule to send somewhere else, and is listed in the BCF log; a 911 call is never refused for it, and unsigned calls (most of them today) are left alone. Each call leaves BitVoice as a new request of its own (BitVoice is a back-to-back agent), carrying only the headers and bodies BitVoice understands and passes on: the location, the Additional Data and the session. Inspect media checks every RTP packet of an ESInet call before it is used or passed on: packets from an address other than the one the call's SDP gave, with a payload type the offer did not name, with header lengths (CSRCs, extension, padding) that do not fit the packet, larger than Largest packet (1,500 bytes when blank), or past Packets a second (150 when blank; G.711 at 20 ms sends 50) are dropped and counted. The first of each kind, then the 10th, 100th and so on, goes in Border control: latest (as *media dropped*) and the call's notes. The call is never ended for its media: the caller keeps the good packets. Calls from CAMA trunks come from the local card program and are not inspected.

Address validation (LVF). Upload your 911 GIS address data as GeoJSON, in the NENA GIS data model (NENA-STA-006): road centerlines with FromAddr_L, ToAddr_L, Parity_L, IncMuni_L and the rest, and site/structure address points with Add_Number, St_Name, Inc_Muni. A LoST query with validateLocation="true" then gets the address's valid, invalid and unchecked parts in its answer (RFC 5222), so carriers and location servers can correct an address before a 911 call ever uses it. Check an address does the same here: an exact address point is the best match, then a street segment whose range on the right side of the road holds the number (odd and even sides respected); spellings like Street and St, North and N are treated alike.

The i3 logging service. Switch on Run an i3 logging service: the other elements of your core (ESRPs, BCFs, PSAPs) send their log events (NENA-STA-010), each signed as a JWS with the element's certificate in its x5c header, by POST to /i3log/LogEvents from the allowed addresses. Each comes as a JWS in the flattened JSON form (signed, or unsigned with algorithm none, which a logging service may take: marked as not traced to the PCA), is checked and kept, and the answer is its log event ID. Read back with GET /i3log/LogEvents/{logEventId}; list with GET /i3log/LogEvents (startTime, endTime, logEventType, limit, start); find the IDs of a call or incident with /i3log/LogEventIds, /CallIds, /IncidentIds and /AgencyIds; and read a call's text conversation with /i3log/Conversations?callId=. GET /i3log/Versions says what this service speaks. Log events received lists a day's events with who signed each. Every answer is checked against NENA's published OpenAPI definition of the service; the service has not yet been tried with another vendor's elements.

PSAP Credentialing Agency. Paste the PCA's root certificates under PSAP Credentialing Agency roots: a signed log event is then taken only when its signer's certificate chains to one of them (and has not expired), and is shown with PCA. Without them, the signature alone is checked, and the event is shown as not traced to the PCA.

Location records (LIS). Switch on Answer location requests (LIS) and upload a spreadsheet (CSV) of location records: a header row, and on each row one of a number (the ALI data, exported), a network (an address range such as 10.20.3.0/24, or one address: a building, a floor, a VLAN, a Wi-Fi network) or a mac address (one device: a desk phone, a wall jack's switch port), then the address as hno, rd, sts, unit, floor (or flr), a3 (city), a1 (state), pc and country, with lat, lon and radius where known (other names, such as phone, street, zip, subnet and ip, are understood too). PSAPs, legacy network gateways and phones then ask /held (HELD, RFC 5985) from the allowed addresses and get a PIDF-LO. A request names its device by telephone number, IP address or MAC address (RFC 6155); a request that names none is answered for the address it came from, as a LIS on an office or campus network does. An address is located by the narrowest network that holds it, so a floor's /24 wins over the campus /16. A device with no record gets HELD's locationUnknown; an identity of another kind (a NAI, a port) gets notLocatable. A BitVoice PSAP points its Location lookup (ALI) here. Look up a number, address or MAC address checks a record and says which network it came from. A number, network or MAC address listed again replaces its old record; Replace every record starts afresh. Only the allowed addresses are answered: a LIS that answers for any address it is asked about must not be open to anyone.

The i3 web services. Under NENA i3 web services, switch on what this core offers the other elements of your ESInet, at /i3/<service>/v1, for the addresses under May ask only. Each answers as NENA's published OpenAPI definitions say (NENA-STA-010.3, the NENA911 repositories), and each has a tab under i3 web services:

Test calls at a PSAP. A BitVoice PSAP answers a test call from the ESInet (urn:service:test.sos, NENA-STA-010.3 section 9, RFC 6881) by itself: its answer says the PSAP's name, the service and the location the call brought, the first three packets of sound go back, and it hangs up. A second test from the same place within two minutes is refused (486), as is a fifth at once. An ESRP passes a test call on like a real one, still marked as a test. Switch off Answer test calls on the 911 calls page to refuse them (404).

JWS algorithms: NENA-STA-010.3 asks for EdDSA with Ed448. Go's standard library, which BitVoice uses for every cryptographic step, has Ed25519 but not Ed448, so EdDSA signatures are checked with Ed25519 keys, and ECDSA and RSA signatures are taken too; an Ed448 certificate is refused.

Did you mean. An address that is not valid gets up to five suggestions from the same data, best first, each saying why: a street a letter or two away (a swapped pair of letters counts as one), the same street in the next town, or the nearest number the street has, on the same side when it can (even numbers stay even). Use fills a suggestion in. A position with the address. Give a latitude and longitude (and the position's radius, when known) with the address: the position is checked against the address's own address point, allowing its radius and 100 m more (the size of a plot, and GIS error). The answer gives the distance and whether the two agree, and, when they do not, the address point nearest the position. An address known only from road centerlines has no point to check against, and the answer says so. LoST's validateLocation has no place for either, so carriers asking by LoST get the validation alone.