> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tolt.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Python SDK

> tolt: sync and async Python clients for the Tolt API, with typed models and errors.

The `tolt` package wraps every v2 endpoint in a typed method. Run it on your server: it needs your secret API key.

![](https://mintcdn.com/tolt-29/IdZ6_r2VYMOh5a6x/images/logos/python.svg?fit=max\&auto=format\&n=IdZ6_r2VYMOh5a6x\&q=85\&s=550ea9e1f75b7aec3b2221ef6ccc106c) client.partners.list()
GET /v2/partners
&#x20;Tolt

Returned

**response**200successtruedata\[part\_8fKq…, …]has\_moretruenext\_cursor"cur\_WyIy…"

Raised on 4xx, 5xx

**ApiError**NotFoundErrorstatus\_code404body.code"not\_found"body.doc\_url…/errors#not\_found

## Install

```bash pip theme={"system"}
pip install tolt
```

```bash uv theme={"system"}
uv add tolt
```

```bash poetry theme={"system"}
poetry add tolt
```

Get an API key in **Dashboard → Settings → Integrations → Tolt API**.

## Initialize

```python Sync theme={"system"}
import os
from tolt import ToltApi

client = ToltApi(token=os.environ["TOLT_API_KEY"])
```

```python Async theme={"system"}
import asyncio
import os
from tolt import AsyncToltApi

client = AsyncToltApi(token=os.environ["TOLT_API_KEY"])

async def main() -> None:
    async for partner in await client.partners.list():
        print(partner.id)

asyncio.run(main())
```

Methods take keyword arguments and return typed models. Single-item calls return the API envelope, so read `.data`. `list` returns a pager you can iterate.

## Common calls

### List partners

Iterating walks every page. The SDK passes each `next_cursor` back as `starting_after` for you.

```python theme={"system"}
for partner in client.partners.list():
    print(partner.id, partner.email)
```

`pager.items` holds one page's rows, and `pager.response` the envelope with `has_more`. Iteration only moves forward: with `ending_before`, read `pager.items` and don't iterate.

### Create a customer

Bind a signup to a partner. `customer_id` is your id for the customer, ideally the one your billing system uses (a Stripe customer id, say), since billing integrations match payments on it. Send it or `email`. A `partner_id` (or `link_id`) is required; add the `click_id` tolt.js captured to keep the click's link.

```python theme={"system"}
customer = client.customers.create(
    email="jane@example.com",
    customer_id="user_4821",
    partner_id="part_8fKq2LmZx7RtYw3nVbHc5dPj",
    click_id="clk_3hTq9WmZr2LxVb7nKcPd5sYe",
).data
# customer.id is the Tolt id: cus_...
```

### Record a payment

Amounts are integers in minor units (`4900` = \$49.00). Responses return money fields as strings (`"4900"`) because they are stored as 64-bit integers. `customer_id` here is the Tolt `cus_` id.

```python theme={"system"}
transaction = client.transactions.create(
    customer_id=customer.id,
    amount=4900,
    billing_type="subscription",
    interval="month",
    charge_id="ch_3PqR8sLmZx7RtYw3",
).data
```

### Refund it

```python theme={"system"}
client.transactions.refund(id=transaction.id)
```

### Mint an embed token

For the [partner dashboard embed](/sdks/embed). Pass a `partner_id`, or `partner={"email": ..., "program_id": ...}`.

```python theme={"system"}
token = client.embed_tokens.create(
    partner_id="part_8fKq2LmZx7RtYw3nVbHc5dPj"
).data
# token.token, token.expires_at
```

## Errors

Non-2xx responses raise. Known statuses get their own class; all of them extend `ApiError`.

```python theme={"system"}
import httpx
from tolt import NotFoundError
from tolt.core.api_error import ApiError

try:
    client.partners.get(id="part_8fKq2LmZx7RtYw3nVbHc5dPj")
except NotFoundError as e:
    print(e.body.code)  # "not_found"
except ApiError as e:
    print(e.status_code, e.body)
except httpx.TimeoutException:
    ...  # no response within the timeout
```

Timeouts raise httpx's `TimeoutException`, not `ApiError`. Read `e.status_code` and `e.body` rather than `str(e)`, which starts with the response headers.

| Class | Status |
| - | - |
| `BadRequestError` | 400 (`validation_error`, `invalid_reference`, ...) |
| `UnauthorizedError` | 401 |
| `NotFoundError` | 404 |
| `ConflictError` | 409 (`already_exists`, `transaction_refunded`, ...) |
| `TooManyRequestsError` | 429 |
| `ApiError` | Base class, and any other status |

The specific classes import from `tolt`. `e.body` is the [error object](/api-reference/errors) (`ErrorResponse`) with `message`, `code`, `doc_url` and `errors`.

## Retries and timeouts

Requests that fail with 408, 409, 429, 5xx or a connection error are retried with exponential backoff, honoring `Retry-After`. Set defaults on the client, or override per call with `request_options`.

```python theme={"system"}
client = ToltApi(
    token=os.environ["TOLT_API_KEY"], max_retries=3, timeout=30
)

client.partners.get(
    id="part_8fKq2LmZx7RtYw3nVbHc5dPj",
    request_options={"timeout": 5},
)
```

> [!WARNING]
>
> Calls that create something (every `create`, and `transactions.rerun_flows`) are never retried, because a retry after a server error could create it twice. Before retrying one yourself, check whether it took effect. `transactions.create` with a `charge_id` is safe to retry: a duplicate raises `ConflictError` with code `already_exists`, so treat that as done.

| Client option | Default | |
| - | - | - |
| `token` | required | Your API key (or a callable returning it) |
| `max_retries` | `2` | Retries on 408, 409, 429, 5xx and connection errors, except for creates |
| `timeout` | `60` | Seconds per request |
| `headers` | | Extra headers on every request |
| `base_url` | `https://platform.tolt.com` | API host |
| `httpx_client` | | Your own `httpx.Client` (`httpx.AsyncClient` for async) |

`request_options` keys: `max_retries`, `timeout`, `additional_headers`, `additional_query_parameters`, `additional_body_parameters`.

### Response headers

Prefix a call with `with_raw_response` to read headers such as `X-RateLimit-Remaining`.

```python theme={"system"}
response = client.partners.with_raw_response.get(id="part_8fKq2LmZx7RtYw3nVbHc5dPj")
print(response.headers.get("x-ratelimit-remaining"), response.data)
```

## Resources

| Resource | Methods |
| - | - |
| `partners` | `list` `get` `create` `update` `approve` `reject` `suspend` `bulk_approve` `bulk_reject` |
| `customers` | `list` `get` `create` `update` `delete` |
| `transactions` | `list` `get` `create` `update` `delete` `refund` `rerun_flows` |
| `commissions` | `list` `get` `create` `update` `delete` `approve` `decline` `bulk_approve` `bulk_decline` |
| `links` | `list` `get` `get_by_param_value` `create` `update` `delete` |
| `clicks` | `list` `get` `create` |
| `promotion_codes` | `list` `get` `create` `update` `delete` |
| `programs` `groups` `flows` | `list` `get` |
| `reports` | `overview` `partners` `links` `timeseries` `customers` |
| `embed_tokens` | `create` |

Each method maps to one endpoint in the [API reference](/api-reference/introduction).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.