Errors

Error format, status codes, and rate limits

All errors are returned as JSON with a consistent shape.

Error format

{
  "statusCode": 401,
  "message": "Unauthorized"
}

message is a string for a single error. When validation fails it can be an array of strings:

{
  "statusCode": 400,
  "message": ["displayName must be shorter than or equal to 64 characters"]
}

Status codes

StatusMeaning
200Success
204Success, no content (e.g. POST /v1/auth/refresh)
302Redirect (Google OAuth flow)
400Validation error — one or more fields are invalid
401Missing, expired, or invalid access/refresh token
403Authenticated but forbidden — e.g. withdrawals disabled, admin-only route, revoked grant
404Identity, profile, or wallet does not exist
409Conflict — e.g. email already associated with another account, PID already taken, or credential already linked
410Gone — claim ticket expired; sign in again for a fresh one
429Rate limit exceeded
503Google OAuth is not configured on the server

Authentication errors

A 401 from a protected endpoint means the access token is missing or expired. Recover by calling POST /v1/auth/refresh. If refresh itself returns 401, the session is unrecoverable and the user must sign in again.

Rate limits

Auth endpoints are rate limited to protect against brute force:

EndpointLimit
POST /v1/auth/refresh10 requests / minute
POST /v1/auth/login20 requests / minute
POST /v1/auth/logout20 requests / minute
POST /v1/auth/exchange20 requests / minute
POST /v1/auth/authorize20 requests / minute
POST /v1/apps10 requests / minute
GET /v1/apps30 requests / minute
PATCH /v1/apps/:id20 requests / minute
POST /v1/apps/:id/secret5 requests / minute
POST /v1/apps/:id/webhook5 requests / minute
GET /v1/apps/:id/fees30 requests / minute
PUT /v1/apps/:id/fees/:operation20 requests / minute
POST /v1/auth/token20 requests / minute
POST /v1/fiat/deposits/checkout10 requests / minute
POST /v1/fiat/transfers/inquiry, …/confirm10 requests / minute
POST /v1/fiat/deposits/:id/sync12 requests / minute
GET /v1/auth/google, /v1/auth/google/callback100 requests / minute
POST /v1/wallet10 requests / minute

Exceeding a limit returns 429. Clients should back off and retry.

Fiat errors

Fiat endpoints return the same JSON shape, but the SDK fiat methods throw (a plain Error whose message is the server message) instead of returning the T | ApiError union that auth/wallet reads use. Handle them with try/catch:

try {
  await peridot.fiat.transferConfirm(inquiryId);
} catch (e) {
  // e.message: "Insufficient internal credit", "Amount too small…", etc.
}

Common fiat statuses: 400 (bad amount / net too small), 401 (no session), 404 (unknown recipient / transaction), 503 (ledger disabled or frozen).

SDK popup errors

Trust-critical SDK calls in popup mode throw instead of returning unions:

ErrorMeaning
PopupBlockedErrorBrowser blocked the popup — ask the user to allow popups, then retry
PopupClosedErrorUser closed the window, or it timed out (login 5 min, approval 2 min)
PopupUnavailableErrorNo popupBaseUrl set, or not running in a browser
Error("…rejected…")User pressed Deny, or the host rejected a malformed/tampered request

A closed or timed-out popup never resolves — treat it as rejected.

On this page