# Python SDK v0.2.0 — Release Notes

**Release Date:** 2026-03-10
**Package:** `rulebook-sdk` v0.2.0
**Compatibility:** Python 3.11+ (tested on 3.11, 3.12, 3.13)

---

## Summary

This release adds support for fee schedule footnotes, definitions, and source document metadata through new `include_footnotes`, `include_definitions`, and `include_source` query parameters across all fee schedule result endpoints. It also includes breaking changes to align the SDK's data model with the API response schema — notably renaming `FeeScheduleResult.id` to `record_id` and removing the `fee_reference` field.

## API Coverage

| Endpoint | SDK Method | Status | Response Time |
|----------|-----------|--------|---------------|
| `GET /exchanges` | `client.exchanges.list()` | PASS | 1387ms |
| `GET /exchanges/{name}` | `client.exchanges.retrieve(name)` | PASS | 602ms |
| `GET /fee-schedule-results` | `client.fee_schedule_results.list(...)` | PASS | 749ms |
| `GET /fee-schedule-results/{id}` | `client.fee_schedule_results.retrieve(id)` | PASS | 686ms |
| `GET /fee-schedule-results/filters` | `client.fee_schedule_results.get_filters()` | PASS | 327ms |
| `GET /fee-schedule-results/versions/{id}` | `client.fee_schedule_results.get_results_by_version(id)` | PASS | 286ms |
| Raw response access | `client.with_raw_response.exchanges.list()` | PASS | — |
| Error handling (404) | `client.exchanges.retrieve("NONEXISTENT...")` | PASS | NotFoundError raised |

**Coverage: 6/6 endpoints verified live against dev API (`https://dev-be-stock-rule-book.codeaza.org/api/v1`)**

### Live Verification Details

| Check | Result |
|-------|--------|
| `exchanges.list()` | 11 exchanges returned (sample: `fee_miax_options`) |
| `exchanges.retrieve()` | `fee_miax_options` — 1 fee type, 1748 records |
| `fee_schedule_results.get_filters()` | 8 filter keys: `exchange_names`, `fee_types`, `fee_categories`, `fee_actions`, `fee_participants`, `fee_symbol_classifications`, `fee_symbol_types`, `fee_trade_types` |
| `fee_schedule_results.list()` | 3635 total records, 5 returned (page_size=5, latest_only=True) |
| `fee_schedule_results.retrieve()` | Record `9ea03542-...` — `has_source=True`, `has_relationships=True` |
| `fee_schedule_results.get_results_by_version()` | Version `ddce0c67-...` — 542 total records, 3 returned |
| `with_raw_response` | status_code=200, headers present, parseable=True |
| Error handling | `NotFoundError` correctly raised for nonexistent exchange |

## What's New

### New Query Parameters
- **`include_footnotes`** — Include resolved footnotes in each result's `relationships` field
- **`include_definitions`** — Include resolved definitions in each result's `relationships` field
- **`include_source`** — Include `source_document`, `source_link`, and `page_number` fields

These parameters are available on:
- `fee_schedule_results.list()`
- `fee_schedule_results.retrieve()`
- `fee_schedule_results.get_results_by_version()`
- All corresponding `with_raw_response` and async variants

### New Response Models
- **`Footnote`** — `text: str` — A resolved footnote from extraction data
- **`Definition`** — `term: str`, `text: str` — A resolved definition from extraction data
- **`Relationships`** — `footnotes: list[Footnote]`, `definitions: list[Definition]` — Container for resolved relationships

### New Fields on `FeeScheduleResult`
- `source_document: str | None` — Source document name (when `include_source=True`)
- `source_link: str | None` — Link to the source document (when `include_source=True`)
- `page_number: int | None` — Page number in source document (when `include_source=True`)
- `relationships: Relationships | None` — Resolved footnotes and definitions

### New Parameter on `get_filters()`
- **`exchange_name: list[str]`** — Narrow filter values to specific exchanges

## Breaking Changes

- **`FeeScheduleResult.id` renamed to `FeeScheduleResult.record_id`** — Aligns with the API response schema. Update all code referencing `.id` to use `.record_id`.
- **Removed `FeeScheduleResult.fee_reference`** — Field does not exist in the API response model. Remove any references to `.fee_reference`.
- **Removed `FeeScheduleResult.created_on`** — Field removed to align with API. Use `scraped_time` for timestamp information.
- **API response envelope handling updated** — The SDK now properly flattens the `meta` envelope from paginated responses, mapping `meta.record_count` to `total_records` and passing through `meta.query_time_ms` (milliseconds) directly.

## Bug Fixes

- **Preserved exception context in error handling** — Exception chains now properly use `raise ... from` to preserve the original traceback context
- **Improved error handling and meta field flattening** — More robust Pydantic validators for the API response envelope

## Docs Alignment

| Check | Status |
|-------|--------|
| SDK methods match all API endpoints | PASS |
| Parameter names/types match across SDK, spec, and docs | PASS |
| Response models match API schema | PASS |
| Error codes match exception hierarchy | PASS |
| `record_count` → `total_records` mapping documented | PASS |
| `query_time_ms` passed through as milliseconds | PASS |
| Quickstart examples verified against current SDK API | PASS |
| Advanced usage docs verified | PASS |
| Error handling docs verified | PASS |

**Alignment verification date:** 2026-03-09 (see `SDK_ALIGNMENT_VERIFICATION.md`)

## Test Results

- **Total:** 164 tests
- **Passed:** 164
- **Failed:** 0
- **Skipped:** 0
- **Duration:** 61s

All unit tests (mocked HTTP) and integration tests (live dev API) pass. Integration tests dynamically discover valid exchange names, result IDs, and version IDs from the API — no hardcoded test data.

## Dependencies

| Package | Version |
|---------|---------|
| `httpx` | >=0.25.0 |
| `pydantic` | >=2.0.0 |
| `anyio` | >=4.0.0 |

### Dev Dependencies

| Package | Version |
|---------|---------|
| `pytest` | >=7.0 |
| `pytest-httpx` | >=0.30.0 |
| `pytest-asyncio` | >=0.23.0 |
| `ruff` | >=0.4.0 |
| `vcrpy` | >=8.1.1 |

## Known Issues

- **`created_on` field removed** — The SDK spec still lists `created_on` as an optional field on `FeeScheduleResult`, but it has been removed from the SDK implementation per the latest commit. The spec should be updated to reflect this.
- **`filters.exchange_names` confirmed** — Live verification confirmed the API returns `exchange_names` (not `supplier_names`) in the filters response, matching the quickstart docs.

## Upgrade Guide

### From v0.1.x to v0.2.0

1. **Update the package:**
   ```bash
   pip install --upgrade rulebook-sdk>=0.2.0
   ```

2. **Rename `id` to `record_id`:**
   ```python
   # Before (v0.1.x)
   result = client.fee_schedule_results.retrieve("some-uuid")
   print(result.id)

   # After (v0.2.0)
   result = client.fee_schedule_results.retrieve("some-uuid")
   print(result.record_id)
   ```

3. **Remove `fee_reference` usage:**
   ```python
   # Before (v0.1.x)
   print(result.fee_reference)  # AttributeError in v0.2.0

   # After (v0.2.0) — field removed, no replacement
   ```

4. **Remove `created_on` usage:**
   ```python
   # Before (v0.1.x)
   print(result.created_on)

   # After (v0.2.0) — use scraped_time instead
   print(result.scraped_time)
   ```

5. **Use new features (optional):**
   ```python
   # Include source document info
   result = client.fee_schedule_results.retrieve(
       "some-uuid",
       include_source=True,
   )
   print(result.source_document, result.source_link, result.page_number)

   # Include footnotes and definitions
   result = client.fee_schedule_results.retrieve(
       "some-uuid",
       include_footnotes=True,
       include_definitions=True,
   )
   if result.relationships:
       for fn in result.relationships.footnotes:
           print(fn.text)
       for defn in result.relationships.definitions:
           print(f"{defn.term}: {defn.text}")

   # Narrow filters to specific exchanges
   filters = client.fee_schedule_results.get_filters(
       exchange_name=["CBOE", "NYSE"]
   )
   ```

## Commit History (v0.1.x → v0.2.0)

| Hash | Message |
|------|---------|
| `16681f6` | refactor(python-sdk): remove created_on field from FeeScheduleResult |
| `cfb0924` | fix(python-sdk): preserve exception context in error handling |
| `dd451bd` | test(python-sdk): update mock responses to match new API envelope format |
| `953fa6f` | refactor(python-sdk): improve error handling and meta field flattening |
| `5318b45` | build(python-sdk): bump version to 0.2.0 |
| `87ca977` | test(python-sdk): add comprehensive tests for new SDK features |
| `418c2e5` | refactor(python-sdk): rename id to record_id in FeeScheduleResult model |
| `32eb617` | feat(python-sdk): add query parameters for footnotes, definitions, and source fields |
| `dd0708e` | feat(python-sdk): export footnote, definition, and relationships types |
| `c874dc7` | chore(sdks): bump Python SDK version to 0.1.3 and update API base URL |
| `3152626` | docs(sdks): fix package name and update SDK installation docs |
| `804f701` | docs(sdk): update Python SDK documentation with fee schedule examples |
| `3395b92` | fix(sdk): rename supplier_name to exchange_name to align with API |
| `91ec8f1` | feat(sdk-python): add fee_schedule_results resource to Python SDK |
| `d179150` | feat(sdk-python): add Python SDK with exchanges resource |
