> ## 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.

# Define and use disposition tags

> Build your tenant's per-call outcome tag taxonomy (sale-made, callback, no-answer, vip), wire agent stamping during wrap-up, and use tag-based reporting and QA filtering — tenant-administered, no deploy required.

Disposition tags are the outcome labels agents stamp on a call — "Sale made", "Callback scheduled", "No answer", "VIP". Each call can carry several tags at once, which makes them different from the single wrap-up code a queue requires. Devotel Orbit ships the tag catalog empty so your taxonomy stays yours, and supervisors curate it through the dashboard or the API.

This guide covers the whole loop: how tags differ from wrap-up codes and pause reasons, designing the catalog, where agents stamp them, reading tag-based reporting, QA uses, and the hygiene rules that keep the catalog usable.

**Dashboard:** **Voice → Disposition Tags** in the sidebar.

**Base path:** `/api/v1/voice/disposition-tags`

**Authentication:** Clerk session (`Authorization: Bearer <token>`) or API key (`X-API-Key`).

**Scope:** admin write scope required for catalog CRUD; agents stamp tags with voice write scope.

***

## 1. What a disposition tag is — and what it is not

Three labeling surfaces sit next to each other in voice operations, and they answer different questions:

* **Disposition tags** (this page) — the per-call **outcome** taxonomy. A call can carry many tags (`sale-made` + `callback` + `vip`), so reports can answer "what happened on these calls?" across several overlapping categories at once. Tags are tenant-wide: every team shares one catalog.
* **Wrap-up disposition codes** — the per-queue **required-code** taxonomy. A queue with `require_disposition` enabled blocks an agent's `busy → available` flip until exactly one code is recorded. That axis gates agent availability; tags never do.
* **Pause reason codes** — the agent **away-state** taxonomy ("Lunch", "Coaching"), documented in [Manage pause reason codes](/guides/voice-pause-reason-codes). Those label agent time, not call outcomes.

Pick the tag axis when the same call legitimately falls into several buckets and you want all of them searchable. Pick the wrap-up-code axis when a queue enforces "no availability until a disposition exists."

## 2. Design the tag taxonomy

Create tags in **Voice → Disposition Tags**, with `slug` + `label` + optional `color` + `sortOrder`. Some starter sets by team type:

* **Outbound sales floor:** `sale-made`, `sale-lost`, `callback`, `wrong-number`, `decision-maker-absent`, `no-answer`.
* **Inbound support:** `resolved`, `escalated`, `refund-requested`, `product-bug`, `follow-up`.
* **Collections:** `promise-to-pay`, `dispute`, `wrong-party`, `refused-payment`.
* **Cross-cutting flags (any floor):** `vip`, `churn-risk`, `lead`, `complaint`.

A new tag goes live in every picker the moment it saves.

```bash cURL theme={null}
curl -X POST "https://api.orbit.devotel.io/api/v1/voice/disposition-tags" \
  -H "X-API-Key: dv_live_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "slug": "sale-made",
    "label": "Sale made",
    "color": "#16a34a",
    "sortOrder": 10
  }'
```

Body fields:

* **`slug`** — machine slug, lowercase letters/digits/`_`/`-` only (max 60). Stamping clients can send slugs directly, so keep them stable.
* **`label`** — the human label pickers render (max 200).
* **`color`** — optional chip color, hex or token slug (max 32).
* **`sortOrder`** — optional integer, default `100`; lower sorts first in the picker.

Create returns `201` with the stored row. A `409` with code `DISPOSITION_TAG_ALREADY_EXISTS` means another active row already owns the slug — retire the old row or pick a different slug.

## 3. Where agents stamp tags

Agents pick tags from two surfaces; both resolve against the live tenant catalog:

* **Softphone / call-detail page** — the per-call chip editor on **Voice → Calls → \[call]** shows the tenant's active tags as toggle chips and applies them in one batch. Read and stamp both happen here, so an agent can also see what a colleague stamped.
* **After-call wrap** — a tag pick is usually part of the wrap-up block, and the stamp endpoint accepts them together with the queue the call arrived on.

```bash cURL theme={null}
curl -X POST "https://api.orbit.devotel.io/api/v1/voice/calls/call_abc123/disposition-tags" \
  -H "X-API-Key: dv_live_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "tagSlugs": ["sale-made", "vip"],
    "queueId": "queue_01HZ..."
  }'
```

Stamping accepts `tagSlugs` (operator-friendly) or `tagIds` (pre-resolved catalog UUIDs), or both; the server dedups by resolved tag. A stamp is **idempotent on the call-tag pair** — re-applying a tag refreshes who stamped it and when, without duplicating the audit row. A batch of 1–64 tags lands in a single round-trip.

Read the current assignments on a call with:

```bash cURL theme={null}
curl "https://api.orbit.devotel.io/api/v1/voice/calls/call_abc123/disposition-tags" \
  -H "X-API-Key: dv_live_sk_your_key_here"
```

The read joins back against the catalog so labels still resolve even after a tag is retired (assignment history keeps the label snapshot).

## 4. Read tag-based reporting

Tags feed the analytics surfaces through the same catalog + assignment tables the stamp endpoint writes:

* **Tag coverage in Insights** — supervisors open **Voice → Calls** and filter by one or more tags to see the share of calls each tag accounts for, so coverage drift (a tag agents stopped applying) is visible before the downstream report goes stale.
* **Cross-cutting segments** — because tags are many-to-many, a supervisor can cross-segment "all `churn-risk` calls that were also `escalated`" rather than picking a single primary outcome.
* **Per-agent tagging adherence** — the stamped rows carry `assigned_by`, so a weekly supervisor review can flag agents whose calls consistently lack any outcome tag (see section 6 on preventing this).

The envelope is paginated (`page` / `pageSize`, plus `total`) on both the catalog list and the per-call assignment list, so report UIs can page large catalogs without a full-table read.

## 5. QA and coaching uses

Tag filtering is the fastest way to build a coaching cohort without listening to everything:

* **Filter recordings by disposition** — QA reviewers open **Voice → Calls**, select `no-answer` or `escalated`, and jump straight to the call recordings that matter this week instead of a random sample. The recordings view links through from the call row. See [Recording view analytics](/guides/recording-view-analytics) for the playback-side detail view.
* **Coaching cohorts** — supervisors set up a saved filter like `product-bug + escalated` and treat the tag intersection as the coaching queue.
* **Spot-checks on sensitive outcomes** — `refund-requested` or `complaint` tags define a targeted review sample that is reproducible week to week.

Tags are also the input the QA sampling surface can weight against, so high-stakes outcome categories can claim a larger fraction of sampled minutes.

## 6. Tag hygiene rules

The catalog is a supervisor-owned taxonomy, and it stays useful only inside a few rules:

* **Cap the active set.** Ten to thirty tags is a working ceiling — past that, agents stop picking reliably and every report starts measuring hesitation rather than outcome.
* **Never accept free-form values.** Picker chips beat text input: free-form means `Sale`, `sale`, and `sold` become three different tags in week two.
* **Prefer retirement over a rename cascade.** Retirement (`is_active = FALSE`) frees the slug for reuse while historical assignments keep resolving — rename when the meaning genuinely stayed the same, retire when it did not.
* **One owner per tag family.** Let one supervisor own the outbound tags, one own the inbound tags; a shared audit trail records every create/update/retire so "who added this?" is answerable.
* **Do not tag what a queue code already answers.** If a queue gates availability on a specific wrap-up code, tagging the same fact again on every call is wasted agent effort.

```bash cURL theme={null}
curl -X DELETE "https://api.orbit.devotel.io/api/v1/voice/disposition-tags/tag_01HZ..." \
  -H "X-API-Key: dv_live_sk_your_key_here"
```

Retire returns `204`. Reactivate later with `PATCH {"isActive": true}`.

## Troubleshooting

* **Agents report a tag missing from the picker:** verify the catalog row is `is_active = TRUE`; the picker only renders active rows. If visibility persists, the picker re-reads the catalog on every open — an archived-then-reactivated tag reappears on the next refresh.
* **Stamp call rejects a slug:** the stamp endpoint only accepts tags that resolve to an active row; a slug staged with `is_active = FALSE` fails with `DISPOSITION_TAG_NOT_FOUND`. Reactivate it and retry.
* **Duplicate-slug 409 on create:** the slug is unique among active rows. Retire the old row first, or pick a different slug; converging the same slug after retirement is allowed.
* **Tag filter shows no calls in Insights:** a tag with zero assignments is noise; either agents have not adopted it or the traffic genuinely stopped. Check adherence before deciding the tag is broken.

## See also

* [Manage pause reason codes](/guides/voice-pause-reason-codes) — the agent away-state taxonomy (distinct from per-call tags)
* [Recording view analytics](/guides/recording-view-analytics) — the playback surface tag filtering lands on
* [Voice queues](/guides/voice-queues) — the ACD surface that can also require a single wrap-up disposition code
* [Voice API reference](/api-reference/endpoints/voice) — parameter and response detail for the tag endpoints
