Skip to main content

The KYC identity model: documents, profiles, and destinations

Every regulated surface on Orbit asks the same question — who is sending this traffic, on whose identity? The answer is split across three objects you own: a document, a compliance profile, and a destination. A first-time entrant into a regulated market almost always builds only two of the three, then wonders why a number won’t activate. This page defines the triangle, shows how expiry propagates through it, gives the renewal runbook, and routes the failures to the pages that already own them. All endpoints below are rooted at https://api.orbit.devotel.io/api/v1/compliance.
Orbit carries your identity packet to the carrier and enforces the gates; final approval is always granted by the carrier or regulator in each country, and supplying and renewing the underlying documents stays with you.

1. The triangle: document → profile → destination

Three objects, each with one job:
  • Document (doc_…) — the evidence file itself, uploaded once into a tenant-wide library. Inert on its own: it does regulatory work only when a destination references it.
  • Compliance profile (cprof_…) — the structured identity the documents back up: who the end user is, for which use_case, in which country. Carriers review the profile as a unit.
  • Destination — the regulated thing trying to go live: a phone number, a Sender-ID registration in one country, a 10DLC wizard draft, a WABA, an RCS agent. The destination is what gets gated.
The doc_… ID is the pointer that ties the triangle together. Upload one business-registration PDF and the exact same ID can serve all three consumers: Reuse only works when the roles and countries line up — a passport uploaded for Germany answers a German profile, and “the same document backs as many countries as accept it” is the ceiling, not the floor. What to upload for each market is in Country Compliance Requirements.

Which use_case does a destination demand?

The profile’s use_case field names the gate it answers to — one profile, one gate. Pick the value for the destination class, not for the document type: The full mapping with per-country requirements is on Compliance-profile use cases. Number, Sender-ID, and 10DLC use cases usually require a country_code on the profile; WhatsApp, RCS, and email accept a country-agnostic one.

Worked examples: country-conditional document types

The generic roles above (id_proof, address_proof, business_doc) are the library’s vocabulary, but the document names carriers actually ask for vary per country. The worked examples below show the three worked country packets end-to-end — the role and the upload type (the multipart field on POST /compliance/documents, one of the eleven accepted values), with the country-conditional document the market actually issues. Germany (DE) — Garanturkunde / rent registration + address proof. BNetzA regulated numbers accept a rent registration certificate (a “Garanturkunde”, the landlord’s confirmation keyed to the lease) as address evidence, in addition to the utility-bill family. Upload as lease_agreement (the rent agreement document) and attach as address_proof:
Then attach it on the profile as the address_proof role. Germany’s packet is business_doc (Handelsregister extract) + address_proof (the lease_agreement above or a utility bill) + id_proof (passport or ID card); Country Compliance Requirements carries the full checklist. France (FR) — justificatif de domicile + Kbis for B2B. France’s address proof is a “justificatif de domicile” (recent utility bill or official address certificate) — upload as proof_of_address or utility_bill, and attach as address_proof. For a business profile, the document the ARCEP packet always expects on top of that is the Kbis (the registry extract issued by the Greffe du Tribunal de Commerce) — upload as business_registration, attach as business_doc:
The Kbis answers the business_doc branch of the France packet; an id_proof-role document is required regardless of entity type. The full per-country role checklist is on Country Compliance Requirements. Brazil (BR) — CPF / CNPJ and an LGPD note. Brazil’s packet is stricter about local presence: the phone_number_purchase registry page for BR names the CNPJ (business registry number) as a required structured data field on the profile, alongside the standard business/address/ID documents. For an individual profile the equivalent is the buyer’s CPF — carried as an id_card or passport document in the id_proof role. Data stays tenant-scoped under LGPD: the document library is encrypted at rest with a per-tenant key and never shared across organizations, which is the compliance surface that answers to Brazil’s controller→processor framing (see LGPD Brazil).
And the business variant the registry page names (business_registration, with the CNPJ structured field on the profile):
Mexico (MX) — RFC on top of the business packet. Mexico’s purchase packet is the standard business trio — business_doc (the acta constitutiva or registry extract), address_proof, id_proof — with one required structured field on top: the RFC, the tax identifier SAT issues to every registered entity. Upload the registration as business_registration and attach it as business_doc:
The RFC itself travels as the profile’s rfc data field, not as a document — set it with PUT /compliance/compliance-profiles/:id/data; a profile without it never completes the MX packet. India (IN) — GSTIN + PAN on top of the business packet. India adds two required structured fields to the same business trio: the GSTIN (goods-and-services tax registration) and the PAN (permanent account number). The documents upload as usual — business_registration for the certificate of incorporation, a utility bill for address_proof, a passport or ID card for id_proof — while both tax numbers are set as profile data:
Set gstin and pan on the profile; the regulatory preview flips compliance_profile_satisfies to true only once both are present. United Kingdom (GB) — the compound ID-or-business-document rule. The UK carrier requirement is a single compound ask: a local government-issued ID/passport copy or a company registration certificate. The wizard therefore prompts both inputs — attach the company registration as business_doc (required), or satisfy the identity branch with a passport or national ID as id_proof (optional). Either proof completes the compound requirement; address_proof stays required alongside:
Japan (JP) — the same compound rule. Japan’s purchase packet mirrors the UK’s: business_doc required (the registry extract, e.g. a certified tokibo now), address_proof required, and id_proof optional as the substitutable identity branch. Upload the business document as business_registration, or the identity branch as passport / id_card:
Brazil (BR) addendum — the authorization role. On top of the CNPJ packet above, Brazil is the one regulated market whose purchase set carries a fourth document role: authorization — a signed letter from a company director authorizing the contact person to act for the business. Upload it as power_of_attorney and attach it in the authorization role alongside the required cnpj structured field:
The wizard prompts the role alongside the required cnpj structured field; attach a letter — accepted as power_of_attorney (or other) — whenever your carrier’s review asks for one.

Fields every regulated purchase prompts

The country branches decide the documents and the market-specific fields, but every phone_number_purchase packet also collects the same shared set: the business identity fields (registered name, registration number, full address, contact person) plus two carrier-disclosure fields — website (your business website) and business_description, labelled “Business use-case description (with sub-allocation disclosure)”: describe how you will use the numbers and state whether you will sub-allocate them to your own end users or to third parties. The wizard prompts both on every regulated purchase. Both are optional, but the carrier’s requirement group reads them the moment they are filled, and a bundle left without them is the standard “partially completed” rejection — fill them even when your market’s branch never mentions them.

An invalid document type comes back as a 422

POST /compliance/documents accepts only the eleven library type values listed above. A value that is not on the list — a carrier-side document name, a localized label, or a typo — is refused with HTTP 422 and the gateway’s VALIDATION_ERROR envelope, with the full accepted set echoed in error.details.allowed so a client can render the picker without another round trip:
The retry is cheap: catch the 422, map the human name to the valid library type (the mapping tables above are the country examples for exactly this), and re-upload.

2. Expiry mathematics: three clocks, three speeds

Expiry is not one event — it is three clocks ticking on different parts of the triangle, each with a different consequence: The clocks propagate outward: a lapsed document degrades the profile, a lapsed profile degrades the destination. Nothing in the chain self-heals — a clock that expires stays expired until you upload a replacement document or re-submit the profile.

What the gates do when a destination’s backing lapses

When a destination’s compliance backing goes from satisfied to lapsed, the pre-send and pre-activation checks — the same gate family described on Send Gates — refuse the surface rather than let it carry traffic:
  • A number whose profile is no longer approved sends fail with the compliance-profile error codes (COMPLIANCE_PROFILE_REQUIRED / COMPLIANCE_PROFILE_NOT_APPROVED, 422) covered on Compliance profile lifecycle errors.
  • A Sender ID whose country registration has lapsed sends fail with SENDER_ID_NOT_APPROVED — the entry exists, but its status is no longer approved.
  • A purchase attempted after the expiry lands the new number at pending_compliance, debited but inert until a satisfying profile is attached.
You don’t have to watch three clocks by hand. Orbit derives per-number alerts from the timestamps it already stores — each document’s expires_at and the carrier verify-by deadline — behind GET /numbers/document-expiry-alerts and the expiry-alerts banner on the dashboard’s Numbers page. Each alert carries a suggested_action (renew while still inside your alert window, renew_or_release once the expiry has landed). The look-ahead window defaults to 30 days; tune it with the numbers.document_expiry_alert_days setting. The full alert payload is documented on KYC Documents.

One expiry sequence, end to end

The one sequence every destination follows when its backing document expires — from the alert through the state change to the runbook:
  1. Alert fires inside the window. GET /numbers/document-expiry-alerts returns the document with suggested_action: renew and the number stays approved — no destination gate has fired yet.
  2. Document clock hits zero. The attached document’s expires_at passes. The next regulatory-preview call flips compliance_profile_satisfies to false — the document stops counting the moment it lapses, even though the file is still in your library. The destination state has now moved from satisfied to lapsed; the profile itself is still approved, but the clock that backed it is gone.
  3. Destination state changes. If the destination was a number whose backing profile relied only on the lapsed document, sends to it start failing with the COMPLIANCE_PROFILE_NOT_APPROVED 422 envelope — the pre-send check rejects rather than let the destination carry traffic. (Full code list on Compliance profile lifecycle errors.)
  4. Runbook — document first, references second. Section 3 below runs the four-step re-attachment: upload the replacement with POST /compliance/documents (a fresh doc_… ID), re-reference it on every consumer of the old ID, detach the expired one, then clean up the library. Every _NOT_APPROVED fail closes the moment the new attachment clears the gate.

3. Renewal runbook: document first, references second

Renewal is always a fresh upload, then a re-reference — never an edit in place. Run it in this order:
  1. Upload the replacement first. POST /compliance/documents with the new file. You get a new doc_… ID — a renewal is a new library entry, not a version of the old one.
  2. Re-reference it on every consumer of the old ID.
    • On each affected profile: attach the new ID in the same role (POST /compliance/compliance-profiles/:id/documents), then detach the expired one. An approved profile stays approved while you swap the document; its submission is re-reviewed on next use.
    • On each Sender-ID country entry: re-submit the registration with the new doc_… ID in document_refs (the upsert is idempotent — countries you already hold approved keep their approval).
    • On any open 10DLC wizard draft: update the draft’s document references before you submit.
  3. Clean up the library — delete the old document with DELETE /compliance/documents/:id once nothing references it. Deletion is refused while a profile still has it attached, so this step is also your completeness check: if the delete is refused, a reference is still open somewhere.

What a carrier re-review round trip costs you

A swap is atomic on your side; the carrier’s is not. After you re-submit, the packet goes back into a review queue — the same queue a first-time submission joins. Plan for that round trip:
  • Gating time is the carrier’s review time, not Orbit’s. The platform enforces the gate the moment the backing lapses and lifts it the moment the carrier approves; the time between is review queue depth in the destination country, not platform latency.
  • Renew inside the alert window (suggested_action: renew, before the expiry lands) and the destination keeps its approved backing while the replacement is under review — you never enter a gated state. Renew after the lapse (renew_or_release) and the surface is gated from the moment the clock expired until the carrier approves the new packet. That difference — zero interruption versus a full review round trip while gated — is the entire argument for a 30-day alert window.

4. Failure modes: which gate fired

This page stays at the concept level. When the triangle breaks, the symptom lands on the destination — and the troubleshooting pages already own each failure class. Route by the symptom you have: The pattern across all five: the gate never lies about which object lapsed. The error names the gate family (sender identity, compliance profile, destination registration); the triangle tells you what to renew first (document → profile reference → destination resubmission).

5. Cross-references