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

# Troubleshooting: FCC AI-voice consent gate blocking outbound calls

> Resolve 422 FCC_AI_VOICE_WRITTEN_CONSENT_REQUIRED on outbound AI, TTS, and cloned-voice calls — read the reason enum, confirm which metadata signal classified the voice, work the audit queue, and attach the written-consent evidence the gate reads.

# Troubleshooting: FCC AI-voice consent gate blocking outbound calls

An outbound call that fails with `422 FCC_AI_VOICE_WRITTEN_CONSENT_REQUIRED`
never reaches the phone network. The consent gate fires **before** a billing
hold is taken, **before** a media room is created, and **before** the leg is
dispatched — so a blocked call costs nothing and routes nothing, but it also
means every recipient on the blast without written consent on record is
dropped. This page walks a blocked AI-voice campaign end to end: why the
gate exists, which metadata signal classified your call as regulated, which
`reason` your block returned, and which evidence unblocks it.

For the rule itself and the classification table in full, see
[FCC 24-17 — written consent for AI voices](/compliance/fcc-ai-voice-consent-guard).
This page works the error, not the statute.

## Why the gate exists

The FCC's February 2024 declaratory ruling 24-17 put AI-generated and
cloned voices under the TCPA's "artificial or prerecorded voice" rule —
[47 CFR § 64.1200(a)(1)(iii)](https://www.ecfr.gov/current/title-47/chapter-I/subchapter-B/part-64/subpart-B/section-64.1200).
For marketing calls that means **prior express written consent**, and the
exposure is statutory: **$500–$1,500 per non-compliant call**
(47 U.S.C. § 227(b)(3)).

The split of ownership, per the
[compliance posture](/compliance/posture-overview): Orbit classifies the
voice on every outbound leg, enforces the consent check against your
records, blocks when the evidence is missing, and writes the audit row.
**Your** obligation is to obtain and hold valid written consent. The gate
is Orbit's; the consent evidence is yours.

## Which metadata key classified your call

The gate resolves `human`, `synthetic`, or `cloned` from the call's request
`metadata`, first match wins:

| Priority | Metadata key | Verdict it yields |
| - | - | - |
| 1 | `voice_content_type` ∈ `{human, synthetic, cloned}` | that value, verbatim |
| 2 | `voice_cloned_model_id` (string) | `cloned` |
| 3 | `voice_agent_id` (string) | `synthetic` |
| 4 | `agent_id` (string) | `synthetic` |
| 5 | `tts_text` / `tts_body` (string) | `synthetic` |
| — | none of the above | `human` |

Which key your call carries depends on the lane it entered on:

* **Campaign or journey with an AI voice agent** — the campaign stamps
  `voice_agent_id`; a TTS-only step stamps `tts_text` / `tts_body`. A
  cloned model stamps `voice_cloned_model_id`.
* **Direct `POST /api/v1/calls`** — whatever your dispatcher set. The
  `agent_id` fallback exists for direct-API callers that predate the
  canonical key; stamp `voice_agent_id` (or the explicit
  `voice_content_type`) instead.
* **Click-to-call, bridged agent, conference** — none of the signal keys,
  verdict `human`, and the gate short-circuits before any consent check.

Two classifier behaviours explain most "why is this regulated" surprises.
A non-string signal is ignored (`{ "voice_agent_id": 12345 }` reads as
`human`), and an unrecognised `voice_content_type` value
(`"robot"`, `"ai"`) also reads as `human`. In the other direction, any one
signal key is enough to regulate — a campaign leg your dispatcher stamped
as a set cannot "fail back" to human.

## Diagnose: which reason your block returned

Every block returns the same 422 code with a `reason` in the error
details. Match yours:

| `details.reason` | What it means | Fix |
| - | - | - |
| `no_written_consent_on_record` | The consent lookup ran and found no granted, non-revoked row for this recipient carrying the FCC 24-17 marker | [Attach the consent evidence](#fix-attach-the-consent-evidence) |
| `tenant_consent_schema_missing` | Your workspace's consent-records store is not provisioned, so the gate cannot even check — it blocks | [Provision the consent store, then record consent](#fix-attach-the-consent-evidence) |
| `consent_lookup_error` | The consent lookup hit a database error and the gate failed closed | Retry; if repeats, contact support with the request ID |

### Trace the block through the audit ledger

Every block — whichever reason — is written to the append-only audit
chain as `voice.fcc_ai_consent_blocked` **before** the error is returned.
Filter on that action in your [audit log](/guides/audit-log) to work the
blocked-campaign queue as a set instead of redialing one recipient at a
time. Each row carries:

* the classification verdict (`synthetic` or `cloned`),
* the redacted recipient number,
* the `reason` from the table above,
* the campaign and agent id, when those were stamped on the call.

Allow-path calls do not write this row — the usual voice-call audit
downstream covers granted-consent calls, so the blocked queue contains
only the recipients you still need evidence for.

### Fail-closed vs fail-open, per call lane

The gate's two failure decisions are asymmetric, and both are deliberate:

* **Human-voice lane fails open by design.** A `human` verdict
  short-circuits the gate before any database read — no check, no block.
  There is no regulatory exposure to guard against, so a consent-database
  blip cannot hold a click-to-call or bridged-agent leg.
* **Synthetic/cloned lane fails closed.** A workspace whose consent store
  is missing, or whose consent lookup errors, blocks the call rather than
  allowing it. $500–$1,500 per call of statutory exposure is the
  platform's to take on the block side. Expect a blocked call (fixable),
  not a silent allow (a class-action discovery request).

The retry-correct lane is the third row in the table above:
`consent_lookup_error` is the only shape where "retry the send" is the
right first move.

## Fix: attach the consent evidence

For each blocked recipient, record a **granted, non-revoked** consent row
in the [consent register](/compliance/consent-management) carrying either
of:

* `consent_type = 'fcc_24_17_written_consent'`, or
* a free-text `consent_type` plus a `lawful_basis` entry of
  `fcc_24_17_written_consent` in the record's metadata.

Either marker unblocks the recipient on the next attempt; the gate reads
both shapes and accepts a legacy row with an unknown consent state as
granted. If the reason was `tenant_consent_schema_missing`, the consent
store first needs provisioning — follow the message in the error's
`hint` field, then record the rows.

### The other fix lane: stamp an honest `voice_content_type`

When your call genuinely uses a human (an agent on a bridged leg, a
click-to-call), the correct unblock is to make the metadata say so:
`voice_content_type = 'human'` short-circuits the gate.

<Warning>
  Stamp the value the call actually uses. Setting
  `voice_content_type = 'human'` on a call that plays synthetic or cloned
  audio to route around the consent check is a compliance violation — the
  audit trail records the classifier verdict on the blocked attempts, and
  the reclassification does not erase it. Do not launder `synthetic` as
  `human`; either collect the written consent or put a human on the call.
</Warning>

## Where this gate sits in the fork

This block is one gate in the full pre-dispatch sequence, and a re-send can
hit a different gate after this one clears. If a blocked send re-fails with
a different code — country allowlist, quiet hours, DNC — work the
[send-gate decision fork](/compliance/send-gate-decision-fork) to map the
new code to the gate that now fires. The federal dialing-window gate runs
before this one; a release window cannot outrank consent, and vice versa.

## See also

* [FCC 24-17 — written consent for AI voices](/compliance/fcc-ai-voice-consent-guard) — the concept page: classification table worked examples, gate ordering, fail-closed rationale
* [Consent management](/compliance/consent-management) — where to record the written-consent row the gate reads
* [Send-gate decision fork](/compliance/send-gate-decision-fork) — the routing index when the re-send hits a different gate
* [Audit log](/guides/audit-log) — filter `voice.fcc_ai_consent_blocked` to work the blocked-recipient queue
