Skip to main content

Short-code preflight: checks and remediation

A short-code application goes through per-carrier vetting that runs for weeks, and carriers reject roughly a third of first-round program briefs on deterministic grounds — restricted content, ambiguous calls to action, missing opt-out or disclosure wording. The preflight engine scores your program brief against that known rejection-pattern catalog before it enters the carrier queue, returning a score, a verdict, and per-field findings with the exact offending fragment and a concrete rewrite suggestion. This page is the reference for that engine: the posture it runs under, the endpoint surface, every rule it checks, the remediation for every failure code, and the preflight → resubmission → carrier-verified lifecycle. For the end-to-end submission walkthrough (opening the application and tracking carrier vetting), see Apply for an SMS short code.
This page describes a tenant-owned compliance control. It is not legal advice. Whether a program brief satisfies carrier and CTIA requirements is your program’s responsibility — confirm with qualified counsel.

Role and posture

The preflight follows the same posture as every Orbit compliance control except the federal TCPA dialing window: tenant-controlled, default-open, advisory-only unless you enforce.
  • Advisory, never a gate. The endpoint only reads your brief and reports findings. It cannot block a submission, and it never touches sending — a block verdict is information for your submission decision, not an enforced stop. If your compliance policy requires a passing preflight before submission, enforce that in your own workflow.
  • Default-open. No org toggle gates the endpoint; any authenticated caller with a read-capable role can lint a brief.
  • A clean pass is not carrier approval. pass means “no known rejection pattern matched.” The application still goes through the normal per-carrier vetting, which includes human review.
Because it is advisory, treat the preflight as the deterministic first pass and carrier vetting as the authoritative second pass.

Endpoint surface

Two endpoints run the same engine (shortcode-preflight/v1), and all routes below are rooted at https://api.orbit.devotel.io/api/v1:

Field-by-field verification matrix

These are the request fields, their shape constraints (a violated constraint returns 422 VALIDATION_ERROR with per-field details), and what the engine checks:

Response shape

  • score — 0–100; 100 means no known pattern matched.
  • verdictpass, warn, or block.
  • findings[] — one entry per rule hit. field is the dot-path of the offending field (e.g. programBrief.sampleMessages[2]); match quotes the exact fragment when one exists; suggestion is the rewrite that resolves the finding.
  • engine — the rule-engine version, stamped on every response so you can correlate score changes when the catalog evolves.

Failure catalogue

Each finding carries a stable ruleId. The table covers every code the v1 engine emits, with the remediation for each. The four Call-to-Action rules (R-SC-CTA-*) only evaluate once the opt-in description clears the substance gate — a flow too thin to vet fails R-SC-OPTIN-LEN first, and per-disclosure findings would be noise until the flow is actually described. Scoring. Each error finding deducts 25 points, each warn 8, each info 2. The verdict is block when any error-severity finding is present, warn when the score lands below 75, otherwise pass.

Lifecycle: preflight → resubmission → carrier-verified

The lint sits inside the application lifecycle as an advisory checkpoint you can run at every draft stage:
  1. Lint before the application exists. Run the ad-hoc POST /numbers/short-codes/preflight while drafting the brief — before an application is even opened.
  2. Lint the stored draft. Once the application exists (draft status), fix findings with PATCH /numbers/short-codes/:id/brief, then re-run POST /numbers/short-codes/:id/preflight. Repeat until the verdict is pass. Both lint endpoints are idempotent reads.
  3. Submit. With a passing brief, POST /numbers/short-codes/:id/submit locks the brief and starts per-carrier vetting.
  4. Carrier-verified. Carriers approve the program and the lease is provisioned — the verdict that actually authorizes sending. The preflight pass was the deterministic first pass; provisioning is the authoritative one.
The application guide walks through each of these calls end to end.

Worked carrier-complaint cycle

The loop the preflight exists to shorten: a rejection comes back from vetting, and you need to turn a corrected brief around without re-entering the queue blind.
  1. Read the reason. A rejected application carries the aggregator or carrier rejectionReason — fetch it with GET /numbers/short-codes/:id: “Program rejected: published CTA missing opt-out wording.”
  2. Open a new application. Rejection is terminal (the brief is locked), so open a fresh draft with the corrected programBrief. For a CTA-wording rejection like the above, that means the opt-in description now carries frequency, rates, STOP, and HELP disclosures.
  3. Re-run the preflight against your original failure class. Lint the new draft with POST /numbers/short-codes/:id/preflight and confirm the finding class is gone. For the CTA example, expect no R-SC-CTA-* findings.
  4. Resubmit when clean. POST /numbers/short-codes/:id/submit re-enters the queue with a brief that has no known rejection pattern left to match.
The same cycle works pre-emptively — run it before the first submission and the deterministic rejection never reaches a carrier.
See also: