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

# Configuration

> create_client options, credential resolution, and the provider-client helpers.

`create_client(**options)` is a factory function that returns a client. All arguments are keyword-only; call it directly (it is not a class).

```python theme={null}
import os
from to11ai_sdk import create_client

client = create_client(
    api_key=os.environ["TO11_API_KEY"],
    project_id=os.environ["TO11_PROJECT_ID"],
    env="production",   # default label for render(); omit to read TO11_ENV
)
```

## Credential resolution

Each URL and credential resolves with a per-option precedence, so an app can construct the client from the environment alone:

* URLs (`base_url`, `gateway_url`) — option → environment variable → built-in default.
* `api_key`, `project_id`, `env` — option → environment variable (no default).
* `format` — option only.

Authenticate with `api_key` (a to11 API key). For control-plane calls the SDK sets `Authorization: Bearer <api_key>` for you and carries the project in the URL path. `project_id` and `env` are validated at construction — a blank `project_id`, or an `env` that isn't a lowercase-kebab slug, raises `ValueError`.

<Note>
  Keep credentials server-side. A to11 API key carries gateway access, so it must never ship to an end user's device. The same goes for a `provider_api_key` (BYOK). Use the SDK from a server, CLI, or backend job.
</Note>

## Options

| Argument           | Type                                  | Resolves from               | Default                                                                                                 |
| ------------------ | ------------------------------------- | --------------------------- | ------------------------------------------------------------------------------------------------------- |
| `api_key`          | `str \| None`                         | option → `TO11_API_KEY`     | — (required)                                                                                            |
| `base_url`         | `str \| None`                         | option → `TO11_API_URL`     | `https://api.to11.ai`                                                                                   |
| `gateway_url`      | `str \| None`                         | option → `TO11_GATEWAY_URL` | `https://gw.to11.ai` (host only, no `/v1`)                                                              |
| `project_id`       | `str \| None`                         | option → `TO11_PROJECT_ID`  | `None`                                                                                                  |
| `env`              | `str \| None`                         | option → `TO11_ENV`         | `None` (must match `^[a-z0-9-]{1,63}$`)                                                                 |
| `provider_api_key` | `str \| None`                         | option                      | `None` (BYOK; carried by `openai_options()` / `anthropic_options()` as the provider client's `api_key`) |
| `format`           | `"openai" \| "anthropic" \| None`     | option                      | `None` (omit for the neutral render result)                                                             |
| `on_unknown_role`  | `"drop" \| "warn" \| "error" \| None` | option                      | `"drop"`                                                                                                |
| `timeout_s`        | `float`                               | option                      | `30.0`                                                                                                  |
| `max_retries`      | `int`                                 | option                      | `3` (only idempotent GET / PUT / DELETE)                                                                |

## What the client exposes

* Resource namespaces `prompts` and `project_environments`.
* Read-only accessors for the resolved config: `client.base_url`, `client.gateway_url` (the gateway root, host only — no `/v1`), `client.api_key`, `client.project_id` (or `None` when unset), and `client.env` (or `None` when unset). `provider_api_key` (BYOK) is deliberately not exposed — it's a secret, not a config value to read.
* Provider-client options `openai_options()` and `anthropic_options()`, each returning `base_url`, `api_key`, and `default_headers` kwargs for a gateway-pointed client.
* The context factory `session()`, `conversation()`, and `turn()` — see [Sessions, conversations & turns](/docs/reference/python-sdk/sessions-and-turns).

The `project_id` set here is the default for **every** `prompts.*` method — `render()` and the lifecycle / version / label calls (`get`, `list`, `get_version`, `move_label`, …). Bind it once on the client and omit it per call; pass `project_id` on an individual call only to override.

## Provider-client options

`openai_options()` and `anthropic_options()` return spread-ready kwargs — `base_url`, `api_key`, and `default_headers` — for a provider client that targets the gateway. Both point at the same gateway; the `base_url` differs only by each SDK's own convention: `openai_options()` returns `f"{gateway_url}/v1"` (the OpenAI client puts `/v1` in `base_url`), while `anthropic_options()` returns the gateway root (the Anthropic client appends `/v1/messages` itself). `default_headers` carries the **static tenant auth** (`x-to11-authorization`, `x-to11-project-id`, and `x-to11-env` when set), so the client authenticates on its own; add `turn().headers(prompt)` per call for the request's trace id and prompt provenance.

```python theme={null}
from openai import OpenAI
from anthropic import Anthropic

openai = OpenAI(**client.openai_options())
anthropic = Anthropic(**client.anthropic_options())
```

`project_id` is required (it becomes `x-to11-project-id`); the helpers raise without one, or without an `api_key`.

### api\_key: managed vs BYOK

The returned `api_key` is the provider client's key:

* **Managed (default):** with no `provider_api_key`, `api_key` is the to11 key as a placeholder. The gateway ignores it and runs the call on the project's **configured provider credential**.
* **BYOK:** set `provider_api_key` on `create_client` (or pass `api_key` per call — see below) and it becomes the provider client's key, forwarded upstream. Whether the gateway uses it depends on the provider's passthrough mode; otherwise the stored credential still wins.

### Overrides and passthrough

Both helpers accept extra keyword arguments. The three managed fields are merged — `api_key` and `base_url` override; `default_headers` shallow-merges over the tenant-auth headers (caller wins) — and **any other keyword passes through untouched** to the provider client:

```python theme={null}
# BYOK for one client + a provider-SDK option, in one call. Pass a real
# provider key — an absent api_key falls back to the managed placeholder.
openai = OpenAI(**client.openai_options(api_key=OPENAI_API_KEY, timeout=60))

# add a header while keeping the tenant-auth headers
anthropic = Anthropic(**client.anthropic_options(default_headers={"x-trace": "1"}))
```

For a client the helpers don't cover (Vercel AI, LangChain), build the base URL from `client.gateway_url` (the gateway root) — an OpenAI-compatible client wants `f"{client.gateway_url}/v1"` — and attach `turn().headers()` (or `gateway_auth_headers`) yourself.
