Worked onboarding reads
The onboarding endpoints are read-mostly state probes — the account estate a new tenant works through in its first session is easiest to learn as one chain: poll the provisioning panel → drive the checklist → override the steps that don’t auto-detect → confirm channel readiness → watch where verification is stuck. The samples below walk that chain end to end and show the full{ data, meta } envelope at each step.
Scope of this overlay: the samples show cURL and Node — the two
most-requested languages. Python, Go, Ruby, and PHP tabs appear on the
operation blocks themselves. The quickstart (quickstart)
chains the same steps with dashboard screenshots; this overlay stays
envelope-accurate against the API.
1. Poll the provisioning panel
Right after signup, pollGET /api/v1/onboarding/provisioning-status at ~2s
intervals until allReady is true. emailVerified, tenantSchemaReady,
and apiKeySeeded are the three blocking signals — the first API key
(dv_live_sk_* / dv_test_sk_*) is seeded by the workspace itself during
provisioning, so this read is also how you confirm you can start signing API
calls. trialCreditsGranted is reported for information but never blocks.
200
allReady is true, stop polling this endpoint — the 5s cache exists
for the provisioning window only.
2. Drive the bootstrap chain off the checklist
GET /api/v1/onboarding/status returns the nine-step getting-started
checklist with every satisfaction probe already resolved server-side. Each
step carries an id, a dashboard deep link (ctaUrl), a completed flag,
and completedBy — system when the platform’s own probe saw the signal,
user when an operator marked or skipped it. Branch your integration on
nextIncompleteStep instead of diffing the steps client-side.
200
trial_credit_grantedis the wallet confirmation. It flips only after account verification (KYC) is approved and the trial credit lands; until verification is approved the step is hidden fromsteps[]entirely, andtotalCountdrops to 8 — compute progress fromcompletedCount/totalCount, never from a hard-coded nine.payment_method_addedis the plan-credit attachment step — it flips the moment a default card or bank account exists for billing, and live traffic and number purchases settle against it.- A backend blip degrades, never errors. When the platform probes are
briefly unavailable the endpoint still returns
200with every step reading incomplete (the response is not cached, so the next poll recovers the true state). Treat an all-incomplete payload as “ask again in a minute”, not as a failed call — and keep your poll cadence at or above the 60s cache.
3. Mark or skip the steps that don’t auto-detect
Steps that resolve outside the platform’s reach need a manual nudge.POST /api/v1/onboarding/complete-step and /skip-step store a per-user
override that the checklist derivation merges on top of its probes — the
step then reports completed: true with completedBy: "user". Both writes
are restricted to the owner and admin roles and are audit-logged; send an
Idempotency-Key so a retried click never double-writes.
200
/skip-step; its echo carries "action": "skipped".
Skip is the right call for steps that genuinely don’t apply — for example a
sandbox-only workspace that never adds a payment method. A step id outside
the nine canonical values is rejected:
422
4. Confirm SMS readiness in one read
For the SMS surface specifically,GET /api/v1/onboarding/sms-checklist
collapses five readiness probes — API key, purchased number, approved SMS
sender ID, first sent message, active webhook — into one round-trip. It is
the fast path to gate a “you can send real traffic now” state without
hitting five endpoints.
200
hasSenderId counts only an approved SMS sender — a registration
still pending provider approval reads false.
5. See where verification is stuck
Once traffic is moving, the remaining onboarding risk is verification lag.GET /api/v1/onboarding/status-timeline folds account KYC, US 10DLC brand
and campaign registration, per-country compliance profiles, and per-number
compliance state into one ordered timeline — each row carries its folded
state, the current blocker line, and a deep-link resolveUrl to fix it.
200
in_review past its etaAt is the one to surface, not to re-fetch faster.