Documentation Index
Fetch the complete documentation index at: https://docs.calmtreasury.xyz/llms.txt
Use this file to discover all available pages before exploring further.
Envelope
Every non-2xx response shares this shape:
{
"error": {
"code": "validation_error",
"message": "Validation error",
"details": { /* optional, on 400 only */ }
}
}
code — stable, machine-readable, snake_case. Branch on this.
message — human-readable, may change wording.
details — optional structured context (e.g. zod field errors).
Auth + session
| Code | Status | When |
|---|
no_access_token | 401 | SDK’s getAccessToken() returned null. User isn’t signed in. |
token_required | 401 | Missing Authorization: Bearer … on POST /v1/session. |
invalid_token | 401 | JWT signature/claims invalid, malformed, or aud missing. |
token_expired | 401 | JWT past its exp. |
wallet_not_linked | 403 | Privy identity token has no linked_accounts wallet entry. |
session_required | 401 | Cookie missing on a wallet route. Call POST /v1/session. |
session_invalid | 401 | Cookie failed verification or expired. Re-bootstrap. |
wallet_token_mismatch | 403 | URL :address doesn’t match the cookie’s bound wallet. |
Wallet routes
| Code | Status | When |
|---|
invalid_wallet | 400 | URL :address isn’t a valid 0x-prefixed Ethereum address. |
customer_not_registered | 404 | No row yet for (app_id, wallet). Call POST /v1/wallets/:address. |
already_registered | 409 | This wallet is already registered for this app. |
validation_error | 400 | Request body failed schema check. details has the zod errors. |
email_already_in_use | 400 | Bridge rejected — email belongs to another customer in the dev account. |
Virtual account
| Code | Status | When |
|---|
kyc_required | 409 | Bridge customer status isn’t active. Finish KYC first. |
already_has_virtual_account | 409 | Wallet already has a VA. Use GET instead. |
virtual_account_not_provisioned | 404 | No VA exists yet for this wallet. Use POST to create one. |
Upstream
| Code | Status | When |
|---|
bridge_error | 502 | Bridge call failed (timeout, 5xx, or unexpected response). Safe to retry. |
Tips
For browser code, treat all 401s as “re-bootstrap the session”:try {
return await calm.wallets.get(wallet);
} catch (err) {
if (err instanceof CalmApiError && err.status === 401) {
await calm.session(); // re-bootstrap, sets a fresh cookie
return await calm.wallets.get(wallet);
}
throw err;
}
Don’t branch on err.message. We may change wording without notice. Branch
on err.code only.