Errors
Every error returned by the 4Cx API uses the same JSON envelope:
When
details.retryAfterSeconds is set, the response also includes a standard Retry-After header.
Programming against errors
- Check the HTTP status first.
- If
error.details.codeis present, branch on that (it is stable across releases). The throttle codes documented on Rate limits are the main consumers of this. - For everything else, the HTTP status + endpoint context is enough. Do not parse
error.message— those strings are not part of the contract and may change.
Common errors by status
400 — Bad request
Validation failed on the request body or query string. Common triggers:- Missing required field (e.g.
Username and password are requiredon/user/login). - Invalid
gameID(Invalid gameID: <id>on any endpoint that looks up a game). - Invalid
playerMode(must be"coins"or"cash"— see Switch player mode). - Order size below
MIN_ORDER_SIZEor above the configured maximum.
401 — Unauthorized
The token inAuthorization (or the auth cookie) is missing, expired, or doesn’t resolve to a user.
data.user.auth token. Remember: the API takes the raw token — no Bearer prefix.
403 — Forbidden
You are authenticated but not allowed to act on this resource. Two common shapes:- Resource ownership:
Not your order: <orderID>when you try to cancel or look up an order another user owns. - Account restrictions:
USER IS BANNED,Your account <username> has been closed, or a permission flag (e.g. admin-only endpoints). - Limits:
Order size exceeds maximum limit of 1000.00on place/edit.
404 — Not found
The path is valid but the resource doesn’t exist — e.g. you looked up anorderID or depositRequestId that was never created (or was deleted).
409 — Conflict
The request was well-formed and you’re authorized, but the state of the market changed between when you read it and when you tried to act on it. This is the most common error class for any trading client and the one most worth handling explicitly. Common triggers onPOST /session/v2/place:
"Order size exceeds quantity available, which is $X.XX"— the resting offer you tried to take was partially or fully consumed by another taker before your request landed."Odds have been edited"— the maker edited their order between your read and your take."Session is expired"/"Session is cancelled"— the order you targeted is no longer takeable."Game is past start time"/"Game has started"/"Game has been taken OTB or is graded"— the market closed (or moved to in-play) between your read and your write."You cannot fill your own order: <orderID>"— you are the maker of the order you tried to take. Only enforced in cash mode."Order size exceeds available credit"/"Exceeds max liability <N>"— your available credit / max liability changed (e.g. a concurrent order on the other side of your book).
- Catch the 409.
- Refresh the orderbook for the affected
gameID(and orderbook depth on the side you wanted). - Decide whether the new state still matches your strategy. If yes, place a new order against the current best offer; if no, abandon.
423 — Locked
AcancelAll-style operation is currently running for your account, so individual cancels are temporarily locked out. This has structured details and should not be retried like a normal rate limit. See Rate limits → CANCEL_ALL_IN_PROGRESS.
429 — Too many requests
You exceeded the per-second rate limit on a place or cancel endpoint, or the cancel pipeline is saturated. Two distinctdetails.code values (RATE_LIMITED, CANCEL_QUEUE_FULL) — full retry strategy on Rate limits.
