Skip to main content

Wrap-up Codes and Disposition Enforcement

A wrap-up code (also called a disposition or reason code) is the outcome an agent records when a conversation ends — Sale completed, Wrong number, Follow-up needed. Orbit lets you define those codes per queue and, when you choose to, require that an agent records one before they can take the next conversation. This page covers the wrap-up catalog for inbound voice (ACD) queues and the matching enforcement on digital (inbox) queues. For the outbound-dialer disposition matrix that routes contact lifecycle statuses, see Dialer dispositions. Base path: /api/v1/voice Authentication: Clerk session (Authorization: Bearer <token>) or API key (X-API-Key). Scope: voice read for catalog reads, voice write for recording; catalog management endpoints are restricted to owners and admins.

The catalog: codes you configure per queue

Each queue carries its own catalog of disposition rows. A row has:
  • code — the lowercase slug agents (or the softphone) post back (for example sale_completed). It is immutable once created; retire and recreate to rename.
  • label — the human-readable text the picker shows.
  • parentId — optional nesting one level deep, so you can group codes under a heading (for example SaleNew, Upsell, Renewal).
  • sortOrder — picker display order.
  • requiredOnTerminate — when true, the picker marks the row as required; when false, the row is optional context the agent may skip. This flag only matters when the queue-level gate is on.
  • noteTemplate — optional starter text the softphone pre-fills into the wrap-up note field when the agent picks this code, so repetitive annotations (case reference, refund amount) start from your wording instead of a blank box.
  • isActive — retiring a code is a soft-delete. Past conversations keep resolving the code’s label for reporting, and you can reactivate the row later.
Manage the catalog with: A slug must be unique across the queue’s active rows — creating a duplicate returns 409 DISPOSITION_ALREADY_EXISTS (replaces the code via retire + recreate). Only owners and admins can change the catalog; agents read it.

Recording the disposition on a conversation

At end of call, the agent (or the softphone picker) posts:
Send either dispositionCode (the slug) or dispositionId (the row id); the code must resolve to an active row on that queue or you get 404 DISPOSITION_CODE_NOT_FOUND. The record is idempotent on (queueId, callId) — a retry replaces the previous code and note instead of piling up duplicate rows. Two guards keep attribution honest:
  • The assigned agent records the outcome. A different agent cannot post a disposition for someone else’s call (404 NOT_OWNING_AGENT); owners, admins, and platform staff keep a blanket capability for after-the-fact corrections.
  • The code must exist on the live catalog. Free-text outcomes are rejected, so reporting never accumulates near-duplicate strings.

AI-suggested code

The softphone can ask for a suggestion before the agent picks:
A reader classifies the call transcript against the queue’s active catalog and returns a code, a confidence, and a one-line rationale. It is an assist, never a gate — nothing is recorded until the agent confirms, and when there is no transcript or the catalog is empty the endpoint returns a null suggestion and the picker falls back to manual selection.

The enforcement gate: disposition required on every conversation

Per queue, set requireDisposition when you create or update the queue. While it is on:
An agent cannot flip from busy back to available while their most recent finished call on that queue has no recorded disposition.
The status change fails with 422 and code: DISPOSITION_REQUIRED, and the response tells you exactly which queue and call are waiting:
The correct client flow is: render the picker from the catalog endpoint, let the agent pick, post the disposition, then retry the status change. Only the busy → available edge is gated — the agent can still step away (away, offline, paused) without recording, and they are prompted again the next time they try to go available. Default is off. Existing queues keep the legacy behaviour (agents return to available freely) until you turn the switch on — enforcement is strictly opt-in per queue.

The same gate on digital queues

Digital queues (email, web chat, WhatsApp, SMS, social channels) carry the same requireDisposition switch and the same owning-agent rule. A conversation routed through a digital queue tracks its wrap-up through an explicit lifecycle — assigned, awaiting wrap-up, and closed with disposition — so a supervisor can audit “closed but no outcome recorded yet” as a first-class gap instead of an invisible one. The digital disposition lifecycle and its state rules are described on the inbox reference.

Reporting: what the gate buys you

Once dispositions are enforced, wrap-up reporting stops having a silent “no outcome” bucket:
  • Wrap-up mix analyticsGET /api/v1/voice/dispositions/analytics returns the fleet-wide code distribution, the per-agent distribution, and outlier flags (agents whose share of a code deviates from the fleet baseline far enough to be worth a coaching conversation). Restricted to owners, admins, and supervisors.
  • Retired codes stay resolvable forever — historical conversations keep their labels even after you restructure the catalog.
  • Every record, override, and catalog change lands in the audit log with the actor, so QA can answer “who set this outcome and when.”
Turn on requireDisposition for a queue, seed it with the five-to-ten codes you actually use, and AHT, abandon, and first-contact-resolution reporting can all be segmented by outcome instead of one undifferentiated total.