Call outcomes: call_status and status_reason
call_status — final status bucket of a finished call (empty string until finalized). One axis, one source of truth; quality (call_successful) and technical reliability (health) are separate axes and never leak into the status:
status_reason — fine-grained reason, always belonging to exactly one bucket:
health_reasons — codes explaining a warning/error health verdict. A call’s verdict is the worst code that fired: any error-level code makes the call error, otherwise warning. The vocabulary is open — new codes are added over time, so treat an unfamiliar one as data, not as a parsing failure.
Codes come from four sources. The split matters: health_reasons carries the output of a rule, never its input — status_reason values and the internal codes of call events never appear here.
1. Call events — something went wrong inside the conversation:
2. The call status axis —
status_reason values fold into these:
Reasons that belong to the callee (
no_answer, busy, user_declined, invalid_destination, spam_blocked) and dials you cancelled yourself before dialing (cancelled_by_function, cancelled_by_operator) contribute nothing: they are not platform defects.
3. Post-call analysis — analysis_skipped, analysis_failed, analysis_interrupted, all warning level, from the terminal state of the analysis.
4. Recording and timing — recording_head_lost (part of the recording does not exist) and slow_turns (the 90th percentile of turn duration is above the configured threshold), both warning.