Skip to content

Errors

Every error is an RFC 9457 problem document, served as application/problem+json with a real HTTP status code:

{
"type": "https://docs.haasapi.com/errors/exchange_not_found",
"title": "Exchange not found",
"status": 404,
"detail": "Exchange 'NOPE' is not supported.",
"code": "exchange_not_found",
"instance": "6f1b2c3d4e5f60718293a4b5c6d7e8f9"
}

code is the stable, machine-readable slug - the field your error handling should switch on. detail is for humans and may be reworded; code values never change meaning.

r = requests.get(url, headers=auth)
if not r.ok:
problem = r.json()
if problem["code"] == "invalid_cursor":
cursor = None # restart the walk
elif problem["code"] == "temporarily_unavailable":
retry_later()
else:
raise ApiError(problem["title"], problem["detail"])
Status code What to do
400 invalid_request Fix the parameter named in detail
400 invalid_cursor Restart pagination from the first page
401 unauthorized / invalid_api_key Check the key - see Authentication
404 not_found The path doesn’t exist
405 method_not_allowed Wrong HTTP method for this path
503 temporarily_unavailable Retry with the same request. Never discard your key on a 503
504 upstream_timeout Retry; the backend took too long

Endpoint-specific codes (like exchange_not_found) are listed on each endpoint in the reference.

Every response carries an X-Request-Id header, and error bodies repeat it as instance. Quote that one identifier when contacting support and we can find your exact request.