Skip to main content

Voice Settings Consoles

Voice runs on a set of organization-level policy knobs that decide how calls are placed, answered, routed, and capped. Eight of these policies ship as paired GET/PUT endpoints under /api/v1/voice/*, so you can inspect and change them from the dashboard or from your own tooling with an API key. This guide covers each setting: what it changes, which endpoints read and write it, the organization settings key it persists, where it appears in Settings → Voice in the dashboard, and runnable curl + Node.js samples you can paste into your own tooling. For rejected STT or TTS keys in the voice inference provider console, see Troubleshooting: voice inference credential rejected.

Access controls

The same two rules guard every endpoint on this page:
  • Admin only. Read and write both require an owner/admin role (or an API key scoped for voice administration). Members without the admin role cannot read or change these policies. Rotate and scope those keys with the API key lifecycle and rotation runbook before wiring scripts into production.
  • Rate limited. Reads run under the standard voice read limit; writes run under a tighter voice write limit, so a misbehaving integration cannot thrash the policy.
Every write replaces the whole policy object for that setting and is recorded in the audit log (Settings → Audit log), so changes are attributable and reviewable. GET responses and PUT bodies use the same shape — what you read is exactly what you PUT back. Each response echoes the persisted object under the section’s settings.<key> (for example, settings.acd_auto_answer), so a GET tells you exactly which organization field a PUT would rewrite. The snippets below authenticate with an X-API-Key header and target https://api.orbit.devotel.io/api/v1. The Node examples use the untyped orbit.request(method, path, body) helper from the @devotel-orbit/node SDK.

Dialing-class restrictions

Control which call classes each user or extension may place: toll-free, domestic, international, or premium. Set a default for the organization and tighten specific users where needed — for example, block international dialing for everyone except the collections team.
  • Read: GET /api/v1/voice/dialing-restrictions
  • Write: PUT /api/v1/voice/dialing-restrictions
  • Settings key: settings.voice.user_dialing_restrictions
  • Dashboard: Settings → Voice (API-only today — no console section yet; manage through the endpoints).
The response echoes the current restriction object under settings.voice.user_dialing_restrictions:
users overrides the default per user ID; premium_prefixes lets you list E.164 prefixes that always count as premium. Enforcement happens when an outbound call is initiated — a denied class returns an error before any ring-out.

Skill-proficiency decay

Agents’ skill ratings fade automatically when a skill goes unused, so routing weights recent handling history instead of an agent’s stale, all-time score. A scheduled sweep applies the decay bands you define.
  • Read: GET /api/v1/voice/skill-proficiency-decay
  • Write: PUT /api/v1/voice/skill-proficiency-decay
  • Settings key: settings.acd_skill_proficiency_decay
  • Dashboard: Settings → Voice (API-only — manage through the endpoints).
The response echoes the current decay policy under settings.acd_skill_proficiency_decay:
Each band caps the proficiency level (1–5) once the agent’s remaining evaluation window drops to that fraction. List regulated or rarely-used skills in exemptSkills so the sweep never decays them. The policy supports up to 10 bands and 200 exempted skills.

Max call duration

Set a hard ceiling on live ACD call length. Queues govern waiting, wrap-up, and idle time; this setting governs the call itself. Use it when you bill per minute, run collections scripts with a fixed cadence, or want a backstop against runaway calls.
  • Read: GET /api/v1/voice/max-call-duration
  • Write: PUT /api/v1/voice/max-call-duration
  • Settings key: settings.acd_max_call_duration
  • Dashboard: Settings → Voice (API-only — manage through the endpoints).
The response echoes the current duration cap under settings.acd_max_call_duration:
maxSeconds accepts 60 to 14,400 (one minute to four hours). When enabled, the inbound call leg auto-disconnects at the limit. The default is disabled with the platform ceiling of four hours — the legacy behaviour for every existing tenant.

ACD auto-answer

Deliver ACD calls straight to the agent’s endpoint without it ringing — the desk phone answers the call leg automatically, optionally preceded by a short zip tone so the agent knows a call was dropped onto the line. Standard headset-operations behaviour in a contact center.
  • Read: GET /api/v1/voice/acd-auto-answer
  • Write: PUT /api/v1/voice/acd-auto-answer
  • Settings key: settings.acd_auto_answer
  • Dashboard: Settings → Voice (API-only — manage through the endpoints).
The response echoes the current auto-answer policy under settings.acd_auto_answer:
The zip tone only applies when auto-answer itself is enabled. Default disabled preserves ring-until-answered behaviour; enable it per organization when your agents run dedicated headsets.

Shared speed dial

Publish an organization-curated speed-dial and busy-lamp-field (BLF) list — front desk, sales hotline, on-call — to every desk phone, ahead of the automatic teammate roster. Entry values are validated as internal extensions only; external numbers are rejected, so one-touch dialing always stays on-net.
  • Read: GET /api/v1/voice/shared-speed-dial
  • Write: PUT /api/v1/voice/shared-speed-dial
  • Settings key: settings.voice_shared_speed_dial
  • Dashboard: Settings → Voice (API-only — manage through the endpoints).
The response echoes the current curated list under settings.voice_shared_speed_dial:
type is blf (monitored lamp field) or speed_dial (one-touch dial). Desk phones pick up the list through their provisioning fetch; a preview of the resolved key layout appears on the device detail page.

Affinity routing

Route each inbound contact to the best-matched agent rather than the globally best-scoring one. Affinity tags on agent profiles (segment, language style, topic fit) are weighed against the resolved caller’s attributes — a behavioral-affinity pairing objective, opt-in per organization.
  • Read: GET /api/v1/voice/affinity-routing
  • Write: PUT /api/v1/voice/affinity-routing
  • Settings key: settings.acd_affinity_routing
  • Dashboard: Settings → Voice (API-only — manage through the endpoints).
The response echoes the current affinity policy under settings.acd_affinity_routing:
treatment_percent (0–100) is the share of calls scored on the affinity arm; the weights balance contact-to-agent fit against load headroom. agent_profiles maps a user ID to up to a bounded set of affinity tags. Default off — matching stays purely score-based until you enable it.

Attribute routing

Match the resolved caller’s contact tags and attributes against an ordered rule list before the call enters a queue, adding skills and a priority boost on the first matching rule. Use it for VIP routing, language detection, or tier-based escalation.
  • Read: GET /api/v1/voice/attribute-routing
  • Write: PUT /api/v1/voice/attribute-routing
  • Settings key: settings.acd_attribute_routing
  • Dashboard: Settings → Voice — this one has a full console section (edit the rule list inline, no API calls needed).
The response echoes the current rule list under settings.acd_attribute_routing:
Rule kinds are tag (matches a contact tag value), attribute_equals (string field equals a value), and attribute_gte (numeric field at or above a threshold). Each rule can add skills and an optional integer priorityBoost (0–99). Up to 50 rules; only the first match applies.

SIP max registrations per extension

Cap how many distinct SIP endpoints may hold a live registration for one extension. Without a cap, nothing prevents a registration flood on a shared credential or an unbounded number of hot-desking devices binding the same extension.
  • Read: GET /api/v1/voice/sip-max-registrations
  • Write: PUT /api/v1/voice/sip-max-registrations
  • Settings key: settings.sip_max_registrations_per_extension
  • Dashboard: Settings → Voice (API-only — manage through the endpoints).
The response echoes the current registration cap under settings.sip_max_registrations_per_extension:
maxRegistrations accepts 1 to 50. The registration itself is checked at login: a device binding past the cap is rejected until another endpoint unregisters. Disabled (the default) restores unlimited registrations — the legacy behaviour.

Worked sequence

Any of the eight policies follows the same read-modify-write loop. This sequence gates a live call through GET → modify → PUT → re-GET so you can trust the persisted state before relying on it in a dial plan:
  1. Read the current policy with GET /api/v1/voice/<setting> and save the response.
  2. Modify the object locally. Preserve the whole blob — these endpoints replace the policy, not merge it.
  3. Write the full object back with PUT /api/v1/voice/<setting>. The server validates the body and returns 422 on the first invalid field, so a half-finished edit never lands.
  4. Re-read with a second GET and compare the echoed settings.<key> to what you submitted. A match confirms persistence; a mismatch means a sibling write raced you — re-read and apply again.
Two production notes:
  • The audit log (Settings → Audit log) records every PUT, so the second GET doubles as your verification step: the row you wrote is attributable and reviewable.
  • If a PUT returns 429, back off and retry — the write limit is intentionally tighter than the read limit, and the window resets quickly.

Troubleshooting

  • 403 on GET or PUT — your role or API key lacks voice admin access. Have an owner grant it, or establish the key through the API key lifecycle and rotation flow.
  • 422 / 400 on PUT — the body failed validation; the error lists each invalid field. Fetch the current policy with GET, correct it, and re-submit.
  • 429 — you hit the read or write rate limit. Back off and retry; the limits reset on a short window.
  • A setting behaves like it is off after a PUT — enabled: false (or a malformed earlier blob) resolves to the safe default. Confirm the saved object with a GET.