Skip to content

MFA API Reference

The MFA API allows dashboard clients to manage TOTP enrollment and recovery codes for the authenticated account.

Interactive sessions only

All MFA write endpoints require an interactive browser session (cookie JWT or short-lived Bearer JWT). Static access tokens receive 403 Forbidden. CLI and Terraform provider calls are unaffected by MFA enrollment.

Endpoints

Method Path Description
GET /accounts/me Current account — includes mfa field
POST /accounts/mfa/setup Provision TOTP (step 1) or verify and enable (step 2)
DELETE /accounts/mfa Disable TOTP and clear all recovery codes
POST /accounts/mfa/recovery-codes/regenerate Regenerate recovery codes

All responses use the standard response envelope:

{
  "metadata": { "request_id": "..." },
  "data": { ... }
}

MFA status on the current account

GET /accounts/me
Authorization: Bearer <token>

The mfa field on the AccountMe response reports enrollment state. The response also includes memberships[] (all organizations the account belongs to), current_organization_id, and project_memberships[] (per-project grants):

{
  "metadata": { "request_id": "req_...", "organization_id": "a1b2c3d4-..." },
  "data": {
    "id": "...",
    "email": "you@example.com",
    "role": "member",
    "current_organization_id": "a1b2c3d4-...",
    "memberships": [
      {
        "id": "m1...",
        "organization_id": "a1b2c3d4-...",
        "role": "admin",
        "permissions": { "projects": ["read", "create", "update", "delete"] }
      }
    ],
    "mfa": {
      "enrolled": true,
      "recovery_codes_remaining": 14,
      "last_used_at": "2026-06-05T10:30:00Z"
    }
  }
}

mfa field shape:

Field Type Description
enrolled boolean true when TOTP is set up
recovery_codes_remaining integer \| null Unused recovery codes. null when not enrolled.
last_used_at string (ISO 8601) \| null When MFA was last successfully used. null if never.

When not enrolled: mfa.enrolled is false and recovery_codes_remaining is null.


Enroll in TOTP — two-step flow

TOTP enrollment is a two-step process using the same endpoint.

Step 1 — Provision

POST /accounts/mfa/setup
Authorization: Bearer <token>
Content-Type: application/json

{}

Returns the provisioning data:

{
  "metadata": { "request_id": "req_..." },
  "data": {
    "provisioning_uri": "otpauth://totp/b%27nerd%20cloud%3Ayou%40example.com?secret=JBSWY3DPEHPK3PQ&issuer=b%27nerd+cloud",
    "qr_code_svg": "<svg ...>...</svg>",
    "raw_secret": "JBSWY3DPEHPK3PQ"
  }
}
Field Description
provisioning_uri Standard otpauth:// URI — pass to an authenticator app
qr_code_svg Inline SVG of the QR code — render as <img src="data:image/svg+xml;base64,...">
raw_secret Base32 secret for manual entry. Hold this value to submit in step 2.

Step 2 — Verify and enable

Submit the 6-digit code from the authenticator app along with the raw_secret returned by step 1:

POST /accounts/mfa/setup
Authorization: Bearer <token>
Content-Type: application/json

{
  "otp_code": "123456",
  "raw_secret": "JBSWY3DPEHPK3PQ"
}

On success, returns the recovery codes (shown once — store them immediately):

{
  "metadata": { "request_id": "req_..." },
  "data": {
    "recovery_codes": [
      "a3f7-29c1",
      "b8e1-f3a0",
      "c12b-8d4f",
      "d9e2-7b5a",
      "e4f3-6c1d",
      "f5g4-5d2e",
      "g6h5-4e3f",
      "h7i6-3f4g",
      "i8j7-5h5h",
      "j9k8-6i6i",
      "k0l9-7j7j",
      "l1m0-8k8k",
      "m2n1-9l9l",
      "n3o2-0m0m",
      "o4p3-1n1n",
      "p5q4-2o2o"
    ]
  }
}

16 recovery codes are returned. Each code is single-use.

Error responses for step 2:

Status code Description
422 invalid_otp_code Code incorrect or expired
422 missing_raw_secret raw_secret not provided
403 forbidden Static access token not permitted

Disable MFA

DELETE /accounts/mfa
Authorization: Bearer <token>
Content-Type: application/json

{
  "password": "your-current-password"
}

Clears the TOTP key and all recovery codes. Returns 204 No Content on success.

Error responses:

Status code Description
422 invalid_password Password incorrect
422 mfa_not_enrolled No TOTP enrollment exists
403 forbidden Static access token not permitted

Regenerate recovery codes

POST /accounts/mfa/recovery-codes/regenerate
Authorization: Bearer <token>
Content-Type: application/json

{
  "password": "your-current-password"
}

Deletes all existing recovery codes and generates a fresh set of 16. The response is the same shape as the step-2 enrollment response:

{
  "metadata": { "request_id": "req_..." },
  "data": {
    "recovery_codes": ["a3f7-29c1", ...]
  }
}

Error responses:

Status code Description
422 invalid_password Password incorrect
422 mfa_not_enrolled TOTP is not enrolled
403 forbidden Static access token not permitted

Interactive API reference

All MFA endpoints are browsable in the Interactive Reference under the Accounts tag.