Errors
Every error is JSON with an `error` message. Status codes tell you whose fault it is.
All errors return a JSON body with a human-readable error field (auth and rate-limit errors also include a docs link). Errors are CORS-open too, so browser clients can always read them.
{ "error": "no range for stack=100 spot=\"UTG_65%_HJ_Call\"" }
Status codes
| Status | When |
|---|---|
400 | Malformed request — missing stack/spot/history, non-numeric stack, or an action path that doesn't parse. |
401 | Missing or invalid API key, or the key's subscription is not active. Carries WWW-Authenticate: Bearer. |
403 | Postflop API only — signed in but no Studio entitlement. |
404 | Well-formed but not in the dataset: unknown stack depth, a spot the tree doesn't contain, or an unknown replay-pack id. |
429 | Rate limit exceeded — see rate limits. Retry after Retry-After seconds. |
502 | The upstream range store is unavailable. Transient; retry with backoff. |
503 | The API is not configured/enabled on the server side (e.g. a pack still being generated). |
400 vs 404
The distinction is deliberate and useful when generating paths programmatically:
400means your path is grammatically wrong — fix the request. Example:stack=abc, or a spot whose second-to-last token isn't a known position.404means the path is valid but unsolved — the spot simply isn't in the dataset. Example: a raise size the tree doesn't offer at that node.
Rather than probing with 404s, enumerate what exists: /spots lists every valid decision node for a stack, and /node returns the exact action tokens available at each one.