Skip to Content
InternalDocsRunbooksSelf Serve Signup API

Self Serve Signup API

Source: docs/runbooks/self-serve-signup-api.md

--- title: Self-Serve Signup API Runbook description: Operational runbook for signup session lifecycle, verification, provisioning retries, and incident troubleshooting. owner: ops last_reviewed: 2026-03-03 audience: internal status: active --- # Self-Serve Signup API Runbook Purpose: operate and troubleshoot the public signup API flow used by customers and agent-driven onboarding. ## Prerequisites Required environment variables: - `SELF_SERVE_SIGNUP_ENABLED` - `RESEND_API_KEY` - `RESEND_FROM_EMAIL` - `SIGNUP_OTP_TEMPLATE_ID` - `SIGNUP_PROVISIONED_TEMPLATE_ID` - `OTP_PEPPER` - `KEY_HASH_SECRET` - `CLERK_SECRET_KEY` ## API flow 1. Create session - `POST /api/public/signup/sessions` - Input includes company info, slug, modules, admin email, legal acceptance snapshot. - Output: `sessionId`, OTP verification window, session expiry. 2. Verify email - `POST /api/public/signup/sessions/:sessionId/verify-email` - Input: 6-digit OTP. - Output: session status (`EMAIL_VERIFIED`). 3. Provision (resumable) - `POST /api/public/signup/sessions/:sessionId/provision` - Input: `idempotencyKey` and optional integration-key template. - Output: - `201` + `PROVISIONED` when complete, - `202` + `REVIEW_REQUIRED` when manual intervention is needed. 4. Poll status - `GET /api/public/signup/sessions/:sessionId` - Use for agents to resume provisioning decisions. ## Provisioning step contract Step markers persisted in `provisionStepState`: - `tenant_created_at` - `clerk_org_created_at` - `clerk_invite_sent_at` - `detectors_seeded_at` - `integration_key_created_at` - `legal_acceptance_recorded_at` - `bootstrap_token_issued_at` Retries resume at the first incomplete step. ## Feature-off behavior When `SELF_SERVE_SIGNUP_ENABLED=false`: - all `/api/public/signup/*` endpoints return: - `503` - `code: FEATURE_DISABLED` - `details.retryAfterSeconds` ## Common failures - `RATE_LIMITED`: create/verify threshold exceeded (IP, domain, or email scope). - `INVALID_REQUEST`: malformed slug, module set, OTP, or idempotency payload. - `REVIEW_REQUIRED`: dependency or provider issue (for example Clerk/Resend/secret configuration). ## Recovery checklist 1. Check session status via `GET /api/public/signup/sessions/:sessionId`. 2. Confirm required env vars are present and valid. 3. Re-run `POST .../provision` with new idempotency key. 4. If still `REVIEW_REQUIRED`, escalate with `sessionId` and `failureReason`.