Every error response fromDocumentation Index
Fetch the complete documentation index at: https://docs.kash.bot/llms.txt
Use this file to discover all available pages before exploring further.
api.kash.bot follows RFC 7807 Problem Details with Content-Type: application/problem+json.
Wire shape
| Field | Use |
|---|---|
type | URI of the per-code documentation page (RFC 7807 §3.1). Stable; safe to fetch. |
title | Short human-readable summary. |
status | The HTTP status (echoed for clients that lose it). |
code | Stable machine-readable string. Branch on this; never on title or detail. |
detail | Sanitised human-readable explanation. May reference the specific bad input. |
instance | URI of the request that produced this error. |
requestId | Trace handle. Include in support tickets — gets you straight to the right span in our backend. |
How to handle errors
Branch oncode, not on status or message text. Status codes are coarse (a 400 could mean any of a dozen specific failures); code is the unambiguous identifier.
KashRateLimitError, KashAuthorizationError, etc.) so you can catch by error type as well.
Status code conventions
| Status | When |
|---|---|
200 | Successful read. |
201 | Successful resource creation (immediate). |
202 | Accepted, work in progress (high-value trade pending confirmation; redelivery). |
304 | If-None-Match cache hit — no body. See ETags. |
400 | Validation failure on the request itself (VALIDATION_FAILED, malformed JSON). |
401 | Auth failure (API_KEY_MISSING, API_KEY_INVALID, API_KEY_REVOKED, REQUEST_SIGNATURE_INVALID). |
403 | Authenticated but not authorised (INSUFFICIENT_SCOPE, IP_NOT_ALLOWED). |
404 | Resource doesn’t exist (or doesn’t exist to you — ownership-checked routes return 404 not 403 to prevent enumeration). |
409 | Conflict (IDEMPOTENCY_KEY_CONFLICT, SPENDING_LIMIT_EXCEEDED, TRADE_NOT_AWAITING_CONFIRMATION, INSUFFICIENT_BALANCE, etc.). |
410 | Gone (a previously valid resource is permanently removed). |
422 | Semantically valid but rejected by domain rules (e.g. MARKET_NOT_TRADEABLE). |
429 | Rate limit exceeded. Honour Retry-After. |
500 | Server bug. Include requestId when reporting. |
502 | Upstream dependency error (RPC, DB). |
503 | Route temporarily disabled (ROUTE_DISABLED) or dependency unavailable. |
504 | Upstream timeout. |
Error code catalog
Everycode has a stable per-page documentation entry at https://docs.kash.bot/developer-docs/api-errors/<CODE> — see the Error catalogue for the full index. The type field on every error is exactly that URL — copy-paste it into a browser to read the page, or fetch it programmatically.
The CLI ships an offline copy of the full catalog. kash explain <CODE> works without a network round-trip:
| Code | When it fires |
|---|---|
API_KEY_MISSING | No X-API-Key header. |
API_KEY_INVALID | Key not recognised or HMAC mismatch. |
API_KEY_REVOKED | Valid format, but the key has been revoked. |
API_KEY_EXPIRED | Key is past its expires_at timestamp. |
INSUFFICIENT_SCOPE | Key lacks the scope this route requires. |
IP_NOT_ALLOWED | Source IP not in this key’s allowlist. |
RATE_LIMIT_EXCEEDED | Per-key quota exceeded. Honour Retry-After. The cap is tier-differentiated — see Rate Limits. |
SPENDING_LIMIT_EXCEEDED | Trade would exceed the key’s per-trade or daily cap. The extensions.cap field is per_trade or daily_volume. Caps are tier-differentiated — see Rate Limits for the matrix and upgrade path. |
VALIDATION_FAILED | Request body or query failed schema validation. |
IDEMPOTENCY_KEY_CONFLICT | Same Idempotency-Key reused with a different body. See Idempotency. |
MARKET_NOT_TRADEABLE | Market is FROZEN/RESOLVED, on an unsupported chain, or otherwise inactive. |
INSUFFICIENT_BALANCE | Smart account doesn’t have enough USDC for the trade. |
TRADE_NOT_AWAITING_CONFIRMATION | Confirm called on a trade that’s not in pending_confirmation. |
CONFIRMATION_TOKEN_INVALID | Confirmation token didn’t match. |
CONFIRMATION_TOKEN_USED | Confirmation token already redeemed (or by a concurrent confirm). |
CONFIRMATION_EXPIRED | Confirmation window passed; the trade auto-failed. |
RESOURCE_NOT_FOUND | Trade/market/event id doesn’t exist (or doesn’t belong to you). |
DEPENDENCY_UNAVAILABLE | Upstream (DB, chain RPC) is degraded. Treat like Retry-After. |
ROUTE_DISABLED | Ops kill switch is active for this route. |
WEBHOOK_REPLAY_LIMIT_REACHED | More than 5 manual redeliveries for the same event. |
WEBHOOK_SECRET_ROTATION_COOLDOWN | Webhook-secret rotation called within 60s of a prior successful rotation. Protects the rollback slot — see Secret Rotation. |
REQUEST_SIGNATURE_INVALID | Opt-in body-signing on POST /v1/trades failed verification. |
What’s NOT in errors
Defensive design choices to be aware of:- No stack traces. Internal stack frames are stripped before the response.
- No DB error strings. Postgres / RPC errors are sanitised to user-safe messages.
- No URLs with credentials. Defence-in-depth scrubbing in case anything slips into a log line.
- 404 instead of 403 for ownership. Trying to GET someone else’s trade returns
RESOURCE_NOT_FOUND, notFORBIDDEN. This prevents id-enumeration attacks (you can’t tell whether a UUID exists if it’s not yours). - Generic
DEPENDENCY_UNAVAILABLEwhen upstream fails. We deliberately hide which upstream — DB vs RPC vs Redis — to avoid leaking architecture detail to attackers. YourrequestIdlets us correlate to the precise root cause server-side.
Reporting bugs
Include therequestId when emailing [email protected] or filing an issue on the relevant public mirror (SDK · CLI · Protocol SDK (TS) · Protocol SDK (Python)). One id is enough — we can pull the full distributed trace, every event, and every retry attempt from it.
Next
Idempotency
Safely retry trade creation without producing duplicates.
Pagination
Cursor-based, never offset. How to walk a list endpoint.