Installation

pip install rulebooksdk
Requires Python 3.11+. The SDK depends on httpx and pydantic.

Initialize the Client

from rulebook import Rulebook

client = Rulebook(api_key="your-api-key")
Or set the RULEBOOK_API_KEY environment variable and omit the parameter:
export RULEBOOK_API_KEY="your-api-key"
from rulebook import Rulebook

client = Rulebook()  # reads from RULEBOOK_API_KEY
You can also override the base URL via the RULEBOOK_BASE_URL environment variable:
export RULEBOOK_BASE_URL="https://your-custom-endpoint/api/v1"

List Exchanges

exchanges = client.exchanges.list()

for ex in exchanges:
    print(f"{ex.name} ({ex.display_name})")
    print(f"  Fee types: {ex.fee_types}")
    print(f"  Records: {ex.record_count}")
Response type: list[Exchange]
FieldTypeDescription
namestrExchange identifier (e.g., “NYSE”)
display_namestrHuman-readable name
fee_typeslist[str]Available fee types
record_countintTotal fee schedule records

Get Exchange Details

detail = client.exchanges.retrieve("NYSE")

print(f"Date range: {detail.date_range.earliest} to {detail.date_range.latest}")
print(f"Actions: {detail.actions}")
print(f"Participants: {detail.participants}")
print(f"Fee categories: {detail.fee_categories}")
Response type: ExchangeDetail

List Fee Schedule Results

page = client.fee_schedule_results.list(
    supplier_name=["CBOE"],
    fee_type=["Option"],
    fee_participant=["Market Maker"],
    latest_only=True,
    page_size=10,
)

print(f"Total results: {page.total_records}")
for result in page.data:
    print(f"  {result.fee_action}: {result.fee_amount} ({result.fee_symbol_type})")
Response type: PaginatedResponse[FeeScheduleResult]
FieldTypeDescription
datalist[FeeScheduleResult]Array of result objects
total_recordsintTotal records matching the query
page_sizeintRecords per page
total_pagesintTotal number of pages
current_pageintCurrent page number (0-indexed)
query_time`floatNone`Query execution time in seconds
Filter parameters:
ParameterTypeDescription
supplier_namelist[str]Filter by exchange name(s)
fee_typelist[str]Filter by fee type(s)
fee_categorylist[str]Filter by fee category(s)
fee_actionlist[str]Filter by trading action(s)
fee_participantlist[str]Filter by participant type(s)
fee_symbol_classificationlist[str]Filter by symbol classification(s)
fee_symbol_typelist[str]Filter by symbol type(s)
fee_trade_typelist[str]Filter by trade type(s)
start_datestrFilter by scraped date (YYYY-MM-DD)
end_datestrFilter by scraped date (YYYY-MM-DD)
latest_onlyboolOnly latest version per exchange
order_bystrSort field (default: created_on)
order_dirstrSort direction: asc or desc
page_sizeintRecords per page (1–100)
page_numberintPage number (0-indexed)

Get a Single Fee Schedule Result

result = client.fee_schedule_results.retrieve("a1b2c3d4-e5f6-7890-abcd-ef1234567890")

print(f"{result.supplier_name}{result.fee_type}{result.fee_category}")
print(f"  Action: {result.fee_action}")
print(f"  Amount: {result.fee_amount}")
print(f"  Participant: {result.fee_participant}")
Response type: FeeScheduleResult

Get Available Filters

Discover valid filter values before querying results:
filters = client.fee_schedule_results.get_filters()

print(f"Exchanges: {filters.supplier_names}")
print(f"Fee types: {filters.fee_types}")
print(f"Categories: {filters.fee_categories}")
print(f"Actions: {filters.fee_actions}")
print(f"Participants: {filters.fee_participants}")
Response type: FeeScheduleResultFilters
FieldTypeDescription
supplier_nameslist[str]Available exchange names
fee_typeslist[str]Available fee types
fee_categorieslist[str]Available fee categories
fee_actionslist[str]Available trading actions
fee_participantslist[str]Available participant types
fee_symbol_classificationslist[str]Available symbol classifications
fee_symbol_typeslist[str]Available symbol types
fee_trade_typeslist[str]Available trade types

Get Results by Version

Retrieve all fee schedule results from a specific extraction version:
page = client.fee_schedule_results.get_results_by_version(
    "f7e8d9c0-b1a2-3456-7890-abcdef123456",
    page_size=50,
)

print(f"Version has {page.total_records} results ({page.total_pages} pages)")
for result in page.data:
    print(f"  {result.fee_action}: {result.fee_amount}")

Pagination

Fee schedule results are paginated. Use page_number and page_size to iterate:
page_number = 0
total_fetched = 0

while True:
    page = client.fee_schedule_results.list(
        latest_only=True,
        page_size=50,
        page_number=page_number,
    )
    total_fetched += len(page.data)
    print(f"Page {page_number + 1}/{page.total_pages}: {len(page.data)} results")

    if page_number >= page.total_pages - 1:
        break
    page_number += 1

print(f"Fetched {total_fetched} of {page.total_records} total results")

Async Client

import asyncio
from rulebook import AsyncRulebook

async def main():
    async with AsyncRulebook(api_key="your-key") as client:
        exchanges = await client.exchanges.list()
        detail = await client.exchanges.retrieve("NYSE")

        page = await client.fee_schedule_results.list(
            supplier_name=["CBOE"],
            latest_only=True,
        )
        filters = await client.fee_schedule_results.get_filters()

asyncio.run(main())
The async client has an identical API surface — every method is await-able.

Context Manager

Both clients support context managers for automatic cleanup:
with Rulebook(api_key="your-key") as client:
    exchanges = client.exchanges.list()
# Connection pool is cleaned up here

Next Steps