Skip to main content

Documentation Index

Fetch the complete documentation index at: https://alphabet-06152314.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

Alphabet supports two MFA methods: a TOTP authenticator app (such as Google Authenticator or Authy) and OTP delivery over email or SMS. Once you enable either method, a standard POST /api/v1/auth/login call no longer returns your access and refresh tokens directly — instead it returns a short-lived mfaToken that you exchange for tokens by completing the MFA challenge.
All MFA enrollment endpoints require an authenticated session. Complete registration and login before enabling MFA.

Authenticator app (TOTP)

1

Start enrollment

Call POST /api/v1/auth/mfa/enable-authenticator. The response contains an authenticatorUri (an otpauth:// URI you can render as a QR code) and a manualEntryKey for users who cannot scan a QR code.
curl -X POST https://your-api/api/v1/auth/mfa/enable-authenticator \
  -H "Authorization: Bearer <accessToken>"
Response200 OK
{
  "authenticatorUri": "otpauth://totp/Alphabet:user@example.com?secret=JBSWY3DPEHPK3PXP&issuer=Alphabet",
  "manualEntryKey": "JBSWY3DPEHPK3PXP"
}
2

Scan the QR code or enter the manual key

Open your authenticator app and either scan the QR code you rendered from authenticatorUri or manually type in the manualEntryKey. Your app will start generating 6-digit TOTP codes.
3

Verify and complete enrollment

Submit the 6-digit code from your authenticator app to POST /api/v1/auth/mfa/verify-authenticator. On success, TOTP MFA is fully enabled and the response returns your recovery codes.
curl -X POST https://your-api/api/v1/auth/mfa/verify-authenticator \
  -H "Authorization: Bearer <accessToken>" \
  -H "Content-Type: application/json" \
  -d '{ "verificationCode": "123456" }'
Request body
{
  "verificationCode": "123456"
}
Response200 OK
{
  "recoveryCodes": [
    "a1b2-c3d4",
    "e5f6-g7h8",
    "i9j0-k1l2",
    "m3n4-o5p6",
    "q7r8-s9t0",
    "u1v2-w3x4",
    "y5z6-a7b8",
    "c9d0-e1f2",
    "g3h4-i5j6",
    "k7l8-m9n0"
  ]
}
4

Save your recovery codes

Copy and store the recovery codes in a secure location. Each code can be used only once to sign in if you lose access to your authenticator app.
Recovery codes are shown only once. If you lose them and lose access to your authenticator app, you cannot recover your account without administrator intervention.

OTP delivery

1

Enable OTP

Call POST /api/v1/auth/mfa/enable-otp to request that a one-time code be sent to you through the configured delivery channel (email or SMS). A 200 OK response means the code is on its way.
curl -X POST https://your-api/api/v1/auth/mfa/enable-otp \
  -H "Authorization: Bearer <accessToken>" \
  -H "Content-Type: application/json" \
  -d '{ "channel": "Email" }'
Request body
{
  "channel": "Email"
}
2

Submit the OTP code

Enter the 6-digit code you received and send it to POST /api/v1/auth/mfa/verify-otp. A 200 OK response confirms OTP MFA is now enabled on your account.
curl -X POST https://your-api/api/v1/auth/mfa/verify-otp \
  -H "Authorization: Bearer <accessToken>" \
  -H "Content-Type: application/json" \
  -d '{ "verificationCode": "654321" }'
Request body
{
  "verificationCode": "654321"
}

MFA login flow

Once MFA is enabled, the login process takes two steps instead of one.
1

Log in as normal

Call POST /api/v1/auth/login with your email and password. Because MFA is active, the response returns an mfaToken instead of a full token pair. This token is valid for 5 minutes.
curl -X POST https://your-api/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com",
    "password": "Password123!",
    "useCookies": false
  }'
Response200 OK
{
  "mfaToken": "eyJhbGci..."
}
2

Complete the MFA challenge

Submit the mfaToken and the current 6-digit code from your authenticator app (or the OTP you received) to POST /api/v1/auth/mfa/login. On success you receive the normal accessToken and refreshToken pair.
curl -X POST https://your-api/api/v1/auth/mfa/login \
  -H "Content-Type: application/json" \
  -d '{
    "mfaToken": "eyJhbGci...",
    "verificationCode": "123456",
    "useCookies": false
  }'
Request body
{
  "mfaToken": "eyJhbGci...",
  "verificationCode": "123456",
  "useCookies": false
}
Response200 OK
{
  "accessToken": "eyJ...",
  "refreshToken": "abc123..."
}
Set useCookies: true to receive HttpOnly cookies instead of tokens in the response body. See the authentication overview for details.
You can use a recovery code in place of a TOTP or OTP code in the verificationCode field. Each recovery code is valid for a single use.

Recovery codes

Recovery codes let you sign in when you cannot access your MFA device.

View current recovery codes

GET /api/v1/auth/mfa/recovery-codes returns your currently active codes. Requires a valid Authorization header.
curl https://your-api/api/v1/auth/mfa/recovery-codes \
  -H "Authorization: Bearer <accessToken>"
Response200 OK
{
  "recoveryCodes": [
    "a1b2-c3d4",
    "e5f6-g7h8"
  ]
}

Regenerate recovery codes

If your codes are compromised or you have used most of them, call POST /api/v1/auth/mfa/recovery-codes/regenerate. This immediately invalidates all existing codes and returns a fresh set of 10.
curl -X POST https://your-api/api/v1/auth/mfa/recovery-codes/regenerate \
  -H "Authorization: Bearer <accessToken>"
Response200 OK
{
  "recoveryCodes": [
    "z9y8-x7w6",
    "v5u4-t3s2",
    "r1q0-p9o8",
    "n7m6-l5k4",
    "j3i2-h1g0",
    "f9e8-d7c6",
    "b5a4-z3y2",
    "x1w0-v9u8",
    "t7s6-r5q4",
    "p3o2-n1m0"
  ]
}
Regenerating recovery codes immediately invalidates all previous codes. Save the new codes in a secure location before closing the response.

Troubleshooting

Check that EmailSettings (SMTP server, API key, from address) and SmsSettings (AccountSid, AuthToken, FromNumber) are correctly configured in appsettings.json. Also confirm that the Communication.EnabledChannels list includes the channel you are using (Email or Sms).
OTP codes expire after 5 minutes (MfaSettings.OtpExpiryMinutes). If verification fails, confirm the cache provider is running correctly — OTP codes are stored in the configured cache backend. Also verify that your server clock is synchronized (NTP) because TOTP codes are time-based.
TOTP codes depend on accurate system time. Ensure the server and authenticator device clocks are synchronized within 30 seconds. If your authenticator app has a “sync clock” option, use it.
After 5 consecutive failed login attempts the account is locked for 5 minutes (LockoutSettings.MaxFailedAttempts, LockoutSettings.LockoutDurationMinutes). An administrator can unlock the account immediately using POST /api/v1/admin/users/{userId}/unlock.