API Docs
Error Codes

Error Codes

All API errors follow a consistent JSON format.

Error Format

{
  "error": {
    "code": "INVALID",
    "message": "email is required",
    "field": "email"
  }
}
FieldTypeDescription
codestringMachine-readable error code (see table below)
messagestringHuman-readable description
fieldstring(optional) The request field that caused the error

Error Code Reference

CodeHTTP StatusDescription
INVALID400Request validation failed — missing or malformed field
WEAK_MASTER_PASSWORD400Master password does not meet strength requirements
REGISTRATION_DISABLED400Open registration is disabled on this server
INVITE_REQUIRED400Invite token is required (server registration mode is invite)
INVITE_NOT_REDEEMABLE400Invite token is expired, already used, or revoked
INVALID_ROLE400Invalid role value provided
UNAUTHENTICATED401No access token provided or token is malformed
TOKEN_INVALID401Access token signature verification failed
INVALID_CREDENTIALS401Email or auth hash does not match
SESSION_EXPIRED401Refresh token has expired or been revoked
API_KEY_INVALID401API key not found or has been deleted
API_KEY_EXPIRED401API key has passed its expiration date
FORBIDDEN403Authenticated but lacking permission for this action
STEP_UP_REQUIRED403Operation requires a step-up access token
NOT_FOUND404Resource does not exist or is not accessible
CONFLICT409Resource already exists (e.g., duplicate email)
ACCOUNT_LOCKED423Too many failed login attempts — account temporarily locked
RATE_LIMITED429Request rate limit exceeded
INTERNAL500Unexpected server error

Common Scenarios

Validation Error

curl -X POST https://vault.example.com/api/v1/auth/register \
  -H "Content-Type: application/json" \
  -d '{}'
{
  "error": {
    "code": "INVALID",
    "message": "email is required",
    "field": "email"
  }
}

Invalid Credentials

{
  "error": {
    "code": "INVALID_CREDENTIALS",
    "message": "invalid email or password"
  }
}

The error message is intentionally vague — it does not reveal whether the email exists or the password was wrong.

Account Locked

{
  "error": {
    "code": "ACCOUNT_LOCKED",
    "message": "account temporarily locked due to too many failed attempts"
  }
}

After 5 consecutive failed login attempts, the account is locked for 15 minutes (configurable via LOCKOUT_DURATION).

Rate Limited

{
  "error": {
    "code": "RATE_LIMITED",
    "message": "too many requests"
  }
}

The response includes a Retry-After header indicating when to retry (in seconds).


Step-Up Handling Flow

Several sensitive operations return STEP_UP_REQUIRED if called without a step-up token. Here is the recommended client flow:

Attempt the protected operation

curl -X DELETE -H "Authorization: Bearer <access_token>" \
     https://vault.example.com/api/v1/vaults/660e8400-.../trash/880e8400-...

Response:

{
  "error": {
    "code": "STEP_UP_REQUIRED",
    "message": "this operation requires re-authentication"
  }
}

Prompt the user for their master password

Re-derive the auth hash from the master password using the stored KDF parameters.

Obtain a step-up token

curl -X POST https://vault.example.com/api/v1/auth/step-up \
  -H "Authorization: Bearer <access_token>" \
  -H "Content-Type: application/json" \
  -d '{"authHash": "base64-encoded-auth-hash"}'

Retry the operation with the step-up token

curl -X DELETE -H "Authorization: Bearer <step_up_token>" \
     https://vault.example.com/api/v1/vaults/660e8400-.../trash/880e8400-...
⚠️

Step-up tokens expire after 5 minutes. If the token expires before the operation completes, you will need to request a new one.

Operations Requiring Step-Up

EndpointDescription
POST /auth/password/changeChange master password
POST /auth/totp/setupBegin TOTP setup
POST /auth/totp/disableDisable TOTP
DELETE /vaults/:id/trash/:idPermanently purge a trashed item
DELETE /vaults/:id/trashBulk purge expired trash
GET /exportExport vault data