Skip to content

Errors & retries

What each endpoint can return is in the API reference, and request limits are in Rate limits. The SDK raises one exception per HTTP status, so you can catch the case you care about.

str(exc) is the API’s error message, and exc.status_code, exc.body, exc.method and exc.path describe the request.

Status Exception Typical cause
400 STXValidationException A bad parameter: status has invalid value: foo
401 STXAuthenticationException Bad key, bad signature, or a clock more than 30 s off
403 STXForbiddenException A read_only key on an order route
404 STXNotFoundException Unknown id, or one belonging to another account
422 STXRejectedException The exchange refused: closed market, insufficient funds, fractional quantity
429 STXRateLimitException Too many requests; retry_after in seconds when sent
5xx STXServerException Server failure

All of those derive from STXAPIException, which derives from STXException. Three more:

  • STXTransportException: no answer at all (connection refused, DNS, TLS, timeout)
  • STXConfigException: the client is misconfigured (unknown region, missing key, bad PEM)
  • STXChannelException: a WebSocket join or control event was refused; .reply holds the reason
from stx import STX, STXNotFoundException, STXRejectedException, STXValidationException
with STX() as client:
try:
client.order("00000000-0000-0000-0000-000000000000")
except STXNotFoundException as exc:
print("404:", exc)
try:
client.markets(status="not-a-status")
except STXValidationException as exc:
print(exc.status_code, exc)
market = next(
m
for m in client.iter_markets(status="open", trading=True, sort_by="event_start", sort_direction="desc")
if m.event_status == "scheduled"
)
try:
client.place_order(market.market_id, "buy", "limit", quantity="1")
except (STXRejectedException, STXValidationException) as exc:
print(exc.status_code, exc)
Failure GET, DELETE POST
429 retried, waiting Retry-After retried, waiting Retry-After
5xx retried not retried
Connection error or timeout retried not retried
400, 401, 403, 404, 422 not retried not retried

A POST that failed with a server error or a dropped connection may still have placed the order, so the SDK does not send it again. Use client_order_id and look the order up (see Avoid duplicate orders).

Every attempt is signed afresh. Backoff is exponential with jitter: 0.5 s, 1 s, 2 s, capped at 30 s, over 3 attempts by default. timeout is seconds per HTTP request (default 30).

from stx import NO_RETRY, STX, RetryPolicy
policy = RetryPolicy(max_attempts=5, initial_backoff=0.25, max_backoff=10)
with STX(retry=policy, timeout=10.0) as client:
print(len(client.markets(limit=1)))
with STX(retry=NO_RETRY) as client:
print(client.me().scope)

The socket reconnects on its own (see Reconnects). A channel that the server closes or errors is rejoined; a rejoin refused as unauthorized closes that channel instead of retrying forever. ReconnectPolicy(max_attempts=...) bounds reconnects; after the last one, run_forever() returns and every channel’s iterator ends.

The SDK logs to the stx logger (and stx.ws for the socket): requests at DEBUG, retries and reconnects at INFO and WARNING.

import logging
from stx import STX
logging.basicConfig(level=logging.INFO)
logging.getLogger("stx").setLevel(logging.DEBUG)
with STX() as client:
client.me()
v1.5.9Changelogllms.txtllms-full.txt