Skip to content

Managed-Mode Resources

A namespace in managed resource-authority mode authors its subscriber resources — lines, devices, trunks, ring groups, voicemail boxes, and namespace linkages — through per-entity REST endpoints instead of the YAML document. It exists for the shapes where a config document stops scaling: tens of thousands of lines, or a provisioning system that churns individual subscribers all day and wants one API call per change, not a version-and-apply cycle around each.

Most managed-mode users drive these endpoints from their own integration code, so this page sketches the model and the basic flows rather than walking every field — the request bodies mirror the YAML resource schemas one-to-one (see the Namespace Resources reference for field meanings), and the API appendix has the full per-endpoint detail. Conventions as usual: $VSS, $TOKEN, $NSID; vsscli commands live under vsscli resource … (aliases res, resources).

Authority mode is chosen at namespace creation and never changes (POST /v1/ns?authority=managed — see namespace administration). In a managed namespace the split is:

Authored via /resources API Still authored in YAML (config versions + apply)
Lines, devices, trunks, ring groups, voicemail boxes, ns-linkages Everything those resources reference: line/trunk profiles, translation / voicemail / caller-ID / screening contexts, routes, recordings, feature codes, configuration: keys

A managed namespace’s YAML rejects the resource sections outright — the two authorities never overlap. The config document keeps its whole lifecycle (versions, validate, apply); it just carries policy, not subscribers.

The write semantics are deliberately different from document mode:

  • Effective immediately. A resource write hits call processing as soon as it lands — no version, no apply, and therefore no rollback and no staged/latest state. Your integration’s audit trail is the change history.
  • Validated per entity, not per document. Each write is checked against the running config body (does the profile/context exist?) and the current resource rows (does the referenced device/box exist?), and refused with a 400 naming the missing reference. What is not checked is the reverse direction: deletes don’t cascade and don’t look for dangling references — removing a device still listed by a line simply leaves the line pointing at nothing. Write ordering is your integration’s job: create referenced things first, delete referencing things first.
  • Runtime surfaces are unchanged. Voicemail state, line features, and device credentials work exactly as the rest of this section describes — rt vm, rt line, and peer password don’t care which authority mode defined the resource.

The /resources tree has its own action pair so definition authoring can be delegated separately from config authoring:

Action Held by
resource:read partition-admin, namespace-admin, operator, editor, provisioner, viewer, system-auditor
resource:write Same, minus viewer / system-auditor

provisioner is the intended role for subscriber-churn integrations: resource definitions, device credentials, and voicemail admin, with no config authoring or namespace lifecycle.

Every resource family follows the same pattern under /v1/ns/{nsid}/resources/:

Family List Get one Create/replace Merge-patch Delete Bulk
lines/{line} PUT PATCH
devices/{device} PUT
trunks/{trunk} PUT
ring-groups/{group} PUT
vm-boxes/{context}/{box} PUT
linkages/{peer} PUT PATCH

PUT is create-or-replace with the full body; PATCH (lines, linkages) is a tri-state merge-patch — absent key untouched, present key applied, blank clears. Bulk (POST …/bulk with a JSON array) is best-effort: each item is validated and written independently, and the response carries a per-item success/error list in order — one bad row doesn’t abort the rest. Bulk exists for the families that churn at subscriber scale (lines, devices, voicemail boxes, linkages).

Calling any of these on a document-mode namespace answers 409 — the same request body belongs in the YAML there.

The basic flow: one subscriber, end to end

Section titled “The basic flow: one subscriber, end to end”

Assume the running config body already defines a standard line profile and voicemail context (that part is YAML, applied once). Provisioning a subscriber is then four calls, ordered so every reference exists before something names it:

Terminal window
# 1. Mailbox definition
curl -s -X PUT "$VSS/v1/ns/$NSID/resources/vm-boxes/standard/1001" \
-H "Authorization: Bearer $TOKEN" -d '{}'
# 2. Device (creates its SIP peer — auth before routing)
curl -s -X PUT "$VSS/v1/ns/$NSID/resources/devices/alice-desk" \
-H "Authorization: Bearer $TOKEN" -d '{"line":"1001"}'
# 3. The line, tying it together
curl -s -X PUT "$VSS/v1/ns/$NSID/resources/lines/1001" \
-H "Authorization: Bearer $TOKEN" -d '{
"line_profile": "standard",
"voicemail": "1001",
"caller_id": "+13055551234",
"devices": ["alice-desk"]
}'
# 4. Mint the device credential (see Device Credentials)
curl -s -X POST "$VSS/v1/peer/alice-desk@pbx.acme.example/setpass" \
-H "Authorization: Bearer $TOKEN"

The subscriber is live the moment step 3 returns — the phone registers as soon as step 4’s credential is configured on it. Inspect and adjust the same way:

Terminal window
curl -s "$VSS/v1/ns/$NSID/resources/lines" -H "Authorization: Bearer $TOKEN"
curl -s "$VSS/v1/ns/$NSID/resources/lines/1001" -H "Authorization: Bearer $TOKEN"
# Merge-patch: change one field, everything else untouched
curl -s -X PATCH "$VSS/v1/ns/$NSID/resources/lines/1001" \
-H "Authorization: Bearer $TOKEN" -d '{"caller_id":"+13055559999"}'

Deletion is the mirror of provisioning: detach references before deleting what they point at. Each delete cleans up its own runtime state — a line delete purges the line’s feature rows (DND, forwards, speed dials, same as when a line leaves a document-mode config), a device delete drops its SIP auth before its routing, and a vm-box delete purges messages and greetings. What deletes never do is cascade across resources: removing a line does not remove its devices or mailbox.

Terminal window
# The line (stops calls, purges feature state), then its devices
# (drops SIP auth first, then routing), then the mailbox
curl -s -X DELETE "$VSS/v1/ns/$NSID/resources/lines/1001" -H "Authorization: Bearer $TOKEN"
curl -s -X DELETE "$VSS/v1/ns/$NSID/resources/devices/alice-desk" -H "Authorization: Bearer $TOKEN"
curl -s -X DELETE "$VSS/v1/ns/$NSID/resources/vm-boxes/standard/1001" -H "Authorization: Bearer $TOKEN"

Conversely, a vm-box definition PUT never touches runtime state — you can re-PUT a box (or rebind a distribution list’s members) without clobbering its PIN, messages, or recorded greetings.

Same verbs, same semantics; the bodies mirror their YAML counterparts (trunks, ring groups, linkages). Two trunk-specific conflict rules are enforced at write time, both 409s: a source IP claimed by another namespace on the same edge proxy, and a source IP claimed by another trunk in the same namespace (inbound classification is by exact source IP, so an IP must have exactly one owner).

A linkage’s inheritance block is part of the managed body like any other field — the profile, granted aliases, concurrency cap, and the permitted edge-IP / SIP-realm envelope a managed parent imposes on a child are all writable via PUT and merge-patchable via PATCH, and constrain the child’s config from its next apply.

Response Meaning Do
409 “resources are document-authored” The namespace is in document mode Author this in the YAML instead; authority is immutable
400 naming a missing reference The profile/context/box/device you referenced doesn’t exist Create it first (YAML apply for config-body refs, a /resources PUT for row refs)
409 device peer conflict The device name (at this realm) is claimed by another namespace Pick another device name
409 trunk IP conflict Source IP owned by another namespace on this edge proxy, or by another trunk here Resolve ownership; one IP, one owner
404 on GET/PATCH/DELETE No such resource row — the problem type names the family (line-not-found, device-not-found, …) Managed resources exist only once PUT — there is no “in config but not applied” state
Bulk returns mixed results Best-effort semantics Inspect the per-item results array; retry the failures