Workspace MFA (v1)
Method & Path
POST /api/v1/workspace/mfa/phone/start
POST /api/v1/workspace/mfa/phone/verify
POST /api/v1/workspace/mfa/totp/setup
POST /api/v1/workspace/mfa/totp/confirm
POST /api/v1/workspace/mfa/backup-codes/generate
POST /api/v1/workspace/mfa/backup-codes/regenerate
GET /api/v1/workspace/mfa/backup-codes/count
GET /api/v1/workspace/mfa/methods
PATCH /api/v1/workspace/mfa/methods/:methodId/primary
DELETE /api/v1/workspace/mfa/methods/:methodId
Description
Multi-factor authentication (MFA) endpoints for workspace owners. Supports multiple MFA methods:
- Phone OTP: SMS-based one-time password
- TOTP: Time-based one-time password (authenticator apps)
- Backup Codes: Recovery codes for account access
Authentication
Required: Workspace authentication required for all endpoints. User must be authenticated as Workspace Owner.
Base Path
All endpoints use the base path:
/api/v1/workspace/mfa
Endpoints
Phone OTP Enrollment
Start Phone OTP Enrollment
POST /api/v1/workspace/mfa/phone/start
Start phone OTP enrollment by sending verification code to phone number.
Headers
Authorization: Bearer <workspace_token>
Content-Type: application/json
Request Body
{
"phoneNumber": "+1234567890"
}
Request Fields
phoneNumber(string, required): Phone number in E.164 format
Response 200 OK
{
"success": true,
"message": "OTP sent to phone number"
}
Common Errors
- 400 Bad Request: Invalid phone number format
- 401 Unauthorized: Workspace authentication required
Verify Phone OTP Enrollment
POST /api/v1/workspace/mfa/phone/verify
Verify phone OTP code to complete enrollment.
Headers
Authorization: Bearer <workspace_token>
Content-Type: application/json
Request Body
{
"otpCode": "123456",
"setAsPrimary": false
}
Request Fields
otpCode(string, required): 6-digit OTP code from SMSsetAsPrimary(boolean, optional): Set as primary MFA method (default: false)
Response 200 OK
{
"success": true,
"message": "Phone OTP method enrolled successfully"
}
Common Errors
- 400 Bad Request: Invalid OTP code
- 401 Unauthorized: Workspace authentication required
TOTP Enrollment
Setup TOTP
POST /api/v1/workspace/mfa/totp/setup
Generate a TOTP secret and QR code for workspace owner.
Headers
Authorization: Bearer <workspace_token>
Response 200 OK
{
"otpauthUri": "otpauth://totp/Placio:user@example.com?secret=JBSWY3DPEHPK3PXP&issuer=Placio",
"qrCodeDataUrl": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA..."
}
Response Fields
otpauthUri(string): URI for adding to authenticator appqrCodeDataUrl(string): Base64-encoded QR code image
Notes
- Secret is encrypted and stored securely
- QR code can be scanned with any TOTP authenticator app
- Setup must be confirmed with
/totp/confirmendpoint
Confirm TOTP Enrollment
POST /api/v1/workspace/mfa/totp/confirm
Confirm TOTP enrollment by verifying a code from the authenticator app.
Headers
Authorization: Bearer <workspace_token>
Content-Type: application/json
Request Body
{
"totpCode": "123456",
"setAsPrimary": false
}
Request Fields
totpCode(string, required): 6-digit TOTP code from authenticator appsetAsPrimary(boolean, optional): Set as primary MFA method (default: false)
Response 200 OK
{
"success": true,
"message": "TOTP method enrolled successfully"
}
Common Errors
- 400 Bad Request: Invalid TOTP code
- 401 Unauthorized: Workspace authentication required
Backup Codes
Generate Backup Codes
POST /api/v1/workspace/mfa/backup-codes/generate
Generate backup codes for account recovery.
Headers
Authorization: Bearer <workspace_token>
Content-Type: application/json
Request Body
{
"count": 10
}
Request Fields
count(number, optional): Number of codes to generate (8-10, default: 10)
Response 200 OK
{
"codes": [
"ABCD-1234-EFGH",
"IJKL-5678-MNOP",
"..."
],
"message": "Backup codes generated. Please save them securely. They will not be shown again."
}
Response Fields
codes(array): Array of backup codes (shown only once)message(string): Instructions for saving codes
Notes
- Codes are shown only once - must be saved securely
- Each code can be used only once
- Codes should be stored in a secure location
Regenerate Backup Codes
POST /api/v1/workspace/mfa/backup-codes/regenerate
Regenerate backup codes, invalidating old unused codes.
Headers
Authorization: Bearer <workspace_token>
Content-Type: application/json
Request Body
{
"count": 10
}
Request Fields
count(number, optional): Number of codes to generate (default: 10)
Response 200 OK
{
"codes": [
"WXYZ-9012-STUV",
"..."
],
"message": "Backup codes regenerated. Old unused codes have been invalidated."
}
Notes
- Old unused codes are invalidated
- Used codes remain valid until regenerated
- New codes must be saved securely
Get Backup Codes Count
GET /api/v1/workspace/mfa/backup-codes/count
Get count of remaining unused backup codes.
Headers
Authorization: Bearer <workspace_token>
Response 200 OK
{
"count": 7
}
Response Fields
count(number): Number of remaining unused backup codes
MFA Methods Management
List MFA Methods
GET /api/v1/workspace/mfa/methods
Get list of enrolled MFA methods.
Headers
Authorization: Bearer <workspace_token>
Response 200 OK
{
"methods": [
{
"id": "507f1f77bcf86cd799439011",
"type": "phone_otp",
"isPrimary": true,
"enabled": true,
"phoneVerifiedAt": "2024-01-15T10:00:00.000Z",
"createdAt": "2024-01-15T10:00:00.000Z",
"updatedAt": "2024-01-15T10:00:00.000Z"
},
{
"id": "507f1f77bcf86cd799439012",
"type": "totp",
"isPrimary": false,
"enabled": true,
"totpConfirmedAt": "2024-01-15T11:00:00.000Z",
"createdAt": "2024-01-15T11:00:00.000Z",
"updatedAt": "2024-01-15T11:00:00.000Z"
}
]
}
Response Fields
methods(array): Array of MFA methodsid(string): Method IDtype(string): Method type (phone_otportotp)isPrimary(boolean): Whether this is the primary methodenabled(boolean): Whether method is enabledphoneVerifiedAt(string, optional): Phone verification timestamptotpConfirmedAt(string, optional): TOTP confirmation timestampcreatedAt(string): Creation timestampupdatedAt(string): Last update timestamp
Notes
- Sensitive data (phone numbers, secrets) are not returned
- Only enabled methods are returned
Set Primary Method
PATCH /api/v1/workspace/mfa/methods/:methodId/primary
Set a method as the primary MFA method.
Headers
Authorization: Bearer <workspace_token>
Content-Type: application/json
Path Parameters
methodId(string, required): MFA method ID
Request Body
{
"methodId": "507f1f77bcf86cd799439011"
}
Response 200 OK
{
"success": true,
"message": "Primary method updated"
}
Common Errors
- 400 Bad Request: Invalid method ID
- 401 Unauthorized: Workspace authentication required
- 404 Not Found: MFA method not found
Notes
- Only one method can be primary at a time
- Setting a new primary method unsets the previous one
Delete MFA Method
DELETE /api/v1/workspace/mfa/methods/:methodId
Disable an MFA method (soft delete).
Headers
Authorization: Bearer <workspace_token>
Path Parameters
methodId(string, required): MFA method ID
Response 200 OK
{
"success": true,
"message": "MFA method disabled"
}
Common Errors
- 400 Bad Request: Invalid method ID
- 401 Unauthorized: Workspace authentication required
- 404 Not Found: MFA method not found
Notes
- Method is disabled (soft delete), not permanently deleted
- Cannot disable if it's the only enabled method and workspace requires MFA
MFA Verification During Login
MFA verification during login is handled by the authentication endpoints:
- POST
/api/v1/auth/mfa/phone/send- Send OTP for login challenge - POST
/api/v1/auth/mfa/verify- Verify MFA challenge
See Authentication Endpoints for details.
Security Notes
- TOTP secrets are encrypted at rest
- Phone numbers are stored securely
- Backup codes are hashed before storage
- QR codes are only shown once during setup
- Challenge-based verification prevents replay attacks
- Maximum 5 attempts per challenge
- Challenges expire after set time period
Use Cases
- Enhanced Security: Add extra layer of protection to workspace accounts
- Multiple Methods: Support different MFA methods for user preference
- Account Recovery: Backup codes provide recovery option
- Compliance: Meet security requirements for sensitive operations