Errors
Errors return a JSON body with a stable numeric code and a human readable msg.
{"code": -1022, "msg": "signature mismatch"}
Every error belongs to one of four ranges, and the range tells the client what to do.
POST /order answers 202 once the order is on its way. Any other status means nothing
was placed, and since the clientOrderId is spent either way, a retry needs a new one.
A 202 can still carry an error object holding -5004, which means the submission was
sent but not confirmed, so the order stands and GET /order says what became of it.
An order that reaches the chain and then fails records the reason on itself, so
-2024, -2023 and -1000 can appear on GET /order after a 202. A client that
places orders should read order.error.code there as well as the HTTP status.
{"orderId": "0x...", "status": "REJECTED", "error": {"code": -2024, "msg": "transaction reverted"}}
Request errors, -1xxx
The request itself is wrong, so it has to be fixed before it is sent again. A retry of the same request fails the same way.
| Code | Meaning |
|---|---|
| -1000 | Internal error. |
| -1021 | Timestamp outside the recv window. Synchronize against GET /time. |
| -1022 | Invalid key, signature, or authentication headers. |
| -1023 | Session missing or invalid on a key management endpoint. |
| -1099 | Unknown API version. |
| -1102 | Missing or malformed field. The message names the field. |
| -1121 | Unknown contractId. |
Rate limits, -1003
Too many requests were sent. Unlike the rest of -1xxx, this one is retryable.
| Status | Meaning |
|---|---|
429 |
This wallet's quota is spent, or this IP address has sent too much. |
503 |
The API is shedding load, which is not a quota problem. |
Wait Retry-After seconds, then retry. If the header is absent, back off and retry.
X-RateLimit-Limit and X-RateLimit-Remaining come back on every response from a
limited endpoint, so a client can watch the remaining count fall and ease off before
it hits zero.
What the limits are and what drains them is in Rate limits.
{"code": -1003, "msg": "rate limit exceeded, slow down and retry"}
State conflicts, -2xxx
The request is well formed but conflicts with the current state of the account or the market. The message states what stands in the way.
| Code | Meaning |
|---|---|
| -2019 | Betting on this market is closed. Sent with HTTP 503 rather than a 4xx, so branch on the code and not on the status, since retrying will not open the market. |
| -2022 | rfqId does not match a live quote, request a new one with POST /order/rfq. |
| -2023 | The broker refused to sign the order. |
| -2024 | The transaction reverted on chain. |
| -2025 | Unknown order. No order matches the orderId or clientOrderId on GET /order. |
| -2026 | The request is understood but this API cannot serve it yet. |
| -2027 | The rfqId was already used by an order, a quote executes once. Look up the order named in the message with GET /order to see what became of it. It may have failed, and the quote is spent either way, so request a new quote to trade again rather than retrying this one. |
| -2028 | This clientOrderId is already being placed, retry the same request in a moment. |
| -2029 | Nothing is held for that outcome to be sold. |
| -2030 | The opposite outcome is held. Close that bet before betting this one. |
| -2031 | The rfqId expired before it was used, request a new quote with POST /order/rfq. |
Signing, -4xxx
| Code | Meaning |
|---|---|
| -4002 | On an order, this key can no longer sign for the wallet because the grant was removed, so create a new API key and retrying will not help. |
Upstream failures, -5xxx
Something behind the API was unavailable. The same request may succeed later.
| Code | Meaning |
|---|---|
| -5001 | Chain state or position history could not be read. |
| -5002 | The broker service was unavailable. |
| -5003 | The signer was unavailable. If it keeps failing, check for a -4002 on the order, which means the grant is gone rather than the service being down. |
| -5004 | The chain was congested and the transaction could not be placed. |
Handling errors in code
try {
await signedPost("/order", body);
} catch (err) {
const { code, msg } = err.response.data;
console.error("rejected:", code, msg);
}
try:
signedPost("/order", body)
except requests.HTTPError as err:
e = err.response.json()
print("rejected:", e["code"], e["msg"])
// call() surfaces API errors as ordinary Go errors carrying code and msg.
if err := signedPost("/order", body, &order); err != nil {
fmt.Println("rejected:", err)
}
Versioning
Clients may pin a major version with the X-Api-Version header. The current version is 0 and is echoed on every response. An unknown version returns -1099.
Limits
Signed request bodies are read up to 1 MB and anything beyond that is truncated rather than rejected, so an oversized body surfaces as a signature mismatch (-1022) or a JSON parse error. The recommended X-Recv-Window is 5000. Request rates are limited, and Rate limits describes how.