Skip to content
On this page

2FA API

The Two-Factor Authentication API adds a second verification step to the login flow and to related session-sensitive actions.

The goal is simple: keep authentication easy for users while making account access safer for developers and product teams.

How to read this page

Each route is documented as a normal operation-style page so the flow is easy to follow.

Base path

All routes live under /auth/two_factor/.

How it works

  1. The user logs in with password or social auth.
  2. If 2FA is required, the server creates a short-lived pending session.
  3. The server sends a 6-digit numeric code by email.
  4. The client submits the code to the verify route.
  5. The session is promoted to active after successful verification.

Route map

MethodPathAuthPurpose
GET/auth/two_factor/systemPublicCheck whether 2FA is enabled and which methods are available
GET/auth/two_factor/methodsSessionList the user’s active 2FA methods
POST/auth/two_factor/email/setupSessionStart email 2FA setup
POST/auth/two_factor/sms/setupSessionStart SMS 2FA setup
POST/auth/two_factor/:method/startPending or active sessionResend a code for a method
POST/auth/two_factor/verifyPending or active sessionVerify a code and activate the session
DELETE/auth/two_factor/:idSessionRemove a method
POST/auth/two_factor/toggleSessionEnable or disable 2FA for the user

Route details

System and methods

GET /auth/two_factor/system

Return global availability and method list.

Auth: public.

GET /auth/two_factor/methods

List the current user’s active methods.

Auth: session.

Setup

POST /auth/two_factor/email/setup

Start email 2FA setup.

Auth: session.

POST /auth/two_factor/sms/setup

Start SMS 2FA setup.

Auth: session.

Verification flow

POST /auth/two_factor/:method/start

Resend a code for a method.

Auth: pending or active session.

Body:

json
{
  "action": "login"
}

POST /auth/two_factor/verify

Verify a code and activate the session.

Auth: pending or active session.

Body:

json
{
  "code": "482913",
  "method": "email",
  "action": "login"
}

Maintenance

DELETE /auth/two_factor/:id

Remove a method.

Auth: session.

POST /auth/two_factor/toggle

Enable or disable 2FA for the user.

Auth: session.

Example: check system availability

http
GET /auth/two_factor/system

Example response:

json
{
  "success": true,
  "data": {
    "global_two_factor_enabled": true,
    "available_methods": ["email"]
  }
}

Example: start a login challenge

http
POST /auth/two_factor/email/start
Content-Type: application/json

{
  "action": "login"
}

Example response:

json
{
  "success": true,
  "data": {
    "method": "email",
    "status": "pending",
    "expires_in_seconds": 600
  }
}

Example: verify a code

http
POST /auth/two_factor/verify
Content-Type: application/json

{
  "code": "482913",
  "method": "email",
  "action": "login"
}

Example response:

json
{
  "success": true,
  "data": {
    "verified": true,
    "session_status": "active",
    "two_factor_verified": 1
  }
}

Important behavior

  • The code is 6 digits and numeric.
  • The code is treated as short-lived and must be verified within the session window.
  • A pending session is not the final session; it becomes active only after verification.
  • The flow is meant to be understandable to the frontend, not hidden behind vague auth behavior.

Typical login flow

  1. User submits credentials.
  2. Server returns a 2FA challenge instead of a full login session.
  3. User enters the code from email.
  4. Client submits the code to verify.
  5. Server activates the session and returns success.

Practical notes

  • Keep login and verification steps separate in the UI.
  • Treat the pending session as a temporary state, not a broken login.
  • Make the 2FA screen explicit so developers can reason about it quickly.

Next