> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.defdex.io/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.defdex.io/_mcp/server.

# Python SDK

Install the [versioned Python client](/sdks-and-cli). Python 3.10+ is required;
there are no runtime dependencies. Load `DEFDEX_API_KEY` privately.

```python
from defdex import DefDexClient, DefDexError

api = DefDexClient()
try:
    page = api.list("programs", q="SBIR", limit=10)
    for record in page["data"]:
        print(record["attributes"]["id"], record["attributes"]["name"])
except DefDexError as error:
    print(error.status, error.request_id, error.retry_after)
```

## Methods

| Method                                                       | Result                    |
| ------------------------------------------------------------ | ------------------------- |
| `datasets()`                                                 | Runtime catalog           |
| `list(dataset, limit=25, cursor=None, q=None, filters=None)` | Generic record page       |
| `get(dataset, record_id)`                                    | Generic detail            |
| `awards(limit=25, cursor=None, q=None, company_id=None)`     | Convenience award page    |
| `award(award_id)`                                            | Convenience award detail  |
| `usage()`                                                    | Account activity summary  |
| `submit_correction(proposal, idempotency_key)`               | Proposal receipt directly |
| `corrections(limit=25, cursor=None)`                         | Own proposal page         |
| `correction(correction_id)`                                  | Own proposal directly     |

Results are dictionaries with the HTTP response shape. List/detail data reads include
`build_id`; correction responses use their own receipt/page shapes. Filters are encoded
as JSON and IDs as path segments automatically.

## Preserve money

```python
from decimal import Decimal

page = api.awards(limit=10)
for award in page["data"]:
    value = award["obligated_usd"]
    obligation = None if value is None else Decimal(value)
    print(award["id"], obligation)
```

Do not convert decimal strings to `float`. Preserve nulls and negative obligations.
Ceilings are not spending.

## Configuration and failures

`DefDexClient(api_key=None, base_url="https://app.defdex.io/api/v1", timeout=30)`
uses a 30-second timeout by default. `DefDexError` exposes `status`, `request_id`
and `retry_after`; transport failures use status 0. Requests identify as
`DefDexPythonSDK/0.1.1`.

The client does not automatically retry or follow redirects. Use [bounded retries](/errors)
and preserve correction idempotency keys across uncertain results. Use HTTPS for remote
base-URL overrides; loopback HTTP is supported for local testing.