Self-service, from your own account — not something an Organization admin turns on for you. Manage it from Security, or directly:
GET /api/v1/mfa/status/ -> { enabled, backup_codes_remaining }
POST /api/v1/mfa/enroll/start/ -> { secret, otpauth_uri, qr_code_data_uri }
POST /api/v1/mfa/enroll/confirm/ {code} -> { backup_codes: [...] } (shown once)
POST /api/v1/mfa/disable/ {current_password?}
POST /api/v1/mfa/backup-codes/regenerate/ -> { backup_codes: [...] } (shown once) Once enabled, every sign-in for that account requires a second factor (a 6-digit TOTP code or a backup code) at token-exchange time — this replaces the device/location step-up gate below entirely for that account; a fresh TOTP code is at least as strong a re-proof as the trust gate exists to demand, so both firing would be redundant friction, not additional security.
Disabling MFA requires either your current password or a recent step-up-verified session — never a bare access token alone, since disabling your own second factor is exactly the kind of action a stolen-but-still-valid token should not be able to take unassisted.
For an account without MFA enabled, signing in from a genuinely new device or a new country triggers a step-up challenge instead of completing immediately — the password/Google credential was correct, but that alone isn't treated as enough from an unrecognized context. The response is a real, distinct OAuth error:
error: "step_up_required" Completing a magic link, email code, or passkey verification satisfies the step-up immediately (those are already a real second proof). "Device" is fingerprinted from the user-agent alone — deliberately stable across a network/IP change, so switching wifi networks on the same physical browser never re-triggers this. "Location" is tracked separately, at country granularity — a recognized device signing in from a genuinely new country still gets its own step-up, independent of whether the device itself is known.
Manage your own trusted devices from Security:
GET /api/v1/sessions/me/trusted-devices/
POST /api/v1/sessions/me/trusted-devices/{id}/revoke/ Revoking a trusted device does not revoke any active Session on it — it only means the next sign-in from that device is treated as new again, and will be asked to step up. To end an active session outright, revoke the Session itself — see Sessions.
Signup and every first-factor request that can be attempted anonymously (password
sign-in, magic-link request, email-OTP request) requires a valid Turnstile token,
verified server-side against Cloudflare before the request is processed at all — a
failed or missing token is rejected with turnstile_verification_failed before any real credential/account lookup happens, so it can't be used to probe account
existence either.
Repeated failed password attempts against the same account, from the same IP, lock that specific (account, IP) combination out for a real cooldown window after 5 consecutive failures — a single success resets the counter immediately. This is independent of, and in addition to, the per-endpoint request-rate throttling every auth endpoint already carries.
No hardware security key (FIDO2 roaming authenticator) support distinct from passkeys —
a passkey covers this today for any WebAuthn-capable authenticator, platform or roaming.
No account-recovery flow for a user who has lost both their password and their MFA
device/backup codes simultaneously; account_recovery_initiated/account_recovery_completed exist as reserved audit-log event types but nothing writes them yet.