Exception Hierarchy
All SDK exceptions inherit fromRulebookError. HTTP errors are further organized by
status code so you can catch exactly what you need.
RulebookError
└── APIError
├── APIConnectionError
│ └── APITimeoutError
└── APIStatusError
├── BadRequestError (400)
├── AuthenticationError (401)
├── PermissionDeniedError (403)
├── NotFoundError (404)
├── UnprocessableEntityError (422)
├── RateLimitError (429)
└── InternalServerError (5xx)
Basic Error Handling
from rulebook import Rulebook, NotFoundError, AuthenticationError, APIConnectionError
client = Rulebook(api_key="your-key")
try:
detail = client.exchanges.retrieve("INVALID")
except NotFoundError as e:
print(f"Exchange not found: {e.message}")
print(f"Status code: {e.status_code}") # 404
except AuthenticationError:
print("Invalid API key — check your credentials")
except APIConnectionError:
print("Network error — check your connection")
Exception Attributes
EveryAPIStatusError (and its subclasses) carries the full context of the failed request:
from rulebook import Rulebook, APIStatusError
client = Rulebook(api_key="your-key")
try:
client.exchanges.retrieve("INVALID")
except APIStatusError as e:
print(e.message) # "Exchange not found"
print(e.status_code) # 404
print(e.body) # {"success": false, "error": "Not Found", ...}
print(e.response) # httpx.Response object
print(e.request) # httpx.Request object
| Attribute | Type | Description |
|---|---|---|
message | str | Human-readable error description |
status_code | int | HTTP status code |
body | object | None | Parsed JSON response body |
response | httpx.Response | Raw HTTP response |
request | httpx.Request | The request that failed |
Catching All API Errors
Use the base classes to handle broad categories:from rulebook import Rulebook, APIStatusError, APIConnectionError, RulebookError
client = Rulebook(api_key="your-key")
try:
exchanges = client.exchanges.list()
except APIConnectionError:
# Network-level failure (DNS, timeout, socket)
print("Could not reach the API")
except APIStatusError as e:
# Any HTTP 4xx/5xx error
print(f"API error {e.status_code}: {e.message}")
except RulebookError as e:
# SDK-level error (e.g., missing API key)
print(f"SDK error: {e}")
Input Validation
The SDK validates required parameters before making HTTP calls. This raises a standardValueError, not an SDK exception:
try:
client.exchanges.retrieve("") # empty string
except ValueError as e:
print(e) # "Expected a non-empty value for `exchange_name` but received ''"
Fee Schedule Results Error Handling
from rulebook import Rulebook, NotFoundError, PermissionDeniedError, AuthenticationError
client = Rulebook(api_key="your-key")
# Retrieve a single result
try:
result = client.fee_schedule_results.retrieve("a1b2c3d4-e5f6-7890-abcd-ef1234567890")
print(f"{result.exchange_name}: {result.fee_amount}")
except NotFoundError:
print("Fee schedule result not found")
except PermissionDeniedError:
print("You do not have access to this exchange's data")
# Get results by version
try:
page = client.fee_schedule_results.get_results_by_version("f7e8d9c0-...")
print(f"{page.total_records} results in this version")
except NotFoundError:
print("Version not found")
except PermissionDeniedError:
print("You do not have access to this version's exchange")
Common Error Scenarios
| Scenario | Exception | How to fix |
|---|---|---|
| Missing or invalid API key | AuthenticationError | Check your api_key or RULEBOOK_API_KEY env var |
| Exchange doesn’t exist | NotFoundError | Verify the exchange name with exchanges.list() |
| Fee schedule result not found | NotFoundError | Verify the ID with fee_schedule_results.list() |
| Version not found | NotFoundError | Check version_id from a fee schedule result |
| No access to exchange | PermissionDeniedError | Contact sales to expand your access |
| Too many requests | RateLimitError | Back off and retry, or contact sales for limits |
| Server error | InternalServerError | Retry — SDK retries automatically by default |
| Network failure | APIConnectionError | Check your internet connection |
| Request timeout | APITimeoutError | Increase timeout via client.with_options(timeout=60) |

