Quality Management API
Run a contact-center quality program end to end: author weighted evaluation forms, score agent calls (or let the AI auto-score them and override when needed), run blind calibration sessions to measure reviewer agreement, read an org-wide quality rollup across voice and inbox, and rank agents on a configurable leaderboard. Base path:/api/v1/quality
Authentication: API key (X-API-Key) or session JWT.
Roles: the reviewer endpoints (forms, scoring, calibration, gamification leaderboards, and the org summary) require the owner, admin, or supervisor role. An agent can read their own evaluations (GET /evaluations returns only their own rows), acknowledge or appeal an evaluation made about them, and read their own gamification card (GET /gamification/me).
All data is scoped to the calling tenant. Validation failures return 422 with a VALIDATION_ERROR body; see Error codes.
This is the contact-center Quality Management resource — evaluation
scorecards, calibration, and agent gamification. It is unrelated to the
per-call Voice AI Quality (VAQI) metrics documented under
/api/v1/voice/intelligence. One scores how a human
agent handled a call; the other scores call audio and AI-agent behavior.Using the SDKs
Prefer the typed client, but this page’s endpoint has no helper yet — the genericrequest() keeps auth/retries and the { data, meta } envelope identical:
client.request() escape hatch above. See the Python SDK.
Raw curl in the body of this page works identically. Full SDK index at SDK quickstart.
Evaluation forms
A form defines the rubric a reviewer scores against: a list of weighted sections, each holding weighted criteria. Weights are bare numbers and are normalized within their section and across the form, so you can author them as percentages or as plain relative weights. Each criterion has amax_score (default 100); reviewers submit a raw 0..max_score value per criterion and the server rolls everything up to a single 0..100 total. Mark a section auto_fail to force the whole evaluation to 0 when any criterion in it scores zero (the compliance-gate pattern).
Set
sample_rate_pct (0–100) on a form to have the continuous auto-sampler — a 15-minute tick over each agent’s completed calls, including AI voice agents — queue a weighted share as pending evaluations for a reviewer to score. 0 (the default) keeps the form manual-only.
Example form definition
Evaluations
An evaluation scores one call for one agent against one form. The reviewer submits ascores map of criterion_id → 0..max_score; the server re-derives total_score from the form weights, so a client can never set the total directly.
Recording library
The searchable post-call recording and transcript library — one unified surface joining every recording, its finalised diarised transcript segments, the latest linked evaluation, and the recording QC verdict, so the hit list is the QA worklist.
Full filter matrix, example requests, and the sibling surfaces that distinguish this route from whole-call transcript search and per-recording caption export are on the Recording library guide.
|
POST | /api/v1/quality/evaluations/{id}/acknowledge | Agent acknowledges their evaluation |
| POST | /api/v1/quality/evaluations/{id}/appeal | Agent appeals with a written note |
| POST | /api/v1/quality/evaluations/{id}/resolve | Reviewer closes an appealed evaluation |
| POST | /api/v1/quality/evaluations/{id}/claim-score | Reviewer scores a pending auto-sampled row |
| POST | /api/v1/quality/evaluations/{id}/override | Reviewer corrects an AI auto-scored row |
Status lifecycle
An evaluation moves throughpending → acknowledged or pending → appealed → resolved:
- The evaluated agent (and only that agent) can
acknowledgeorappealapendingoracknowledgedevaluation. An appeal requires anappeal_note. - A reviewer closes an
appealedevaluation withresolve. Resolving closes the appeal; it does not regrade the score.
Listing and pagination
GET /evaluations orders newest-first and uses an opaque keyset cursor. Read next_cursor from a response and pass it back as the cursor query parameter to fetch the next page; a null cursor means there are no more rows. Filter with agent_id, call_id, reviewer_id, status, auto_scored, and flagged_for_review. Agents may only list their own evaluations — the agent_id filter is forced to the caller for non-reviewer roles.
Auto-sampling and AI auto-scoring
Two kinds of system-created rows surface in the list with a distinctreviewer_id and may be claimed or corrected:
- Auto-sampled rows are queued un-scored (
total_score0) by a form’ssample_rate_pct. A reviewer fills in the real per-criterion scores withclaim-score; the server re-derives the total and stamps the reviewer. Only apending, still-unclaimed auto-sampled row is eligible — claiming a human-authored row returns409. - AI auto-scored rows carry
auto_scored: true, and those below your tenant’s flag threshold carryflagged_for_review: true. A reviewer corrects one withoverride; the corrected total is re-derived, the row is stamped with the reviewer, andflagged_for_reviewis cleared. Only apending, not-yet-corrected AI row is eligible.
Calibration
A calibration session pins one call and one form and invites a roster of reviewers who each score the call blind — they cannot see another reviewer’s score or the AI’s score until they submit their own. Once two or more reviewers have submitted, the report computes per-criterion variance, overall agreement, each reviewer’s delta from consensus, and the AI’s drift from that consensus. Calibration scores are practice rows; they never feed the agent-facing scorecard, ack/appeal flow, or leaderboard.
The session detail and the report enforce the blind rule server-side: an invited reviewer who has not yet submitted gets
403 from the report until they score. Each reviewer may submit once per session (a second attempt returns 409). If the call already has an AI auto-scored evaluation against the same form, it is seeded read-only as a drift baseline.
Quality summary
A cross-channel rollup of LLM-judged conversation outcomes across both voice and inbox, for a supervisor dashboard.
Pass
days (1–90, default 30) and conv_type (inbox, voice, or all). The response returns overall totals (scored count, pass rate, average confidence), a per-channel breakdown, the top rubrics by evaluation volume with their pass rates, and a short list of recent low-confidence failures for triage.
Quality trends
A time series of official reviewer-scored evaluations for a supervisor dashboard: per-day score averages over a window, plus per-agent and per-scorecard-form (rubric) breakdowns. This is the complementary surface to the point-in-time summary above — the summary answers “where does quality stand right now”; the trend answers “is it moving”.
Pass
days (1–90, default 30) and optionally drill the whole series with agent_id (one evaluated agent) or form_id (one rubric). The response echoes the resolved window, returns overall totals (evaluation count, average score, distinct agents and forms scored), the chronological per-day series, and the top 25 agents and top 25 forms by evaluation volume.
avg_score is the weighted 0–100 rollup the server derives when an evaluation is scored (see worked example 1 below) — the trend averages those totals per day. Only official scores count: an agent’s self-assessment and evaluations still under appeal or already resolved stay out of the average, so the line you read is the current reviewer-verdict signal.
Gamification
Rank agents on points and badges computed on demand from existing QA, call, and CSAT aggregates — no extra setup. The board is derived for a window and an optional queue or agent allow-list against a configurable ruleset.
Scope a leaderboard with
period (day, week, month) or an explicit from/to window, and optionally a queue_id or agent_ids list. Owner and admin callers see all agents; a supervisor sees only the agents in the queues they supervise, and requesting a queue they do not supervise returns 403. Pass point_rules or badge_definitions in the body to preview a tuned ruleset before adopting it. GET /gamification/me returns only the calling agent’s slice — ranked against the same default board so the agent’s rank always matches the supervisor view.
Worked examples
Eight end-to-end operator flows with real request and response bodies, covering scoring, calibration, trends, sampling settings, workload management, autoscore settings, and the recordings playbook. All calls below assumeORBIT_API_KEY holds a tenant API key and BASE_URL points at the product domain (https://orbit.devotel.io). Resource ids such as evform_…, call_…, and user_… are tenant-scoped examples — substitute your own.
1. Score a call against a form
The reviewer sends only the per-criterion scores; the server re-derives the weighted total from the form definition and stamps the caller asreviewer_id.
request() keeps the envelope identical):
total_score is the weighted 0–100 rollup the server derived: the opening section (crit_greeting 100 at weight 1, crit_identity 80 at weight 2) normalises to 86.67, the compliance section (crit_pii 100) contributes 100, and the section weights (20 × 86.67 + 30 × 100) ÷ 50 land the total at 94.67. The derivation runs server-side from the form’s weight fields — any total_score you send in the body is ignored; you cannot set the total directly. Fetch the weights from GET /evaluation-forms/{id} if you need to preview a score before submitting.
Response fields: status always lands pending for a reviewer-scored evaluation; the evaluated agent moves it to acknowledged (or appealed, which a reviewer then closes with resolve). For an agent scoring their own call, use POST /evaluations/self — it takes the same body minus agent_id, stamps both agent_id and reviewer_id to the caller, and lands directly in acknowledged.
2. Compute the gamification leaderboard
Rank the support queue over the trailing week and preview a tuned points ruleset in one call: passperiod: "week", narrow with queue_id, and override point_rules to try a heavier QA weighting before adopting it (GET /gamification/config returns the default rules when you want a starting point).
rules_source reports custom when the request supplied its own point_rules, otherwise default. entries is ordered by totalPoints — an empty array means no agent in scope has data for the window yet. Pass from/to (ISO 8601, both required) instead of period for an arbitrary window, or agent_ids instead of queue_id to run a hand-picked cohort. A supervisor is silently limited to the queues they supervise, and requesting a queue outside that set returns 403.
3. Run a blind calibration session
Three calls trace the full session lifecycle: open the session, submit one reviewer’s blind score, then read the agreement report. The report is blind-gated — an invited reviewer who has not yet submitted gets403 BLIND_SUBMISSION_REQUIRED until they score, so score first, then read.
Create the session pinned to one call and one form:
reviewer_ids beyond what you sent. ai_seeded: true means this call already had an AI auto-scored evaluation against the same form — that score is copied in read-only as the report’s drift baseline; it never counts toward the human consensus.
Each reviewer then submits their score (one submission per reviewer — a second attempt returns 409 ALREADY_SUBMITTED):
POST /evaluations, total_score is re-derived from the form weights — only the scores map is taken from the request.
Once two or more reviewers have submitted, read the report:
ready is false until at least two human reviewers have submitted (variance needs two graders); below that the numeric fields are still returned zeroed so you can render a partial state. reviewer_deltas holds one entry per human reviewer with their signed distance from the consensus; ai_delta is the seeded AI score’s distance from that same consensus, or null when no AI baseline was seeded. Calibration scores are practice rows — they never feed the agent-facing evaluations or the leaderboard. Close the session with POST /calibrations/{id}/close when the cohort is done; a closed session rejects further submissions with 409 INVALID_STATE.
4. Read the QA score trend
Track the support queue’s official scores over the trailing month, then drill the same series into one agent as soon as a downward slope shows up.window echoes the resolved filters so you can render the exact query you served. An out-of-range days falls back to 30, and an invalid agent_id / form_id degrades to the unfiltered org view — the endpoint never rejects a malformed drill with 4xx. avg_score on totals is null when nothing was scored in the window (per-day and per-row breakdown entries carry the day’s or row’s own average). Both breakdowns are capped at 25 rows ordered by evaluation volume, with an id tie-break so the page is stable across polls. Append &agent_id=user_… or &form_id=evform_… to drill the same payload shape into one agent or one rubric.
5. Configure QA sampling settings
The weekly auto-sampler reads its knobs from your organization settings —qa_sample_assignment.enabled, samples_per_agent_per_week, and lookback_days. Update them with a wholesale PUT on the general settings surface (owner or admin role).
Write the block (send every field you mean to keep — the key replaces the previous one wholesale):
request()):
qa_sample_assignment block. Read the current value back with GET /api/v1/settings/general; the same endpoint serves the autoscore settings (example 7) and this qa_sample_assignment block together. See the QA sampling guide for the sweep’s behaviour and range limits (1–20 samples per agent, 1–30 days lookback).
6. Manage the QA workload
Work on the reviewer queue: assign one call to one evaluator, move an open assignment across evaluators when load shifts, and read every evaluator’s open/overdue count against the per-evaluator quota. Assign a call to a specific evaluator:data.id is the new assignment. Two assignments on the same call return 409 ALREADY_ASSIGNED; one evaluator already at its quota returns 409 QUOTA_EXCEEDED. Tune the quota (default max_open_per_evaluator: 25) and due window (default due_days: 3) through the general settings surface (see example 5), persisted under qa_evaluation_assignment.
Rebalance an open assignment to a different evaluator while it is still pending and unscored:
409 INVALID_STATE if the assignment is already scored — a submitted score carries an audit trail the evaluator owns.
Node SDK (no typed helper — the generic request()):
open_count, quota, remaining, and overdue_count derived from the tenant’s due_days window. Narrow the list with ?evaluator_id=user_…. The full behaviour matrix (agent visibility, the 409 codes, per-evaluator due windows) is in the QA workload guide.
7. Configure AI autoscore settings
The AI autoscore sweep reads its master toggle and review threshold from organization settings —qa_autoscore.enabled and qa_autoscore.flag_threshold. Write them through the general settings surface (owner or admin role), then let the 60-second sweep pick up the change.
request()):
enabled: true is the only state the sweep treats as truthy; any other shape is off. flag_threshold accepts 0–100 (default 70) — auto-scored evaluations below it are stamped flagged_for_review: true, which surfaces them in the “Needs human review” dashboard filter and the workload queue (example 6). A numeric string is also accepted; an absent value falls back to 70. For the sweep’s per-tick behaviour and the readiness gates it checks, see the AI Auto-QA guide.
8. Work the recordings playbook
Run the post-call recordings pipeline end to end: find the recording in the library, check its QC verdict, preserve it with a legal hold, export its transcript for a review bundle, and mint a share link for an external auditor. Start by filtering the QA worklist — transcript search plus QC and score bands (see the recording library guide for the full filter matrix):request()):
pending / passed / failed / skipped; re-run it with POST /recordings/{id}/qc/run when you suspect the capture):
video:write scope):
data.share_url, data.token, and data.expires_at; lifetimes clamp between 5 minutes and 30 days (default 7 days when expires_in_seconds is omitted). Revoke every outstanding link for the same recording with:
recording.qc_failed webhook), per-conversation legal-hold batches, tamper-evident integrity seals, and clip/highlight extraction — is covered in the recordings pipeline guide.
See also
- Node SDK — typed helpers for call-control surfaces, preferred over curl for desk flows
- Voice API — per-call Voice AI Quality (VAQI) metrics
- Workforce Management API
- Analytics API
- Error codes