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_MISSING401

No authentication token provided

When: Request has no Authorization header or access_token cookie

AUTH_INVALID401

Token is malformed or signature is invalid

When: JWT cannot be parsed or signature verification fails

AUTH_EXPIRED401

Authentication token has expired

When: JWT exp claim is in the past

AUTH_FAILED401

Login credentials are incorrect

When: Email/password mismatch or user not found during login

2FA_REQUIRED401

Two-factor authentication is required

When: User has TOTP enabled and must verify before receiving tokens

SESSION_EXPIRED401

Refresh token or session has expired

When: Refresh token is no longer valid or session was revoked

ACCOUNT_SUSPENDED403

Account has been suspended by an administrator

When: User is_suspended=true in database

ACCOUNT_LOCKED403

Account is temporarily locked due to failed login attempts

When: locked_until is in the future after too many failed logins

Authorization4

FORBIDDEN403

User does not have access to this resource

When: Role-based check fails (e.g., investor accessing admin routes)

PERMISSION_DENIED403

User lacks the required permission

When: RBAC permission check fails (e.g., missing users.manage)

KYC_REQUIRED403

KYC verification must be completed first

When: Action requires approved KYC but user status is pending/rejected

ACCREDITATION_REQUIRED403

Investor accreditation is required

When: Attempting to invest in accredited-only token offerings

Input Validation3

INVALID_BODY400

Request body cannot be parsed

When: Malformed JSON or missing required fields in POST/PUT/PATCH

INVALID_PARAM400

URL parameter is invalid

When: Path or query parameter fails validation (e.g., invalid UUID)

VALIDATION400

Business rule validation failed

When: Field values are syntactically valid but violate business rules

Business Logic7

CONFLICT409

Operation conflicts with current state

When: Attempting duplicate registration, re-approving KYC, etc.

DUPLICATE_ENTRY409

Resource already exists

When: Creating a resource that violates a unique constraint

NOT_FOUND404

Requested resource does not exist

When: Entity lookup by ID returns no rows

INSUFFICIENT_BALANCE400

Wallet balance is too low for the operation

When: Placing an order or transferring more than available balance

TOKEN_NOT_TRADEABLE400

Token is not in a tradeable status

When: Attempting to trade a token that is draft, paused, matured, or delisted

INVALID_TOKEN_STATUS400

Token cannot transition to the requested status

When: Invalid lifecycle transition (e.g., draft directly to secondary)

ORDER_NOT_CANCELLABLE400

Order cannot be cancelled in its current state

When: Attempting to cancel a filled, already-cancelled, or expired order

Rate Limiting1

RATE_LIMITED429

Too many requests in a given time window

When: Client exceeds the configured rate limit (default: 100 req/min)

Internal1

INTERNAL500

An 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);
  }
}