Skip to main content

Hold and pause reason codes

A hold reason code says why an agent placed a caller on hold; a pause reason code (also called an aux code) says why an agent is away and not taking calls. Tagging either one turns an anonymous duration — 4 minutes on hold, 22 minutes away — into a supervisor-readable fact: verifying information, consulting a colleague, lunch, training. Both catalogs cover the same reporting questions from different sides, so they share this page:
  • Hold reason codes attach to a live call. The catalog is fixed by the platform; agents pick from it but you cannot add entries.
  • Pause reason codes attach to an agent’s availability state. The catalog ships platform defaults, and owners and admins can add their own codes to match their operation.
Base path: /api/v1/voice Authentication: Clerk session (Authorization: Bearer <token>) or API key (X-API-Key). Scope: voice:read to list either catalog. Create, update, and delete on the pause catalog require the owner or admin role; the hold catalog is read-only for everyone.

Hold reason codes: why the caller is on hold

Agents still place a caller on hold the same way they always have — from the softphone or with POST /api/v1/voice/calls/{callId}/hold. A hold reason code is the optional tag attached with that hold so the hold has context instead of being an unexplained gap. The catalog is a fixed platform list — the reasons Five9, Genesys, and NICE each ship out of the box, consolidated into one set. It is not tenant-editable, and that is deliberate: hold reasons are short and occur per call, so every tenant reads the same seven options and supervisor roll-ups compare like with like. Codes are lowercase slugs matching ^[a-z0-9_-]+$. They are stable across releases — a code you tag today resolves to the same label in a year, so historical reporting never dangles. Because the catalog is code-defined in the platform itself, it exists for every tenant without any migration or setup.

Attaching a hold reason

The softphone hold picker lists the catalog, and the agent taps it as they place the caller on hold:
The code is normalised (trimmed and lowercased), so Consulting and consulting resolve to the same tag. An unknown slug is rejected with 422 — the error response includes the valid codes, so a typo never becomes a silent untagged hold, and your integration never has to guess at the catalog. What happens to the tag:
  • The reason is stored on the call record itself — hold_reason and its resolved hold_reason_label land in the call’s metadata alongside the hold start timestamp. No catalog row to reference, no schema change to deploy.
  • Releasing the hold clears the tag. When the agent resumes the call, the current hold’s reason slate resets; the pattern is “what is the current hold for,” not a standing flag.
  • The reason is optional. POST .../hold with no body works exactly as before — long-standing integrations that never send a reason_code keep working unchanged.
Supervisors see the label on the live wallboard while the hold runs, and it carries into after-call reporting once the call ends — see Reporting below.

Pause (aux) reason codes: why the agent is away

Pause reason codes tag agent availability, not a call. When an agent flips from available to an away state — lunch, break, training — they pick a reason. Those reasons do two jobs: they give supervisors a readable wallboard, and they give WFM adherence something precise to measure scheduled time against. Unlike hold reasons, this catalog is tenant-extendable. The platform ships defaults, and owners and admins add their own:
  • Defaultslunch, bio, training, break, coaching. These are always available to every tenant and cannot be shadowed by a tenant row.
  • Tenant additions — domain-specific reasons like team_standup, qa_review, or a shift supervisor’s one_on_one. Tenant codes carry a display label, an optional per-reason duration ceiling, and an active flag they can flip to retire a code without orphaning history.
Each tenant row carries code (the same ^[a-z0-9_-]+$ slug shape), display_label, an optional max_seconds ceiling, and active. A code created while inactive is staged but invisible to pickers until activated; deactivating is a soft-delete, and agents who used the retired code keep its label in historical records. Agents pick a reason when they set their own away state; supervisors and admins can also set it for an agent from the agent-activity surface. The resolved reason shows up:
  • On the wallboard — the away tile renders the label next to the away duration, so a glance tells “three on lunch, two in training” from “two missing agents.”
  • In the agent activity feed — every state change is recorded with the reason code, so a day-review can reconstruct when each agent went away and for what.
  • In WFM adherence — the reason an agent set is read against their scheduled activity, so an unscheduled meeting reads differently from a scheduled training deviation. See Workforce-management workflows for how adherence consumes the feed.
Agents flipping status can only send a code from the union of platform defaults and the tenant’s active additions — a response of 422 names the allowed set on an invalid attempt, so a rogue integration never produces a reason supervisors cannot report on. Pause codes have a per-reason duration ceiling (max_seconds). When an agent stays in a reason longer than its ceiling, a supervisor alert fires — a reason-coded overrun, such as lunch over 30 minutes. Leave the ceiling blank to defer that to a manual supervisor nudge.

Reporting: what the tags buy you

Hold and pause reasons share one purpose: they answer “how long, and was that time justified.”
  • After-call reporting — a call that spent 4 minutes on hold now reports 4 minutes — Consulting a colleague instead of an unexplained block. Hold mix (how much of handle time is hold, broken down by reason) becomes a coaching input instead of an anecdote.
  • Supervisor hold-time alert — when a caller sits on hold past the threshold (60 seconds by default), the wallboard emits a long-hold alert. The reason tag is alongside the duration, so the supervisor triaging “who needs a hand” sees Awaiting supervisor and acts on it instead of walking to the agent’s desk to ask.
  • Pause reporting — adherence exceptions, shrinkage, and break-overrun alerts all segment by reason. “Away 12% of staffed hours” is a very different problem when most of that 12% is approved training versus when it is a miscellany of uncoded absences.
Without the tag, none of this is askable — you only see the duration. With it, every duration carries its why.

API examples

All examples use https://api.orbit.devotel.io/api/v1/voice with a session token or API key. Replace call_01HZK… and the pause-code id with real values from your tenant.

List the hold-reason catalog

Read-only; any authenticated user can call it. Static — this endpoint never touches a tenant schema.

Hold a call with a reason, then release it

An invalid code returns 422 with the full valid catalog in error.details.validCodes, so a picker can re-render from the response without a second fetch.

Read hold history for a call

The tagged holds live on the call record. Fetch the call to see each hold segment with its reason:
The response includes the current hold_reason and hold_reason_label in the call’s metadata while the call is held, and the hold duration stamps (hold_started_at, unhold timestamps) that after-call reporting aggregates.

List the pause-reason catalog (defaults + tenant codes)

Active rows only by default. Add ?include_inactive=true to render the archived set in an admin editor.

Add a tenant pause reason (owner or admin)

A duplicate active slug returns 409; retiring and recreating is the way to replace a label. Code slugs are case-normalised at the boundary — send them lowercase.

Update or retire a tenant pause reason (owner or admin)

Reactivate with PATCH { "active": true }.

Set an agent’s away state with a reason

Agents (and admins acting for an agent) post the status change with a reason from the union of defaults and active tenant codes:
422 names the allowed set if the code is not found, so the picker always stays aligned with the catalog it rendered from.

Edge notes

  • Reasons are optional everywhere. A hold posted with no body, or a status flip with no reason_code, behaves exactly as before the catalogs existed — no breaking change for integrations built before this.
  • Hold catalog slugs are stable across releases. The seven platform codes never change name; report queries keyed on code are safe to persist.
  • Tenant additions only apply to pause codes. There is no tenant extension point for hold reasons — that is a deliberate parity choice, not an oversight, since a per-call picker should never need domain training.
  • Pause code slugs are immutable once created. Retire (soft-delete) and recreate to rename; a hard rename would orphan the audit and adherence records that carry the slug.
  • Codes normalise. Consulting, consulting, and consulting are the same tag; keep your integration storing the canonical lowercase slug.
  • The catalogs are tenant-scoped for pause, global for hold. One tenant’s added pause reasons are invisible to others; the hold catalog is identical for everyone.