Skip to content

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.

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.

Terminal window
# 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 boxes
curl -s "$VSS/v1/ns/$NSID/vm/boxes/standard" -H "Authorization: Bearer $TOKEN"
# One box in detail
curl -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}

Reading the detail:

  • unread / read / urgent_unread — the live counters that drive message-waiting lamps. urgent_unread is 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 normally true; false means 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.

Terminal window
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"}]}
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.

Message audio streams as audio/wav:

Terminal window
curl -s "$VSS/v1/ns/$NSID/vm/boxes/standard/1001/messages/01J1FZK7Q0X5B3M8QW9RS2T4VE" \
-H "Authorization: Bearer $TOKEN" -o message.wav

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.

Terminal window
curl -s -X DELETE "$VSS/v1/ns/$NSID/vm/boxes/standard/1001/messages/01J1FZK7Q0X5B3M8QW9RS2T4VE" \
-H "Authorization: Bearer $TOKEN"

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.

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.

Terminal window
# Download the current default greeting
curl -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 slot
curl -s -X DELETE "$VSS/v1/ns/$NSID/vm/boxes/standard/1001/greetings/temp" \
-H "Authorization: Bearer $TOKEN"

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:

Terminal window
# 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 set
curl -s -X POST "$VSS/v1/ns/$NSID/vm/boxes/standard/1001/pin/reset" \
-H "Authorization: Bearer $TOKEN"
  • 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).

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.
Terminal window
# A present key is applied; a missing key is a no-op
curl -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.

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:

Terminal window
vsscli user create --username sub-1001 --owner-scope ns:$NSID
vsscli 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.

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.