Compliance profile lifecycle errors
A compliance profile is the reusable KYC packet that every gated surface — number purchases, Sender-ID registrations, brands, and campaigns — draws from instead of re-asking for the same paperwork. Four error codes guard that packet across its lifecycle: two block a surface that references a profile, two block an operation on the profile itself. This page maps each code to the state that raises it and to the fix you can run yourself.Compliance posture is tenant-owned: you create the profile, submit
it, and decide what it references. Orbit enforces the lifecycle
gates; the approval itself always comes from the carrier or
regulator reviewing your packet.
The lifecycle state map
A profile moves through one fixed review lifecycle, with three side-exits:- draft — freely editable. Nothing submits to a carrier until you submit the profile, so fields, documents, and metadata may change.
- pending_review — submitted and awaiting carrier or regulator review. The payload freezes: downstream submissions carry a copy of what we sent, and edits to the live packet could fork it from what each carrier holds.
- approved — review cleared; the profile may open gated surfaces. Still frozen for mutation — once carriers act on the submitted packet, edits would fork our record from theirs.
- locked (not a status — a guard) — any mutation or submit attempt
on a non-
draftanswers409 COMPLIANCE_PROFILE_LOCKEDbecause the payload entered a downstream submission. Fix is clone-and-fix, below. - in use (a status-independent guard) — any asset (number
purchase, sender, brand, or campaign) still referencing the profile
answers
409 COMPLIANCE_PROFILE_IN_USEon delete or document-detach, because deletion would strand the downstream reference. - rejected / partially_rejected — the carrier refused the packet
(or some of it). Editable again;
rejectedcarries the notes to fix before re-submit. - expired — the carrier’s validity window lapsed. Treated like
rejectedfor the gating surfaces; re-submit the profile to regain approval.
draft, rejected, and partially_rejected are editable;
everything else is locked against mutation by design.
The statuses gate surfaces in one direction only — a profile governs
what it may be attached to, but every surface’s own gate (number
pending_compliance, sender pending) is documented on
Troubleshoot a pending number or Sender ID.
Map your symptom to the failing operation
Before you read the individual codes, sort the failure by which call you made:The four codes
COMPLIANCE_PROFILE_REQUIRED — 422
Where it fires. A purchase or registration call on a surface that
requires a profile: a number purchase into a regulated country (UK,
DE, FR, and similar), a DIDWW DID-group placeholder row, a sender
registration, a brand or campaign registration that requires KYC.
Why. The surface checked your account for an approved profile
covering that use case and country and found none — either because no
profile exists yet, or because the existing ones are draft,
pending_review, rejected, or expired.
Fix. Two paths:
- You already have a suitable profile — pass its id. For a
number purchase, send
compliance_profile_idon the purchase request; for a sender or brand registration, attach the profile from its console surface (Settings → Compliance → Sender IDs / Brand identity). Some surfaces pick up the only approved profile automatically; the explicit id is always safer. - You do not — create a profile (Settings → Compliance →
Profiles, or
POST /api/v1/compliance/compliance-profiles), fill its fields against the country’s checklist (see Country Compliance Requirements), submit it, and wait forapproved. Only then re-run the blocked purchase.
COMPLIANCE_PROFILE_NOT_APPROVED — 422
Where it fires. The same attach path as above, when the request
references a profile whose status is not approved.
Why. The gate reads the profile’s status: draft,
pending_review, rejected, partially_rejected, or expired all
fail identical to a missing profile. A pending_review retry loop
does nothing but waste lead time.
Fix. Read the profile’s status first (the Profiles list in the
dashboard, or GET /api/v1/compliance/compliance-profiles/:id).
- pending_review — wait for the carrier’s review to complete;
attach succeeds the moment it flips to
approved. See the lead times on Troubleshoot a pending number or Sender ID. - rejected / partially_rejected — read the reviewer notes on the
Profiles page, fix what they flagged on the still-editable draft,
and re-submit. A re-submit moves the profile back to
pending_review; only an approved packet clears this gate. - expired — treat as rejected: clone and re-submit (see LOCKED below for why clone is the path once a profile is frozen).
COMPLIANCE_PROFILE_LOCKED — 409
Where it fires. Any attempt to mutate a profile that has moved
past draft: editing structured fields or metadata, updating the
use-case or country, attaching or replacing documents, or re-submit.
Why. Once a profile submits to providers, its payload freezes so
the copy carriers hold and the copy Orbit reads stay in sync — an edit
to a post-submit profile would fork those copies. draft,
rejected, and partially_rejected stay editable precisely because
nothing depends on them yet; everything else is locked by design.
Fix. Clone-and-fix:
(copy), structured data,
and document attachments — into a new draft with a new id and no
provider submissions yet. Edit the clone, submit it, and re-attach it
to every downstream asset the old profile fed (with
POST /api/v1/numbers/:id/attach-compliance-profile for numbers, or
the sender-ID / brand surfaces’ attach endpoints). This is also the
path for expired profiles once you need to re-verify them.
COMPLIANCE_PROFILE_IN_USE — 409
Where it fires. DELETE on the profile, or a document-detach call
on one of its underlying documents, when any active downstream entity
still references the profile — a purchased number, a registered sender
ID, a brand, or a campaign.
Why. Deletion would strand the downstream asset without its KYC
backing, so the API refuses and names the conflict.
Fix. Detach downstream first, then retry the delete. Walk your
numbers, sender IDs, brands, and campaigns; for each asset referencing
the profile, either attach a different approved profile or retire the
asset. The conflict check runs server-side, so run the detach walk
from the console surfaces each asset exposes. Only when nothing
references the profile does the delete (or the document-detach)
succeed.
When a non-approved profile is acceptable
Three lawful uses survive the NOT_APPROVED gate:- Draft-time assembly — while you fill the profile against its
country’s checklist, nothing is blocked:
COMPLIANCE_PROFILE_REQUIREDanswers only the surface that wants an approved reference, not the profile itself. - Attach by explicit
compliance_profile_idwith optimistic reference — some surfaces accept a profile id and queue againstpending_complianceuntil approval lands (see the pending-gated runbook for the numbers flow). Referencing a non-approved profile goes through as long as the surface supports queuing; the 422 fires when the surface requires an approved profile now. - Clone-and-fix cycles — editing the clone and re-submitting replaces the old profile gradually; the old asset keeps serving traffic until you re-attach, so an asset mid-swap is not an approved profile failure.
approved opens the gate.
Retry class map
From Error Codes: each class permits a different retry behaviour, so classify before you loop.
None of the four is a transient fault, and none carries
details.retry_after — the 409-class conflicts are resolved by state,
not by waiting.
Escalate with the full payload
If a profile-side error persists past the fix above, open a support ticket carrying:- The profile id (
cprof_…), its current status, and the operation you attempted (attach / mutate / delete). - The error code and HTTP status from the response envelope.
- The referencing asset id (
num_…, sender id, brand id, or campaign id) for REQUIRED / NOT_APPROVED / IN_USE. - The
meta.request_idfrom the failed response — the durable handle support uses to pull the attempt directly. - For LOCKED: the id of the clone you created and its own status.
Related references
- Troubleshoot a pending number or Sender ID — the status vocabulary, pending-gated surfaces, and re-submission path this page plugs into.
- Assemble your tenant’s compliance posture — how a profile composes with country rules and vertical packs, and the day-one activation order.
- Country Compliance Requirements — the per-market checklist a profile grades against before any of this.
- Error Codes — the attach-time retry-class table these four codes join.
- Compliance profiles API — the endpoint surface, including the clone endpoint the LOCKED fix drives.