Authentication
JWT login, registration, MFA, token refresh, and password reset.
Auth Methods
BoxOwl supports three authentication methods:
- User JWT — for user sessions from the Android app, browser extension, and web. Header:
Authorization: Bearer <jwt>. - Agent Token — opaque
bot_…tokens scoped to a single user with explicit expiry, for AI agents and automation. Header:X-Agent-Token: bot_…. - Organization API Key — opaque
boxlive_…keys for PDaaS integrations. Header:X-API-Key: boxlive_…. See PDaaS docs.
Register
/api/v1/auth/register
No auth required. Creates a new account. If enableMfa is true, returns TOTP secret and QR URL for MFA setup.
curl -X POST https://api.boxowl.me/api/v1/auth/register \
-H "Content-Type: application/json" \
-d '{
"email": "alice@example.com",
"password": "YourSecurePass123!",
"handle": "alice",
"enableMfa": false
}'
Response 201 Created:
{
"userId": "usr_01h455vb4pex5vsknk084sn02q",
"handle": "alice",
"mfaSecret": null,
"mfaQrUrl": null
}
With MFA enabled:
{
"userId": "usr_01h455vb4pex5vsknk084sn02q",
"handle": "alice",
"mfaSecret": "BASE32SECRETHEXTVALUE",
"mfaQrUrl": "otpauth://totp/BoxOwl:alice@example.com?secret=BASE32SECRETHEXTVALUE&issuer=BoxOwl"
}
Response 409 Conflict (BOX-409-001):
{
"error": "BOX-409-001",
"message": "Email or handle already in use",
"hint": "Log in instead, or choose a different handle.",
"suggestedAction": "POST /api/v1/auth/login"
}
Login
/api/v1/auth/login
Authenticates with email + password. If MFA is enabled, returns mfaRequired: true and requires a second request with mfaCode.
curl -X POST https://api.boxowl.me/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "alice@example.com",
"password": "YourSecurePass123!"
}'
Response 200 OK (no MFA):
{
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expiresIn": 86400,
"mfaRequired": false,
"userId": "usr_01h455vb4pex5vsknk084sn02q"
}
Response 200 OK (MFA required):
{
"accessToken": null,
"refreshToken": null,
"expiresIn": null,
"mfaRequired": true,
"mfaToken": "mfa_01h455vb4pex5vsknk084sn02q"
}
Complete MFA login:
curl -X POST https://api.boxowl.me/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "alice@example.com",
"password": "YourSecurePass123!",
"mfaCode": "123456"
}'
Refresh Token
/api/v1/auth/refresh
Exchange a valid refresh token for a new access token. Refresh tokens are valid for 30 days.
curl -X POST https://api.boxowl.me/api/v1/auth/refresh \
-H "Content-Type: application/json" \
-d '{
"refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}'
Response 200 OK:
{
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expiresIn": 86400
}
Logout
/api/v1/auth/logout
Invalidates the current session server-side. Returns 204 No Content.
curl -X POST https://api.boxowl.me/api/v1/auth/logout \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."
Reset Password
/api/v1/auth/reset-password
Sends a password reset email to the account. No auth required. Token expires in 1 hour.
curl -X POST https://api.boxowl.me/api/v1/auth/reset-password \
-H "Content-Type: application/json" \
-d '{ "email": "alice@example.com" }'
Response 200 OK (always succeeds, even if email not found — prevents enumeration):
{
"message": "If that email exists, a reset link has been sent."
}
MFA Setup
After registration with enableMfa: true, activate TOTP by calling the MFA verify endpoint:
/api/v1/auth/mfa/verify
Verify a TOTP code to activate MFA on the account.
curl -X POST https://api.boxowl.me/api/v1/auth/mfa/verify \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '{ "code": "123456" }'
Response 200 OK:
{
"mfaEnabled": true,
"recoveryCodes": ["rc_01h455...", "rc_01h456...", "rc_01h457..."]
}
Save recovery codes securely. Each can only be used once to bypass MFA.