TOTP (Time-based One-Time Password)
TOTP provides two-factor authentication using authenticator apps like Google Authenticator, Authy, or 1Password.
TOTP must be enabled by the server administrator. If disabled, these endpoints will return 400 Bad Request.
Get TOTP Status
GET /api/user/mfa/totp Check if TOTP is enabled and generate setup credentials if needed.
Request
curl -X GET https://your-zipline.com/api/user/mfa/totp \
-H "Authorization: YOUR_TOKEN"
Response (TOTP Not Enabled)
If you haven’t set up TOTP yet:
Base32-encoded secret key to enter manually
Data URL containing QR code image for scanning
{
"secret" : "JBSWY3DPEHPK3PXP" ,
"qrcode" : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUg..."
}
Response (TOTP Already Enabled)
If TOTP is already configured:
{
"secret" : "JBSWY3DPEHPK3PXP"
}
Enable TOTP
POST /api/user/mfa/totp Verify and activate TOTP authentication.
Request
6-digit verification code from your authenticator app
The secret key returned from GET /api/user/mfa/totp
curl -X POST https://your-zipline.com/api/user/mfa/totp \
-H "Authorization: YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"code": "123456",
"secret": "JBSWY3DPEHPK3PXP"
}'
Response
Returns the updated user object with TOTP enabled.
Errors
400 Bad Request : Invalid verification code or TOTP disabled on server
Disable TOTP
DELETE /api/user/mfa/totp Remove TOTP authentication from your account.
Request
Current 6-digit TOTP code to confirm removal
curl -X DELETE https://your-zipline.com/api/user/mfa/totp \
-H "Authorization: YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"code": "123456"
}'
Response
Returns the updated user object with TOTP disabled.
Errors
400 Bad Request : Invalid code, TOTP not enabled, or TOTP disabled on server
Passkeys (WebAuthn)
Passkeys provide passwordless authentication using biometrics, security keys, or device authentication.
Passkeys must be enabled and configured by the server administrator (requires RP ID and Origin). If disabled or misconfigured, these endpoints will return 404 Not Found.
List Passkeys
GET /api/user/mfa/passkey Get all registered passkeys for your account.
Request
curl -X GET https://your-zipline.com/api/user/mfa/passkey \
-H "Authorization: YOUR_TOKEN"
Response
Returns an array of passkey objects (without sensitive registration data).
[
{
"id" : "pk_abc123" ,
"createdAt" : "2024-03-10T14:22:00.000Z" ,
"updatedAt" : "2024-03-15T09:30:00.000Z" ,
"lastUsed" : "2024-03-15T09:30:00.000Z" ,
"name" : "YubiKey 5C" ,
"userId" : "clxxx123456789"
},
{
"id" : "pk_def456" ,
"createdAt" : "2024-02-18T11:45:00.000Z" ,
"updatedAt" : "2024-03-14T16:20:00.000Z" ,
"lastUsed" : "2024-03-14T16:20:00.000Z" ,
"name" : "MacBook Touch ID" ,
"userId" : "clxxx123456789"
}
]
Get Registration Options
GET /api/user/mfa/passkey/options Generate WebAuthn registration options for creating a new passkey.
Request
curl -X GET https://your-zipline.com/api/user/mfa/passkey/options \
-H "Authorization: YOUR_TOKEN"
Response
Returns WebAuthn PublicKeyCredentialCreationOptions for the browser’s navigator.credentials.create() API.
{
"rp" : {
"name" : "Zipline" ,
"id" : "zipline.example.com"
},
"user" : {
"id" : "Y2x4eHgxMjM0NTY3ODk=" ,
"name" : "john_doe" ,
"displayName" : "john_doe"
},
"challenge" : "random-challenge-string" ,
"pubKeyCredParams" : [
{ "type" : "public-key" , "alg" : -7 },
{ "type" : "public-key" , "alg" : -257 }
],
"timeout" : 60000 ,
"excludeCredentials" : [],
"authenticatorSelection" : {
"userVerification" : "preferred" ,
"residentKey" : "preferred"
}
}
Registration options are cached for 3 minutes. Requesting options again within this period returns the same challenge.
Rate Limiting
This endpoint is rate-limited to 1 request per second .
Register Passkey
POST /api/user/mfa/passkey Complete passkey registration with the WebAuthn credential.
Request
WebAuthn RegistrationResponseJSON from navigator.credentials.create()
Friendly name for this passkey (e.g., “YubiKey 5C”, “iPhone 15”)
curl -X POST https://your-zipline.com/api/user/mfa/passkey \
-H "Authorization: YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "YubiKey 5C",
"response": {
"id": "credential-id",
"rawId": "credential-id",
"type": "public-key",
"response": {
"clientDataJSON": "...",
"attestationObject": "..."
}
}
}'
Response
Returns the updated user object.
Errors
400 Bad Request : Invalid registration response, expired challenge, or verification failed
429 Too Many Requests : Rate limit exceeded (1 request per second)
Delete Passkey
DELETE /api/user/mfa/passkey Remove a registered passkey from your account.
Request
ID of the passkey to delete
curl -X DELETE https://your-zipline.com/api/user/mfa/passkey \
-H "Authorization: YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"id": "pk_abc123"
}'
Response
Returns the updated user object.
Security Best Practices
Use TOTP and passkeys together for defense in depth
Register multiple passkeys as backups in case you lose a device
Name your passkeys clearly to identify them later (e.g., “Work YubiKey”, “Personal iPhone”)
Review active sessions regularly in /api/user/sessions
If you lose access to all MFA methods and are locked out, contact your server administrator for account recovery.