Voicemail Box Management
This page covers the runtime side of voicemail: the messages, greetings, PINs, and preferences that accumulate inside a mailbox once it exists. The config side — declaring boxes and the policy contexts that govern them — is covered in Voicemail Boxes and Voicemail Contexts. Maintenance and recovery operations (wipe, repair, the orphan-box lifecycle) are on the companion page, Voicemail Administration.
The examples use the same conventions as the rest of the management guides:
$VSS, $TOKEN, $NSID on the curl side; an active profile with a
namespace set on the vsscli side. Voicemail commands live under the
realtime tree — vsscli realtime voicemail …, or the short form used
throughout this page, vsscli rt vm ….
The model — configuration vs. mailbox state
Section titled “The model — configuration vs. mailbox state”A voicemail box has two halves with different lifecycles:
| Declared in config | Runtime mailbox state | |
|---|---|---|
| What | The box’s existence and its context binding | Messages, recorded greetings, PIN, email, preferences, unread counters |
| Changed by | Config versions + apply | The endpoints on this page, and subscribers using the dial-in menus |
| Survives a config apply | n/a | Yes — applies never touch it (one exception: a distribution list’s static greeting is re-stamped) |
Every operation addresses a box by an explicit (context, box) pair — the same two names used in the config document. Both document-mode and managed-mode namespaces use the same endpoints; only where the box definition lives differs.
Permissions
Section titled “Permissions”Voicemail operations map to four actions:
| Action | Covers | Held by |
|---|---|---|
vm:list |
Box and message listings, box detail | All admin/ops roles, provisioner, viewer, system-auditor, voicemail-owner (own box) |
vm:read |
Audio downloads (messages, greetings) | Same as vm:list |
vm:write |
Message delete, greetings, PIN, options, wipe, repair | partition-admin, namespace-admin, provisioner, operator, editor, voicemail-owner (own box) |
vm:admin |
Orphan destruction and rehoming | partition-admin, namespace-admin, provisioner |
voicemail-owner is the single-box self-service role, granted at resource
scope over exactly one mailbox — see
self-service owners below and the
role catalog.
Inspecting boxes
Section titled “Inspecting boxes”# Every active box in the namespace (sorted by context, box)curl -s "$VSS/v1/ns/$NSID/vm/boxes" -H "Authorization: Bearer $TOKEN"
# Just one context's boxescurl -s "$VSS/v1/ns/$NSID/vm/boxes/standard" -H "Authorization: Bearer $TOKEN"
# One box in detailcurl -s "$VSS/v1/ns/$NSID/vm/boxes/standard/1001" -H "Authorization: Bearer $TOKEN"# → {"success":true,"context":"standard","box":"1001",# "email":"alice@example.com","envelope_autoplay":false,# "unread":2,"read":11,"urgent_unread":1,# "pin_set":true,"greetings":["default","temp"],# "temp_greeting_active":true}vsscli rt vm boxes # all active boxesvsscli rt vm boxes standard # one contextvsscli rt vm show standard 1001 # one box in detailReading the detail:
unread/read/urgent_unread— the live counters that drive message-waiting lamps.urgent_unreadis the subset of unread messages flagged urgent by their caller.pin_set— whether a PIN exists. The PIN itself is stored only as a strong one-way hash and is never returned by any endpoint.greetings— which of the three slots (default,busy,temp) currently hold a recording.temp_greeting_active— whether the temporary (vacation) greeting is switched on. When true it overrides the other greetings for callers.provisioned(listings only) — whether the box’s storage row has been materialized. Boxes are provisioned by the config apply that introduces them, so this is normallytrue;falsemeans the namespace’s apply predates voicemail storage on this deployment — re-apply the running version to seed it.
The box/orphan listings are point-in-time snapshots, not paginated — a namespace’s box census is bounded by its config size.
Messages
Section titled “Messages”Listing
Section titled “Listing”curl -s "$VSS/v1/ns/$NSID/vm/boxes/standard/1001/messages" \ -H "Authorization: Bearer $TOKEN"# → {"success":true,"context":"standard","box":"1001","messages":[# {"msg_id":"01J1FZK7Q0X5B3M8QW9RS2T4VE","caller_id_num":"+13055551234",# "caller_id_name":"MIAMI FL","duration_ms":14200,"read":false,# "folder":"INBOX","priority":false,"received_at":"2026-07-10T18:24:31Z"}]}vsscli rt vm messages standard 1001| Field | Meaning |
|---|---|
msg_id |
The message’s identifier — a ULID, so IDs sort by arrival time. |
received_at |
Arrival timestamp (derived from the ULID). |
caller_id_num / caller_id_name |
The caller-ID presented by whoever left the message. |
duration_ms |
Recording length. |
read |
Whether the subscriber has heard it (this is what clears the message-waiting lamp). |
folder |
INBOX by default; subscribers can file messages into the named folders (Family, Friends, Work, …) from the dial-in menu. |
priority |
Urgent flag, set by the caller in the review menu. |
Downloading
Section titled “Downloading”Message audio streams as audio/wav:
curl -s "$VSS/v1/ns/$NSID/vm/boxes/standard/1001/messages/01J1FZK7Q0X5B3M8QW9RS2T4VE" \ -H "Authorization: Bearer $TOKEN" -o message.wavvsscli rt vm message get standard 1001 01J1FZK7Q0X5B3M8QW9RS2T4VE --out message.wavWithout --out, audio goes to stdout for piping (… | ffplay -); vsscli
refuses to dump binary audio onto an interactive terminal.
Downloading a message through the API does not mark it read — only the subscriber hearing it (or deleting it) does. An export made for a compliance request won’t silently clear the customer’s message lamp.
Deleting
Section titled “Deleting”curl -s -X DELETE "$VSS/v1/ns/$NSID/vm/boxes/standard/1001/messages/01J1FZK7Q0X5B3M8QW9RS2T4VE" \ -H "Authorization: Bearer $TOKEN"vsscli rt vm message delete standard 1001 01J1FZK7Q0X5B3M8QW9RS2T4VEDestructive vsscli commands prompt; --yes skips the prompt for scripts.
Deletion removes the recording and its metadata, fixes the box counters, and pushes a message-waiting update to the subscriber’s devices — the same housekeeping as a subscriber deleting from the menu. There is no undo; for “delete everything”, see wipe.
Greetings
Section titled “Greetings”Each box has three greeting slots — default, busy, and temp
(temporary/vacation). Which one callers hear, and the fallback chain when a
slot is empty, is described in
what callers hear.
# Download the current default greetingcurl -s "$VSS/v1/ns/$NSID/vm/boxes/standard/1001/greetings/default" \ -H "Authorization: Bearer $TOKEN" -o greeting.wav
# Upload/replace a slot (raw WAV body, up to 25 MiB)curl -s -X PUT "$VSS/v1/ns/$NSID/vm/boxes/standard/1001/greetings/default" \ -H "Authorization: Bearer $TOKEN" --data-binary @greeting.wav
# Delete a slotcurl -s -X DELETE "$VSS/v1/ns/$NSID/vm/boxes/standard/1001/greetings/temp" \ -H "Authorization: Bearer $TOKEN"vsscli rt vm greeting get standard 1001 default --out greeting.wavvsscli rt vm greeting set standard 1001 default -f greeting.wavvsscli rt vm greeting delete standard 1001 tempgreeting set also accepts --stdin for pipelines.
Upload plain WAV audio; telephony playback is 8 kHz, so 8 kHz 16-bit mono PCM is the safe authoring target. An upload replaces the slot’s existing recording outright — including one the subscriber recorded from their phone — so treat greeting uploads on subscriber boxes as a support action, not routine automation.
The PIN lifecycle is security-sensitive by design — new boxes have no PIN, and a PIN-less box cannot be opened through the PIN dial-in path at all (see the rationale). These endpoints are how an administrator establishes or clears one:
# Set (digits only; minimum length from the context's min-pin-length)curl -s -X PUT "$VSS/v1/ns/$NSID/vm/boxes/standard/1001/pin" \ -H "Authorization: Bearer $TOKEN" -d '{"pin":"52346"}'
# Reset — CLEARS the PIN; the box is dial-in-inaccessible until a new one is setcurl -s -X POST "$VSS/v1/ns/$NSID/vm/boxes/standard/1001/pin/reset" \ -H "Authorization: Bearer $TOKEN"vsscli rt vm pin set standard 1001 # prompts twice, no echovsscli rt vm pin set standard 1001 --pin 52346 # scripted (visible in shell history)vsscli rt vm pin reset standard 1001- PINs must be digits only, at least the context’s
min-pin-length; violations are refused with a 400. - A PIN is write-only: it is stored as an argon2id hash, and nothing ever returns it. If a subscriber forgets their PIN there is no recovery — set a new one.
- Reset means clear, not default. After a reset the box behaves like a
new one: dial-in access is refused until a new PIN is set by an
administrator or by the subscriber from their own device (
*98, which authenticates by line rather than PIN).
Box options
Section titled “Box options”Non-PIN preferences are set through the options endpoint. Three options are recognized:
| Key | Value | Meaning |
|---|---|---|
email |
string | The box’s notification address. A blank/null value clears it. |
temp_greeting_active |
"true"/"false" |
Activate or deactivate the recorded temp (vacation) greeting on the subscriber’s behalf. |
envelope_autoplay |
"true"/"false" |
Per-box override of the context-level envelope-autoplay default. |
# A present key is applied; a missing key is a no-opcurl -s -X PUT "$VSS/v1/ns/$NSID/vm/boxes/standard/1001/opts" \ -H "Authorization: Bearer $TOKEN" -d '{"email":"alice@example.com"}'
curl -s -X PUT "$VSS/v1/ns/$NSID/vm/boxes/standard/1001/opts" \ -H "Authorization: Bearer $TOKEN" -d '{"email":""}' # clear email
# Start a vacation greeting for the subscriber (audio must already be recorded)curl -s -X PUT "$VSS/v1/ns/$NSID/vm/boxes/standard/1001/opts" \ -H "Authorization: Bearer $TOKEN" -d '{"temp_greeting_active":"true"}'
curl -s -X PUT "$VSS/v1/ns/$NSID/vm/boxes/standard/1001/opts" \ -H "Authorization: Bearer $TOKEN" -d '{"envelope_autoplay":"false"}'Unknown option keys are refused with a 400 rather than ignored, so a typo can’t silently do nothing. The boolean options have no “clear” state: a null or non-boolean value is a 400. Validation runs before any write, so a request that mixes a good and a bad key applies nothing.
vsscli rt vm set standard 1001 --email alice@example.comvsscli rt vm set standard 1001 --clear-emailvsscli rt vm set standard 1001 --temp-greeting-active # start vacation greetingvsscli rt vm set standard 1001 --temp-greeting-active=false # end itvsscli rt vm set standard 1001 --envelope-autoplay=falseSelf-service mailbox owners
Section titled “Self-service mailbox owners”A subscriber (or a portal acting for them) can be given control of exactly
one mailbox with a resource-scoped voicemail-owner grant — no visibility
into any other box or any other part of the namespace:
vsscli user create --username sub-1001 --owner-scope ns:$NSIDvsscli user grant add <sub-user-id> --role voicemail-owner \ --scope "resource:$NSID!vm_box!standard!1001"The owner authenticates like any other user and calls the same box-scoped
endpoints shown above — box detail, message listing, greeting
upload/download, PIN set, options — for their own (context, box) only.
Namespace-wide and context-wide listings remain outside the role’s reach:
those endpoints carry no concrete box, so the box-scoped owner grant is
never applied to them, and an owner credential can never be used to
enumerate other mailboxes.
Message-waiting indication
Section titled “Message-waiting indication”Every mutation that changes what’s unread — message delete, wipe, repair, rehome — pushes a fresh message-waiting state to the devices of the line bound to the box automatically. There is no “refresh MWI” call to make; if lamps have drifted out of sync with reality, that’s what repair is for.