> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Onboarding wizard lifecycle

> The getting-started checklist model — nine server-derived steps, per-step probe semantics with partial success, per-operator skip and mark-complete overrides, KYC-gated trial-credit visibility, and how it differs from the go-live verification timeline.

# Onboarding wizard lifecycle

The Home dashboard shows a getting-started checklist of nine canonical steps — verify your email, create and name the workspace, add a payment method, receive the trial credit, buy a number, send a first message, add a first contact, and pick up one advanced item (a campaign, an agent, or a teammate invite). The server computes every step from live platform data on each read; no state lives in the browser. This page defines the step states, the probe semantics, the manual overrides, and the one compliance gate that hides a step.

The checklist answers "what should I do next to become productive." A separate surface — [Onboarding status timeline](/guides/onboarding-status-timeline) under **Settings → Onboarding Status** — answers "where is my go-live verification stuck" across KYC, 10DLC, country profiles, and per-number registration. Section 7 maps the difference.

***

## 1. The wizard state machine

Steps are served in six endpoints. Two carry the actual wizard UI; four reinforce it.

* `GET /api/v1/onboarding/status` — the main checklist. Returns the nine steps, each with `completed`, `completedAt`, `completedBy` (`"system"` or `"user"`), plus totals (`completedCount`, `totalCount`, `overallPct`) and a `nextIncompleteStep` summary used by the resume banner shown on other dashboard pages.
* `POST /api/v1/onboarding/complete-step` and `POST /api/v1/onboarding/skip-step` — write a manual override for one step; see Section 4. Either changes the response shape on the next `GET /status` poll.
* `GET /api/v1/onboarding/sms-checklist` — a five-probe fast read for the SMS getting-started panel (API key, number, sender Id, first SMS send, webhook).
* `GET /api/v1/onboarding/provisioning-status` — the signup gate (email verified, tenant schema ready, first API key seeded, plus a volatile trial-credit signal). The provisioning panel polls this every \~2 seconds during the post-signup window.
* `GET /api/v1/onboarding/status-timeline` — the verification-timeline spillover covered in Section 7.

Every step on `GET /status` is in exactly one of three states — **pending** (no signal), **complete**, or **complete-by-override**. There is no in-progress state; a step either has a satisfying probe row or it does not. `complete` and `complete-by-override` differ only by the `completedBy` marker (`"system"` vs `"user"`).

### The nine canonical steps

All steps are read in one shape: a label, a description, a `ctaUrl` (the dashboard route the step links to), and a stable `id`. The ids are the same ids the complete-step and skip-step endpoints accept; the validator rejects any other id with a `422`.

| # | Step                                                                                        | Satisfied when                                                                         |
| - | ------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- |
| 1 | `email_verified` — Verify your email                                                        | The account's email is confirmed.                                                      |
| 2 | `org_created` — Create your workspace                                                       | The workspace has a real, operator-chosen name (see Section 2).                        |
| 3 | `org_named` — Name your workspace                                                           | Same signal as step 2 — one probe satisfies both.                                      |
| 4 | `payment_method_added` — Add a payment method                                               | A default payment method exists on the billing profile.                                |
| 5 | `trial_credit_granted` — Receive your trial credit                                          | KYC is approved (see Section 5) and the grant ledger row exists.                       |
| 6 | `first_number_purchased` — Buy a phone number                                               | At least one number is assigned to your workspace.                                     |
| 7 | `first_message_sent` — Send your first message                                              | At least one message in your workspace reached `sent` or `delivered`.                  |
| 8 | `first_contact_created` — Add your first contact                                            | At least one contact exists in your workspace.                                         |
| 9 | `first_agent_or_campaign_or_team_invite` — Build a campaign, an agent, or invite a teammate | Any one of: an agent exists, a campaign exists, or a second user joined the workspace. |

Readable labels resolve into the nine ids the complete/skip endpoints take; the ids are stable API contract values and safe to hard-code in integrations.

## 2. The probe model

`GET /status` derives every step from underlying rows rather than state persisted on the requester's progress. At most \~9 cheap `SELECT ... LIMIT 1` probes run per cache miss, all behind a 60-second Redis cache scoped per (workspace, user), so the dashboard polls on every Home render without paying the derivation.

Two examples of probe semantics that are not "row exists":

* **Workspace identity.** A workspace row is provisioned automatically at signup, so the naive probe (`organization.name is not null`) would satisfy steps 2 and 3 the instant you reach the dashboard. Instead, both steps wait until the operator has set a real, chosen name, using the explicit placeholder flag stamped at provisioning when present and a name-pattern fallback for older workspaces.
* **Trial credit ledger.** Step 5 looks for the trial-grant ledger entry keyed to the workspace, written when the grant executes. Absence of the row is "not yet granted" — it never blocks the dashboard past the cache cycle that follows the grant.

The whole derivation is also deadline-bounded; when the backend is slow to answer, the response degrades to an all-incomplete checklist (a 200 that is deliberately **not** cached) instead of failing. The next poll re-derives the true state. Pollers should rely on that invariant: a `GET /status` read never hangs, and a degraded read is indistinguishable from a genuinely-incomplete state for one cache cycle.

## 3. Partial success — one passing probe satisfies a step

Step 9 is the one step satisfied by any of three channels: a campaign exists, an agent exists, or a second user accepted an invite. The derivation returns whichever of the three probes completes earliest, and the step flips as soon as one of them passes. The checklist stays honest about the funnel: reaching "platform graduate" needs exactly one of the three — you do not need all of them.

Partial-success semantics extend across the read path. Each probe fails closed on itself — a probe that cannot reach its data resolves to `pending` for its step rather than failing the whole checklist, and the other steps still resolve independently. Operators see a settled checklist even while part of the backend is degraded.

## 4. Operator overrides — complete or skip a step

Two write endpoints store a per-(workspace, user, step) override:

* `POST /api/v1/onboarding/complete-step` — the operator marks a step done ("Mark as done" in the dashboard).
* `POST /api/v1/onboarding/skip-step` — the operator dismisses a step that does not apply (e.g. payment method on a sandbox-only workspace).

The body is `{ "stepId": one-of-the-nine }`; anything else is a `422`. Both endpoints require admin-or-higher privileges and write an audit-log entry, so a teammate with a viewer or billing role cannot move your checklist.

An override applies to the operator's own checklist view — the key is the pair (workspace, user) — while probe-derived steps complete for the workspace irrespective of who polls. This is deliberate: the derivation reflects reality; your override reflects your declared intent. A probe-driven completion stays `completedBy: "system"`; an override flips the marker to `completedBy: "user"` without rewriting `completedAt`.

Overrides persist idempotently — re-marking a step re-upserts the row, and the intent (`manual_complete` or `skipped`) is recorded even though the checklist treats both as "complete." The distinction is retained for analytics over which steps operators skip.

## 5. KYC gates the trial-credit step's visibility

Step 5 (trial credit) has a compliance visibility rule the other eight steps do not share:

* **KYC not approved.** The step is **hidden from the checklist entirely** — excluded from `steps[]` and from the totals — unless the grant already landed (either a real completion signal or an operator override). The step's description never says "submit KYC now" once you have; it adapts to `pending_review` ("KYC submitted — under review (usually \< 24h)."), `rejected` ("contact support to resolve"), and `approved` (grant is in-flight). The **KYC banner** on the dashboard covers the review state with its own copy and link, so the checklist does not repeat it.
* **KYC approved.** The step reappears on the next `GET /status` poll (within one cache cycle).

That is the sole tenant-separation the checklist applies, and it is an operator-read rule, not an entitlement. Tenant-level KYC responsibility stays with the workspace's own `Settings → KYC` page; the checklist only surfaces or hides the step.

## 6. SMS checklist and provisioning-status are sibling surfaces

* **SMS checklist** (`GET /sms-checklist`) runs five per-surface probes (active API key, number, approved SMS sender, an SMS that reached `sent`/`delivered`, active webhook) behind a 30-second cache. It powers the SMS getting-started panel instead of hitting six endpoints.
* **Provisioning status** (`GET /provisioning-status`) exposes three blocks — email verified, tenant schema ready, at least one API key seeded — plus a volatile trial-credit signal. The signup provisioning panel polls it every \~2 seconds with a 5-second cache so the rows advance in near real time. Trial credit is informational there: the three blocking signals are email, schema, and API key.

Both endpoints answer booleans for an opted-in surface; they do not affect the nine-step derivation.

## 7. Wizard vs verification timeline

The wizard and the timeline are deliberately two surfaces:

* **This page (the wizard).** "What should I do to become productive" — nine steps derived from platform-usage data, with operator overrides. Lives at **Home**, reachable for most users through the resume banner.
* **[Onboarding status timeline](/guides/onboarding-status-timeline).** "Where is my go-live verification stuck" — a read aggregation across account KYC, 10DLC brands and campaigns, per-country compliance profiles, and per-number registration. Lives at **Settings → Onboarding Status**, the surface where reviewers, blocks, SLA, and resolution links are tracked.

Run the checklist first; run the timeline when verification is frozen. The two never write to each other.
