> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Jambonz verb extensions in Devotel Orbit: what the platform layers on

> Orbit's voice engine runs on Jambonz verbs. This page catalogs the extension layer Orbit adds on top: dialed feature codes, trunk and tenant guards, billing events, whisper coaching, mid-call recording, and the resolver that wires a handset keypress into a verb chain.

Orbit's voice plane is built on [Jambonz](/concepts/jambonz-softswitch), the open-source voice engine. Every call Orbit handles is ultimately described as a sequence of Jambonz verbs. What Jambonz documentation will not tell you is how much Orbit layers on top of the stock verb catalog: a feature-code resolver for desk phones, guard verbs that enforce tenant isolation and SIP-credential policy, billing verbs that float money mid-call, and coaching verbs that whisper context into a transfer. This page is the catalog of that extension layer, written for voice developers evaluating or building on Orbit.

One framing rule before the catalog: every extension described here runs inside Orbit's voice engine and depends on Orbit services (tenant schemas, the billing wallet, the Devotel wholesale softswitch for egress). They are not portable to a stock Jambonz install, and this page does not promise a public verb-authoring SDK. It documents what ships today.

## The Jambonz baseline

The upstream verb set is the substrate everything below sits on. In one sentence each:

* `dial` connects the call to another endpoint: a SIP extension, a queue, or the PSTN through the softswitch.
* `say` renders text to speech to the caller.
* `play` streams an audio file to the caller.
* `gather` collects DTMF digits or speech from the caller.
* `pause` holds the call silent for a set interval; Orbit also uses it as the parking primitive while devices ring.
* `record` captures the call, including SIPREC hand-off to an external recording server.
* `conference` bridges the caller into a named room.
* `redirect` sends the call to a new verb sequence, which is how Orbit re-hooks a call when its disposition changes.
* `hangup` terminates the call.

If a behaviour you need maps cleanly onto one of those verbs, Orbit passes it through unchanged. The rest of this page is what Orbit adds around them.

## The Orbit extension layer

Each row is a verb-shaping concern in the voice engine, named by the behaviour it produces rather than by internal module names.

| Extension | What it adds on top of stock Jambonz |
| - | - |
| Feature-code dispatch | Star codes dialed from a registered desk phone (`*78` DND on, `*79` DND off, `*97` voicemail check, `*57` malicious-call trace, `*1` through `*9` park retrieve) resolve to a spoken confirmation plus hangup, or a conference join for retrieval. Codes follow the RingCentral / 8x8 / Zoom Phone conventions your users already have muscle memory for. |
| Trunk reject verbs | When a customer SIP trunk INVITE fails digest authentication or policy, the caller hears a sanitized reject announcement instead of dead air. Reject reasons are capped and header-sanitized so a hostile PBX cannot smuggle content into the announcement. |
| Conference wait music | Hold verbs that bridge early arrivals into music-on-hold before a conference starts, with a shared handler deadline so a stuck wait hook cannot wedge the room. |
| Inbound disposition lock | A parked inbound call can be answered from several producers at once (two softphone tabs, a decline, a park timeout). A race-safe lock makes exactly one of them win, so the call record gets one disposition code, not conflicting mutations. |
| Inbound route org guard | A defense-in-depth guard that drops an inbound call whose routed organization no longer owns the dialed number, closing a cross-tenant hijack window on the inbound routing table. |
| Inbound wake retry | Mobile softphones have no live SIP registration while backgrounded. When a push wakes the device, this retry re-attempts the ring after the phone re-registers, instead of ringing a dead socket and logging a 410. |
| On-net loopback | When an extension or customer PBX dials a number that is actually the same org's own platform DID, the call stays on-platform instead of hair-pinning through the PSTN. Tenants without a configured trunk no longer fail on internal calls. |
| Personalized announce | Queue waiting announcements with per-caller variable substitution ("Hi Sarah, you are number 3 in line"), resolving the caller profile from your contacts, in the style of Five9 and NICE native announcements. |
| IVR node analytics | Every IVR node emits visit, exit, and abandonment events, so you can answer "which prompt sheds 30% of callers?" A partially migrated tenant never breaks a call over analytics: emission is fire-and-forget. |
| Mid-call recording | A single canonical SIPREC `record` shape for start and stop, fixing the class of 400s that came from callers shipping incomplete record payloads one field at a time. |
| SIP credential concurrency | An atomic Redis-enforced cap on concurrent calls per SIP credential, closing the race where two simultaneous dials both read "one slot free" and oversubscribe the extension. |
| SIP credential DND | Do-not-disturb is honoured per device at the verb layer: a credential with DND on simply does not ring, matching the toggle in the extension settings. |
| Warm-transfer whisper | When agent A warm-transfers to agent B, an AI summary of the conversation is stashed and played to agent B as a `say` verb before the bridge, so B hears the context pop, not a cold hello. This is the verb behind [whisper coaching](/guides/agent-assist-whisper-coaching). |
| Supervisor bridge | The verb hook that inserts a supervisor into a live call as listen, whisper, barge, or takeover, extracted as its own concern so the four modes share one bridging path. |
| Application self-heal | An attempt ledger for the last-resort repair that restores a missing default Jambonz application when configuration drifts, so conference creation heals itself with an audit trail instead of failing opaque. |

Two adjacent concerns shape verbs without being verbs themselves: the voice DSL executor sanitizes tenant-supplied verb sequences fetched from your webhook answer URLs (Jambonz validates verb shape, not policy, so Orbit enforces the policy side), and the DSL signing layer HMAC-signs those webhook fetches so your verb endpoint can verify requests genuinely come from Orbit.

## Billing-integrated verbs

Three extensions exist purely to move money correctly, and each maps to a wallet ledger entry:

1. **Pre-call hold.** Every outbound origination (dial-confirm, click-to-call, conference participant adds, warm-transfer consult legs) places a small advance hold with a deterministic idempotency key before the call leaves the platform. An insufficient wallet balance rejects the dial with a 402 rather than placing an unpaid call. Ledger entry: a hold against the org wallet at dispatch.
2. **Final charge.** When a call reaches a terminal state with a known duration, the finalizer debits actual usage against the hold and releases the difference. Zero-duration and never-connected legs are refunded by the stuck-call sweep, so the finalizer only ever settles answered calls. Ledger entry: the final per-minute charge reconciling the hold.
3. **Hold pause.** A hold-billing mode that pauses accrual while a call is deliberately held, so customers are not charged active rates for their own hold time. Ledger entry: a pause marker that bounds the billable window.

The dialer side has its own gate: per-org dialer billing resolution decides which org wallet a dialer attempt is charged to before the feedback branch records the attempt, so multi-org dialer campaigns bill the right entity per attempt.

## Feature-code resolver walk-through

A desk phone has no dashboard. The resolver is what makes the handset a first-class citizen: it turns whatever Jambonz forwards as the dialed destination into a typed feature-code match, and the verb layer renders that match into verbs.

The lookup chain, in order:

1. **Normalize.** The dialed `To:` value arrives as bare digits, a full SIP URI, a `tel:` URI, or with a trailing `#` send key. Normalization strips scheme, host, URI parameters, and the send key, leaving the bare code. Malformed input never throws; it resolves to "not a feature code."
2. **Exact table match.** `*78`, `*79`, `*97`, and `*57` match against the fixed code table first.
3. **Pattern match.** Single-digit `*1` through `*9` match the park-retrieve pattern. Two-digit codes never collide with it because the table runs first.
4. **Deliberate non-match.** Call forward (`*72` / `*73`) returns null today by design: unconditional forward is stored per user, and resolving a credential to a user is a link the platform does not yet maintain, and `*72` carries a follow-on destination that the say-and-hangup feature-code shape cannot model. Shipping a half-built handler is worse than saying "not a valid feature code."
5. **Verb render.** A match renders into its verb chain: confirmation plus hangup for toggles, mailbox playback for `*97`, a conference join into the park lobby for retrieval.

A concrete scenario, `*3` (retrieve the call parked in slot 3):

1. The handset dials `*3`; Jambonz posts the lookup with `To: sip:*3@…`.
2. Normalization yields `*3`; the table misses; the park pattern matches with slot 3.
3. The handler claims the parked call in slot 3 for this org and receives the immutable parked-call id.
4. The verb layer renders a `conference` join into the park lobby holding that parked caller, bridging the retrieving handset to the waiting party. The lobby is keyed on the parked-call id, not the slot, so a second park reusing slot 3 can never strand the first caller.
5. If slot 3 is empty, the caller hears "no call parked on 3" and the call ends cleanly.

The same normalization and table drive `*78` and `*79`, which flip the DND boolean on the credential the desk phone registered as, and `*97`, which resolves the mailbox through the credential's registered inbound routes and plays unheard messages back over the keypad call. See the [call park lobby concept](/concepts/voice-call-park-lobby) for the park half of the loop.

## Abandoned-safe-harbor: the tenant-owned abandoned-call guard

When a predictive dialer abandons a call (no agent available after the called party answers), the dialer's operator is on the hook for what the caller hears. The safe-harbor guard plays the identification message the abandoned-call rules require: the business name on whose behalf the call was placed, that the call was placed on behalf of a telemarketer, and the do-not-call contact information, delivered within the required window after greeting.

Two things to be precise about:

* **It is a tenant-owned guardrail.** The guard runs for tenants who run predictive dialing and configure the abandoned-call message from their own business identity. It is not a platform-wide compliance claim: Orbit provides the mechanism and the timing, and the content and the legal sufficiency of what plays belong to the tenant running the dialer.
* **It cites, it does not generalize.** The message shape tracks the abandoned-call safe-harbor provisions for predictive dialers. If your campaign is not predictive dialing, this guard is not your compliance story; your quiet-hours, suppression, and consent obligations live in the [federal voice guard documentation](/concepts/tcpa-federal-voice-guard).

## Building on the extension layer

There is no public verb-authoring SDK, and this page does not promise one. What exists today is a clear internal landing pattern, documented so platform contributors extend the layer in one place:

* A new verb concern lands as its own module beside the jambonz route surface, owning its handler and verb rendering, with the route registered by the bridge plugin so the public route surface stays stable.
* Tenant-supplied verb sequences flow through the DSL executor, which is where policy sanitization happens. Anything that accepts verbs from outside the platform must pass through it, not around it.
* Webhook fetches of tenant verb sequences are signed with the DSL signing layer; a new fetch path must carry the signature or your endpoint has no way to authenticate Orbit.
* SIP header reads use the shared case-insensitive header helpers, because upstream proxies rewrite header casing arbitrarily. One matching semantic, one place.
* State that must survive a replica restart (whisper stashes, park claims, concurrency counters) lives in Redis with a TTL and an idempotency key, never in process memory.
* Software that mutates voice-edge state as a self-heal writes to an attempt ledger first. A heal without a trail is indistinguishable from drift.

## Where these verbs fire in the lifecycle

One inbound call, in order:

1. **Ingress.** The INVITE arrives at the voice edge; header helpers extract org and tenant identity from SIP headers regardless of casing.
2. **Guard.** The inbound route org guard verifies the routed organization still owns the dialed number; a deleted or hijacked route drops here.
3. **Credential policy.** For registered extensions, the concurrency cap and DND filters run before anything rings.
4. **Resolution.** The lookup decides the route type: a feature code resolves through the resolver; a webhook route fetches tenant verbs through the signed DSL path; an outbound origination consumes its stashed call flow.
5. **Verb chain.** The IVR or queue runs, with per-node analytics emitting on every visit, exit, and abandonment, wait music and personalized announces rendering in queues, and mid-call recording startable from the dashboard at any point.
6. **Billing.** The hold lands at dispatch, the hold-pause mode bounds held time, and the finalizer settles the charge at terminal state.
7. **Disposition.** The disposition lock records exactly one outcome for the call, even when several producers race to answer.
8. **Aftermath.** Quality metrics (MOS, jitter, packet loss) ingest per call, and transcripts and analytics land where the dashboards read them.

Outbound calls run the same spine in reverse order of concern: billing hold and org gate first, then egress exclusively through the Devotel wholesale softswitch, then the same disposition and quality tail.

## Related reading

* [Conference rooms](/guides/voice-conferences): the rooms the wait-music, supervisor bridge, and park-lobby verbs feed.
* [Voicemail boxes](/guides/voice-voicemail-boxes): the mailbox the `*97` feature code plays back over a keypad call.
* [Whisper coaching](/guides/agent-assist-whisper-coaching): the coaching surface the warm-transfer whisper verb drives.
* [Number masking privacy sessions](/guides/number-masking-privacy-sessions): proxy sessions whose on-net traffic the loopback verb keeps on-platform.
* [Jambonz softswitch concept](/concepts/jambonz-softswitch): the upstream engine this layer extends.
* [Call park lobby](/concepts/voice-call-park-lobby): the park half of the `*1` through `*9` retrieve codes.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.