Enroll in MFA
Start turning on two-factor authentication for your user. The call generates a new TOTP secret and ten one-time backup codes and returns them; MFA is not on yet. Add the secret to an authenticator app (scan qr_code or type in secret), then confirm with a current code at /mfa/activate. Until then sign-in is unchanged and /mfa/status reads enabled: false.
Interactive session only. This call requires an interactive dashboard session (a session JWT): sign in with /auth/login (followed by /auth/mfa when MFA is on) and send the token as Authorization: Bearer <session_jwt>. API keys and OAuth/MCP tokens get 403 with code: "interactive_session_required".
The secret and the backup codes are shown only in this response; the server keeps the secret encrypted and the codes hashed. Store the backup codes somewhere safe: each one signs you in once if you lose the authenticator.
Enrolling again before activating replaces the pending enrollment (new secret, new codes — the earlier ones stop working). If MFA is already on, the call is refused with 409: disable it first, which needs your password and a current code.
The codes are standard TOTP (RFC 6238): six digits, a 30-second step, SHA-1 — any authenticator app works.
Request body
None. Send the Content-Type: application/json header anyway — every POST without it is refused with 415.
Response (200 OK)
true on a 200.data: prefix — add data:image/png;base64, to show it in an <img>).XXXX-XXXX-XXXX. Each is accepted once in place of an authenticator code — at sign-in (/auth/mfa), /mfa/verify, /mfa/disable and regenerate (not at /mfa/activate). Check how many are left with /mfa/backup-codes.Errors
{"error": "…", "code": "interactive_session_required"}.MFA is already enabled for this account. Disable it first (requires your password and a current code) before re-enrolling.Content-Type: application/json header is missing.Failed to save MFA record).