Skip to main content

10DLC Registration Wizard

The wizard is the recommended way to complete TCR brand and campaign registration. It turns the linear single-shot flow into a guided, resumable process:
  • Save and resume — your draft persists across sessions, tabs, and weeks. Close the tab or come back tomorrow; you pick up where you left off.
  • Move between steps non-linearly — the wizard tracks brand, campaign, and review as independent steps. Fill the campaign samples while the brand section is still incomplete, and the progress payload keeps both counts.
  • Validate before you pay — per-field validation fires on every save, and a pre-submission lint pass scores the saved draft against known TCR rejection patterns before the upstream registration fee is charged.
The wizard writes to your organization’s own draft storage only. It does not hold, gate, or route any message traffic.
All wizard endpoints live under /api/v1/compliance/10dlc/wizard. Authenticate with your API key, exactly as for the brand and campaign endpoints.

Roles and rate limits

  • Reads (GET /wizard, GET /wizard/draft) — any authenticated role on the organization.
  • Writes (PUT /wizard/draft, DELETE /wizard/draft, POST /wizard/phone/send, POST /wizard/phone/confirm, POST /wizard/preflight, POST /wizard/submit) — owner or admin role.
  • Write profile: 10 requests per minute, matching the legacy brand/campaign endpoints. Wizard preflight: 30 requests per minute, matching the ad-hoc preflight endpoint.

GET /10dlc/wizard — progress payload

Returns the computed progress object the dashboard uses for its “Continue where you left off” banner. Always 200 OK — a fresh organization gets the empty-draft shape with state: "not_started".
Response:
state is one of not_started, in_progress, brand_pending, campaign_pending, ready, rejected. current_step is brand, campaign, or review. next_action is a machine-readable hint: fill_brand, fill_campaign, review_and_submit, amend_brand, amend_campaign, or done. When the brand or campaign has been submitted, the response also carries brand_id, campaign_id, and any upstream rejection reason. GET /10dlc/wizard/draft returns the full saved draft (brand fields, campaign fields, current step) for form prefill.

PUT /10dlc/wizard/draft — partial save

Saves any subset of brand and/or campaign fields. Every field is optional — you only validate the fields you send, and the rest keep their previously saved values. current_step updates separately so a resume lands on the right screen.
A save that fails validation returns 422 and leaves the persisted draft untouched — the previously saved state survives. Brand fields: entity_type, display_name, company_name, ein, phone, street, city, state, postal_code, country, email, website, vertical. Campaign fields: usecase, description (40–4096 characters), sample_message (1–10 messages), message_flow (min 40 characters), help_message (min 20), optout_message (min 20), is_political, cv_token.
Save after each required field if you like — each save costs under one write-rate token and the draft is the safety net. The campaign’s brand_id is never typed by hand: the wizard fills it in from the brand submission outcome.

Sole-proprietor phone verification (OTP)

US brands with entity_type: "SOLE_PROPRIETOR", and only those, substitute a verified mobile number for an EIN: TCR anchors sole-proprietor identity on a phone number the registrant proves they control. Every other US entity type must submit an EIN instead. Verify the number before submitting:
Response:
Response:
The proof is keyed to the exact phone string saved on the draft. If you edit brand.phone after verifying, the old proof no longer counts and submit fails with 422 until you run a fresh challenge against the new number. Calling /phone/send on an already-verified number returns 409 ALREADY_VERIFIED; calling /phone/confirm without a pending challenge returns 404.

POST /10dlc/wizard/preflight — lint the saved draft

Scores the persisted wizard draft against the known TCR rejection-pattern catalog, so the “Review & submit” screen sees findings against the exact draft it is about to submit — no chance of lint drift that the ad-hoc preflight endpoint has when it lints a hand-built payload. The request body is optional: expected_msg_per_day_per_number (for the throughput-tier rule) and brand_vetting_score (0–100) when you already hold one.
The response shape — score, verdict, findings[] — is identical to the preflight linter on the registration page. As with that endpoint, a pass verdict means “no known rejection patterns matched,” not “TCR will approve.”

POST /10dlc/wizard/submit — atomic brand + campaign

Validates the full draft, then submits the brand and the campaign in one call. Brand vetting typically lands in 1–48 hours; the campaign follows immediately after.
Response (201 Created):
Validation failures return 422 before anything is charged, with details.section telling you whether the missing or invalid fields are in the brand or campaign section. Failure semantics — the atomic guard:
  • Brand rejected upstream — no campaign is submitted. The draft is preserved with the brand rejection reason stamped, and next_action flips to amend_brand. Amend the brand fields and resubmit.
  • Campaign rejected upstream — the accepted brand_id is persisted, state stays at brand_pending, and the campaign rejection reason is stamped. A resubmission skips the brand stage entirely, so the brand fee is never re-charged; only the campaign pays again.
  • Upstream 5xx or provider unavailable — the draft is preserved verbatim and you can retry as-is.
State transitions to ready once both the brand and campaign come back APPROVED from carrier review.

DELETE /10dlc/wizard/draft — reset

Returns 204 No Content. Resets the wizard to the empty draft (state: "not_started"). This does not clear the approved brand or campaign ids on file — it only resets the wizard working state, so it is safe as post-approval cleanup or a “start over.”

Full lifecycle order

  1. PUT /10dlc/wizard/draft — progressively fill brand + campaign.
  2. (SOLE_PROPRIETOR only) POST /10dlc/wizard/phone/sendPOST /10dlc/wizard/phone/confirm.
  3. POST /10dlc/wizard/preflight — fix findings until the verdict passes.
  4. POST /10dlc/wizard/submit — atomic submission.
  5. GET /10dlc/wizard — poll state until ready (or GET /10dlc/campaigns/:id/status for the per-carrier map, as on the registration page).
  6. DELETE /10dlc/wizard/draft — optional post-approval cleanup.
The legacy single-shot endpoints (POST /10dlc/brand, POST /10dlc/campaign) stay available for scripted pipelines. The wizard is the recommended operator flow; the direct endpoints demand a fully populated payload in one request.