Error Codes
All API error responses follow a consistent format with a machine-readable code field. There are 24 standardized error codes across 6 categories.
Response Format
{
"success": false,
"error": {
"code": "AUTH_FAILED",
"message": "Invalid email or password",
"status": 401
}
}Auth & Session8
AUTH_MISSING401No authentication token provided
When: Request has no Authorization header or access_token cookie
AUTH_INVALID401Token is malformed or signature is invalid
When: JWT cannot be parsed or signature verification fails
AUTH_EXPIRED401Authentication token has expired
When: JWT exp claim is in the past
AUTH_FAILED401Login credentials are incorrect
When: Email/password mismatch or user not found during login
2FA_REQUIRED401Two-factor authentication is required
When: User has TOTP enabled and must verify before receiving tokens
SESSION_EXPIRED401Refresh token or session has expired
When: Refresh token is no longer valid or session was revoked
ACCOUNT_SUSPENDED403Account has been suspended by an administrator
When: User is_suspended=true in database
ACCOUNT_LOCKED403Account is temporarily locked due to failed login attempts
When: locked_until is in the future after too many failed logins
Authorization4
FORBIDDEN403User does not have access to this resource
When: Role-based check fails (e.g., investor accessing admin routes)
PERMISSION_DENIED403User lacks the required permission
When: RBAC permission check fails (e.g., missing users.manage)
KYC_REQUIRED403KYC verification must be completed first
When: Action requires approved KYC but user status is pending/rejected
ACCREDITATION_REQUIRED403Investor accreditation is required
When: Attempting to invest in accredited-only token offerings
Input Validation3
INVALID_BODY400Request body cannot be parsed
When: Malformed JSON or missing required fields in POST/PUT/PATCH
INVALID_PARAM400URL parameter is invalid
When: Path or query parameter fails validation (e.g., invalid UUID)
VALIDATION400Business rule validation failed
When: Field values are syntactically valid but violate business rules
Business Logic7
CONFLICT409Operation conflicts with current state
When: Attempting duplicate registration, re-approving KYC, etc.
DUPLICATE_ENTRY409Resource already exists
When: Creating a resource that violates a unique constraint
NOT_FOUND404Requested resource does not exist
When: Entity lookup by ID returns no rows
INSUFFICIENT_BALANCE400Wallet balance is too low for the operation
When: Placing an order or transferring more than available balance
TOKEN_NOT_TRADEABLE400Token is not in a tradeable status
When: Attempting to trade a token that is draft, paused, matured, or delisted
INVALID_TOKEN_STATUS400Token cannot transition to the requested status
When: Invalid lifecycle transition (e.g., draft directly to secondary)
ORDER_NOT_CANCELLABLE400Order cannot be cancelled in its current state
When: Attempting to cancel a filled, already-cancelled, or expired order
Rate Limiting1
RATE_LIMITED429Too many requests in a given time window
When: Client exceeds the configured rate limit (default: 100 req/min)
Internal1
INTERNAL500An unexpected server error occurred
When: Unhandled exception, database connection failure, or downstream service error
Frontend Usage
try {
await api.auth.login(email, password);
} catch (err: any) {
if (err.code === "ACCOUNT_LOCKED") {
showMessage("Account locked. Try again later.");
} else if (err.code === "2FA_REQUIRED") {
navigateTo("/2fa");
} else {
showMessage(err.message);
}
}