Skip to main content

Toll-Free Verification and RespOrg lifecycle

US toll-free numbers (800/833/844/855/866/877/888 prefixes) sit in their own regulatory lane: carriers do not weigh 10DLC registration for them, and they impose their own throughput penalties on unverified senders instead. Orbit handles toll-free from two directions — the SMS surface (Toll-Free Verification, POST /numbers/:id/tfv-submit) and the voice surface (the SMS/800 RespOrg — Responsible Organization — change workflow). This page is the lifecycle model for both.

1. Where toll-free fits in the sender-identity taxonomy

The sender-identity classifier resolves every from value to one of five classes — alphanumeric, short_code, toll_free, long_code, or unknown — before any gate or registration decision applies. A NANP +1 number on a toll-free prefix beats the geographic long-code branch and becomes toll_free, which is what puts the verification lane on deck. See Sender identity classification model for the full mapping. The classes are ordered by explicit prefix checks, not by likelihood: The toll_free label does not describe a brand — it describes the number shape. Everything after this label resolves (whether to run TFV, which gate to apply, which daily cap to land) hangs off the classifier’s five-output verdict.

2. The TFV lifecycle — draft, pending, and terminal verdicts

TFV moves a per-number row on the tenant schema through a four-state status enum: not_submittedpendingapproved or rejected.
  1. Draft — the row exists but has stored no payload yet. The persisted shape of the draft is what the dashboard fills in before it calls POST /numbers/:id/tfv-submit.
  2. SubmitPOST /numbers/:id/tfv-submit validates the payload server-side (same rules the dashboard form enforces), then routes the submission to the carrier that owns the DID. Twilio-imported DIDs go to Twilio’s Tollfree Verifications endpoint; Telnyx-owned DIDs go to Telnyx’s Verification Requests API; a DID that is not wired to either (Bandwidth-hosted, inventory placeholder, credentials absent) is staged locally so the reconciler retries the next time the credentials state changes.
  3. Pending platform submission (staged-local) — when the carrier could not be reached, tfv_status lands at pending with tfv_provider = 'platform_staged' and a synthetic tfv_local_* submission id. The dashboard renders the same state it would for a live submission, so a missing-creds tenant is not told the number is safe. The background reconciler (and the on-demand refresh button) re-attempts the carrier call on every poll; a call that went live on retry advances exactly the same way as a first-call success. This is the staged-submission state — not a separate status, but the same pending state with a staged provider label.
  4. Carrier decision — a background reconciler polls every pending submission until the carrier returns a terminal verdict, which is normalized onto the same four-state enum (approved, rejected, pending, or null for transient errors). The on-demand “refresh” button forces that poll for one DID and persists the verdict on first read; an operator can also re-submit the form if a rejection was down-weighted by a missing field.
The submission payload itself carries the review context the carrier asks for: a use-case category (one of the TFV_USE_CASES enum), a 40–500 character use-case summary, 1–5 production sample messages, the opt-in mechanism and at least one opt-in evidence URL, the business name/website/contact, and either a US EIN or a business-registration number plus its ISO-3166 country. A Political use case additionally requires a Campaign Verify authorization token — the field is validated at the API boundary so a missing token fails fast with a 422 rather than a carrier rejection days later.

3. What a reviewer looks for in sample messages and the use case

The carrier decision lands on the content of the submission, so the reviewer’s checklist matches what the form collects:
  • Use-case alignment — the useCase category and useCaseSummary must agree with the sample messages; a 2FA category carrying marketing copy is a rejection trigger.
  • Sample messages — 1–5 production bodies, each 1–1024 characters, numbered as ProductionMessageSample1…5 (Twilio) or positional messageSample{N} (Telnyx). An array carrying fewer than the declared length is a common source of silent rejection.
  • Opt-in evidence — at least one public URL (optInImageUrls) showing how the recipient opted in (VERBAL, WEB_FORM, PAPER_FORM, VIA_TEXT, or MOBILE_QR_CODE). A missing or non-http(s) URL fails the API-level check first.
  • Business identity — either ein (format xx-xxxxxxx) or businessRegistrationNumber + businessRegistrationCountry (holds ISO-3166 alpha-2; carriers have required one of the two since January 2026 — a tenant can have non-US registration and still submit).
  • Political trafficcvToken when the use case is Political or isPolitical: true; the token travels to the carrier for the round-trip and is not persisted.
Pre-flight the file is validated server-side so a malformed submission fails the call with a 422 before the carrier sees it.

4. RespOrg evolution for toll-free voice

A RespOrg change (SMS/800-administered Responsible Organization) is the inbound-telephony equivalent of a port-in/port-out for toll-free voice numbers, and it sits upstream of every SMS consideration on the same row: until the correct RespOrg owns the number, the TFV lane is the operation you are preparing, not resolving. Without a RespOrg path an established toll-free number could not be brought or released — the service closes the gap the TFV and port-in routes left. Orbit runs RespOrg as a manual, ops-processed request stored on the tenant schema: direction (in/out), the target numbers (up to 50 per request), the LOA + in-platform signature, ownership of the submission timestamped, and a Redis-locked write that serializes concurrent mutations. The service deliberately has no live Somos integration — request/tracking is the customer-facing surface, exactly like a manual-mode port-in row, and operations processes the change through the Somos portal. A RespOrg change is an inbound-routing ownership operation, not an outbound voice/SMS path — it does not touch the MT termination lane at all. When the numbers on the row are toll-free by shape — +1 on the 800, 833, 844, 855, 866, 877, or 888 prefixes — the REST surface (POST /porting/toll-free/resporg) accepts only that E.164 form and a LOA URL that resolves to the platform’s media-bucket prefix. The lifecycle beyond “captured” is the same: an Ops team member claims the request, submits it through Somos, and the row advances to its terminal state.

5. How TFV state plugs into the daily-cap and warming kernels

The warming and daily-cap engines treat TFV state as a hard first gate, not a bonus multiplier. For a tenant-owned toll-free sender the daily cap computed by the sender-warming kernel (rule the sender pool) is the smaller of:
  • the warming curve for that number (unverified toll-free senders are excluded from the high-trust-phase tables and pinned to a conservative initial-tier cap), and
  • the carrier-grade ceiling that the TFV preflight enforces at send time.
At send time the TFV preflight gate (sender is toll_free AND recipient is US) blocks the entire channel when the sender’s tfv_status is not approved — a preflight DB outage fails closed with “unable to verify TFV state” instead of fail-OPEN-ing a guaranteed-throttled send, so the warming ramp is not advanced on work the carriers will drop. A number that has never been TFV-approved stops there; approved entries proceed to the daily-cap count check; a rejected verdict blocks until the form is resubmitted and the carrier returns a new verdict. This is also why the sender-identity classifier must label toll-free correctly at render: misclassifying +1 888… as a long code would skip both the TFV state check and the TFV-idle daily-cap pin, and the warming kernel would read the number as eligible for throughput it can never carry.