Start 2FA enrollment
/v1/auth/2fa/initiateBegins the enrollment flow for the authenticated user. Authenticated with a JWT Bearer token (not a secret API key).
For method=totp, the response includes the base32 secret and a pre-rendered qr_code data URL — show the QR to the user, ask them to scan it in their authenticator app, then call /v1/auth/2fa/confirm with the first 6-digit code.
For method=email, a 6-digit code is emailed to the user (10-minute TTL) and the response carries only a masked sent_to address. The same /v1/auth/2fa/confirm endpoint finishes the flow.
two_factor_enabled stays false until confirm succeeds — calling initiate alone does not lock the user out.
Body parameters
methodenum<'totp' | 'email'>requiredtotp mints a persistent secret for an authenticator app (Google Authenticator, Authy, 1Password). email sends a fresh 6-digit code to the user's email on every login.
Response
200methodenum<'totp' | 'email'>Echoed enrollment method.
secretstringBase32 TOTP secret. **Only present when `method=totp`.** Returned once — show in QR + manual entry, then discard client-side.
qr_codestringData URL (`data:image/png;base64,…`) of the otpauth QR code. **Only present when `method=totp`.**
sent_tostringMasked email address the setup OTP was sent to (e.g. `j***@example.com`). **Only present when `method=email`.**
Errors
INVALID_TOKEN401JWT missing, expired, or invalid.ALREADY_ENABLED4002FA is already enabled. Disable it first to re-enroll.