> ## 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.

# API Reference

> Gateway endpoints, headers, request/response formats, and error codes.

The gateway is reachable at `https://gw.to11.ai/v1`. It exposes chat ingress endpoints, model discovery, embeddings, token counting, image generation, audio (transcription + TTS), and file management. Each chat endpoint accepts one SDK's wire format and forwards the request to the provider as written; the provider's response comes back in that same format. The gateway does not translate between formats, so the provider a request resolves to must speak the endpoint's format — see [Wire format must match the provider](#wire-format-must-match-the-provider).

<Info>
  Send `x-to11-authorization` and `x-to11-project-id` on **every** request (see [Authentication](#authentication)). For brevity, most examples on this page show only the upstream provider credential — `Authorization: Bearer` (or `x-api-key` for Anthropic-style requests) — and omit the two `x-to11-*` headers. Drop the provider credential entirely when it is managed in the dashboard.
</Info>

<Note>
  **This page is the gateway — the data plane.** It serves the model calls your application makes. The **control plane** is a separate API that manages what the gateway serves: prompts, versions, releases, providers and routing. It is reached through the [TypeScript](/docs/reference/typescript-sdk) and [Python](/docs/reference/python-sdk) SDKs, and its prompt endpoints — including the ones a [skill](/docs/skills/concepts#the-endpoints-behind-it) is created, imported, released and rendered through — are described alongside the feature they belong to.

  The distinction matters for one case in particular: a skill is delivered to a developer's machine and is **never resolvable for inference**, so no endpoint on this page will ever serve one.
</Note>

## Endpoints

| Endpoint | Method | Description |
| - | - | - |
| `/v1/responses` | POST | Canonical chat ingress (OpenAI / xAI / Anthropic shapes) |
| `/v1/chat/completions` | POST | OpenAI / xAI chat completions |
| `/v1/messages` | POST | Anthropic messages API |
| `/v1/models` | GET | List all configured models |
| `/v1/models/{model_id}` | GET | Get single model info |
| `/v1/embeddings` | POST | Embeddings (OpenAI-compatible providers only) |
| `/v1/messages/count_tokens` | POST | Token counting (Anthropic only) |
| `/v1/rerank` | POST | Rerank (Cohere and other rerank-capable providers) |
| `/v1/images/generations` | POST | Image generation (OpenAI-compatible providers only) |
| `/v1/audio/transcriptions` | POST | Audio transcription (OpenAI, multipart/form-data) |
| `/v1/audio/speech` | POST | Text-to-speech (OpenAI-compatible providers only) |
| `/v1/files` | POST | File upload (OpenAI-compatible providers only) |
| `/v1/files` | GET | List files |
| `/v1/files/{file_id}` | GET | Retrieve file metadata |
| `/v1/files/{file_id}/content` | GET | Download file content |
| `/v1/files/{file_id}` | DELETE | Delete a file |

The `model` field determines which upstream provider handles the request. It names the provider or route with a prefix separated by `::`:

* `<provider-slug>::model` — send to the connected provider with that routing identifier (e.g. `anthropic::claude-sonnet-4-6`)
* `route::name` — route to a named route
* `function::name` — route to a named function defined in your to11 project's routing

A model with no prefix (e.g. `gpt-4o`) must carry the `x-to11-provider-id` header naming the provider; without it the request is rejected with `400 Bad Request`. The examples on this page assume providers whose routing identifiers are `openai` and `anthropic`. See [Naming the provider in a request](/docs/deploy/concepts/models#naming-the-provider-in-a-request).

Provider-native passthrough routes also exist under `/v1/bedrock/*`, `/v1/vertex/*`, and `/v1/mistral/*` for advanced provider-specific APIs; those forward request bodies to the upstream verbatim and are gated to providers that support them.

## Headers

### Authentication

Gateway requests use two independent credentials:

1. **Your to11 platform key** authenticates the request to to11 and is sent in the `x-to11-authorization` header. The `x-to11-project-id` header selects which project's routing and provider configuration applies.

   ```
   x-to11-authorization: Bearer <your-to11-api-key>
   x-to11-project-id: <your-project-id>
   ```

2. **The upstream provider credential.** Either the project's provider credentials are configured in the dashboard (project → Gateway), in which case you send nothing extra; or you pass your own provider key (BYOK) in the standard `Authorization: Bearer <provider-key>` header (or `x-api-key` for Anthropic-style requests). The gateway forwards that key to the upstream provider.

<Note>
  The standard `Authorization` header carries the **upstream provider** key, not your to11 key. Put the to11 key in `x-to11-authorization`. When provider credentials are managed in the dashboard, you can omit `Authorization` entirely.
</Note>

### SDK detection

The gateway auto-detects the caller's SDK format from the endpoint. Override with:

```
x-genai-sdk: openai | anthropic | xai
```

### Provider selection

Name the provider with a `<provider-slug>::model` prefix in the `model` field:

```json theme={null}
{ "model": "anthropic::claude-sonnet-4-6", "messages": [...] }
```

Or, for a client that cannot change its model string, send the bare model with the provider's id in a header:

```
x-to11-provider-id: <provider id>
```

The header is read only when the model has no prefix. See [Pinning a provider by id](/docs/reference/providers#pinning-a-provider-by-id).

The `x-genai-provider` header (`openai | anthropic | xai`) names a provider type, not one of your connected providers, and does not select where a request goes. If it is present alongside a prefix that is also a provider type name and the two disagree, the request is rejected.

## Chat completions

### OpenAI format

<CodeGroup>
  ```bash curl theme={null}
  curl https://gw.to11.ai/v1/chat/completions \
    -H "x-to11-authorization: Bearer $TO11_API_KEY" \
    -H "x-to11-project-id: $TO11_PROJECT_ID" \
    -H "Authorization: Bearer $OPENAI_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "openai::gpt-4o",
      "messages": [{"role": "user", "content": "What is the capital of France?"}],
      "max_tokens": 256
    }'
  ```

  ```python Python theme={null}
  from openai import OpenAI

  client = OpenAI(base_url="https://gw.to11.ai/v1")
  response = client.chat.completions.create(
      model="openai::gpt-4o",
      messages=[{"role": "user", "content": "What is the capital of France?"}],
      max_tokens=256,
  )
  ```

  ```typescript TypeScript theme={null}
  import OpenAI from "openai";

  const client = new OpenAI({ baseURL: "https://gw.to11.ai/v1" });
  const response = await client.chat.completions.create({
    model: "openai::gpt-4o",
    messages: [{ role: "user", content: "What is the capital of France?" }],
    max_tokens: 256,
  });
  ```
</CodeGroup>

**Response:**

```json theme={null}
{
  "id": "chatcmpl-abc123",
  "object": "chat.completion",
  "model": "gpt-4o",
  "choices": [{
    "index": 0,
    "message": { "role": "assistant", "content": "Paris." },
    "finish_reason": "stop"
  }],
  "usage": { "prompt_tokens": 14, "completion_tokens": 3, "total_tokens": 17 }
}
```

### Anthropic format

```bash theme={null}
curl https://gw.to11.ai/v1/messages \
  -H "Authorization: Bearer $ANTHROPIC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "anthropic::claude-sonnet-4-6",
    "max_tokens": 256,
    "messages": [{"role": "user", "content": "Hello!"}]
  }'
```

**Response:**

```json theme={null}
{
  "id": "msg-abc123",
  "type": "message",
  "role": "assistant",
  "content": [{ "type": "text", "text": "Hello!" }],
  "model": "claude-sonnet-4-6",
  "stop_reason": "end_turn",
  "usage": { "input_tokens": 10, "output_tokens": 5 }
}
```

### Wire format must match the provider

Each chat endpoint carries one wire format, and the gateway forwards the request to the provider in that format:

| Endpoint | Wire format | Reaches |
| - | - | - |
| `/v1/chat/completions` | `openai.chat` | OpenAI, xAI, and the OpenAI-compatible providers |
| `/v1/responses` | `openai.responses` | OpenAI and xAI |
| `/v1/messages` | `anthropic.messages` | Anthropic |

[Which SDK to call a provider with](/docs/reference/providers#which-sdk-to-call-a-provider-with) has the full list, including Google Gemini, Google Vertex AI, and AWS Bedrock. A request in a format the provider does not speak — such as a `/v1/chat/completions` request with `"model": "anthropic::claude-sonnet-4-6"` — is rejected with `400 Bad Request` and `x-to11-error-code: cross_dialect` before anything is sent to the provider. See [Wire-format mismatch](/docs/reference/error-handling#wire-format-mismatch).

### Streaming

Add `"stream": true` to any request to receive Server-Sent Events:

```bash theme={null}
curl -N https://gw.to11.ai/v1/chat/completions \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai::gpt-4o",
    "messages": [{"role": "user", "content": "Count to 3"}],
    "stream": true
  }'
```

The gateway forwards the provider's SSE events as they arrive. See [Streaming](/docs/reference/streaming).

### Structured output

`response_format` is an OpenAI Chat Completions field and reaches the provider unchanged:

```json theme={null}
{
  "model": "openai::gpt-4o",
  "messages": [{"role": "user", "content": "List 3 colors as JSON"}],
  "response_format": { "type": "json_object" }
}
```

Whether a type (`text`, `json_object`, `json_schema`) is supported is up to the provider and model; an unsupported one returns the provider's error.

### Tool calls

The `tools` field reaches the provider unchanged, in the endpoint's format: OpenAI `function` definitions with `parameters` on `/v1/chat/completions`, Anthropic definitions with `input_schema` on `/v1/messages`:

```json theme={null}
{
  "model": "openai::gpt-4o",
  "messages": [{"role": "user", "content": "What's the weather in Paris?"}],
  "tools": [{
    "type": "function",
    "function": {
      "name": "get_weather",
      "description": "Get current weather for a location",
      "parameters": {
        "type": "object",
        "properties": {
          "location": { "type": "string" }
        },
        "required": ["location"]
      }
    }
  }]
}
```

## Models

List all configured models or retrieve a single model. The list holds each active provider's listed models that its access policy serves in the request's environment — no upstream provider call is made. `id` is the bare model id and `owned_by` is the provider's routing identifier, so `<owned_by>::<id>` is the value to send in `model`. A provider that allows by default can serve models that are not listed here.

```bash theme={null}
# List all models
curl https://gw.to11.ai/v1/models \
  -H "x-to11-authorization: Bearer $TO11_API_KEY" \
  -H "x-to11-project-id: $TO11_PROJECT_ID"
```

```json theme={null}
{
  "object": "list",
  "data": [
    { "id": "gpt-4o", "object": "model", "created": 0, "owned_by": "openai" },
    { "id": "claude-sonnet-4-6", "object": "model", "created": 0, "owned_by": "anthropic" }
  ]
}
```

```bash theme={null}
# Get a single model
curl https://gw.to11.ai/v1/models/gpt-4o
```

## Embeddings

Passthrough proxy to OpenAI-compatible providers. The request is routed by its `model` field, like a chat request. Anthropic models return `400 Bad Request`.

```bash theme={null}
curl -X POST https://gw.to11.ai/v1/embeddings \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "openai::text-embedding-3-small", "input": "hello world"}'
```

Input text is scanned by the security pipeline (PII + blocklist) when security is enabled. The embedding model must be one the provider's [access policy](/docs/deploy/concepts/models#access-policy) allows.

## Token counting

Passthrough proxy to Anthropic's `/messages/count_tokens` endpoint. Only Anthropic models are supported — OpenAI models return `400 Bad Request`.

```bash theme={null}
curl -X POST https://gw.to11.ai/v1/messages/count_tokens \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "anthropic::claude-sonnet-4-6",
    "messages": [{"role": "user", "content": "How many tokens is this?"}]
  }'
```

Response: `{"input_tokens": 14}`

## Image generation

Passthrough proxy to OpenAI-compatible providers' DALL-E endpoint. Anthropic models return `400 Bad Request`.

```bash theme={null}
curl -X POST https://gw.to11.ai/v1/images/generations \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "openai::dall-e-3", "prompt": "a white cat", "n": 1, "size": "1024x1024"}'
```

The `prompt` field is scanned by the security pipeline when enabled. The image model must be one the provider's [access policy](/docs/deploy/concepts/models#access-policy) allows.

## Audio transcription

Passthrough proxy to OpenAI's Whisper endpoint. The request must be `multipart/form-data` containing an audio file. No security scanning is applied (binary audio input).

```bash theme={null}
curl -X POST https://gw.to11.ai/v1/audio/transcriptions \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -F file=@recording.mp3 \
  -F model=openai::whisper-1
```

## Audio speech (TTS)

Passthrough proxy to OpenAI's text-to-speech endpoint. Anthropic models return `400 Bad Request`.

```bash theme={null}
curl -X POST https://gw.to11.ai/v1/audio/speech \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "openai::tts-1", "input": "Hello world", "voice": "alloy"}' \
  --output speech.mp3
```

The `input` field is scanned by the security pipeline when enabled.

## Files

Passthrough proxy to OpenAI's file management endpoints. Supports upload (multipart), list, retrieve, download, and delete. Anthropic models return `400 Bad Request`. No security scanning is applied.

```bash theme={null}
# Upload a file
curl -X POST https://gw.to11.ai/v1/files \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -F purpose=assistants \
  -F file=@data.jsonl

# List files
curl https://gw.to11.ai/v1/files \
  -H "Authorization: Bearer $OPENAI_API_KEY"

# Retrieve file metadata
curl https://gw.to11.ai/v1/files/file-abc123 \
  -H "Authorization: Bearer $OPENAI_API_KEY"

# Download file content
curl https://gw.to11.ai/v1/files/file-abc123/content \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  --output downloaded.jsonl

# Delete a file
curl -X DELETE https://gw.to11.ai/v1/files/file-abc123 \
  -H "Authorization: Bearer $OPENAI_API_KEY"
```

## Response headers

The gateway adds these headers so clients can classify and correlate responses without parsing the body:

| Header | When | Value |
| - | - | - |
| `x-to11-error-code` | Every error response | Stable to11 error classification (e.g. `rate_limit`, `auth`, `model_not_found`) |
| `x-to11-upstream-provider` | Errors that reached an upstream | Provider slug that produced the error (e.g. `openai`, `anthropic`) |
| `Retry-After` | Upstream 429 that carried it | Seconds to wait before retrying |
| `x-to11-cache` | When response caching is enabled | `hit` or `miss`. Entries are scoped to the project and to the environment the request resolved to (`x-to11-env`), so a response cached in one environment is never served to another |
| `x-to11-cache-age` | On a cache hit | Age of the cached entry, in seconds |

## Error responses

| Scenario | Status |
| - | - |
| Model names no provider (no `::` prefix, no `x-to11-provider-id`) | `400 Bad Request` |
| Provider slug or id not active in the environment | `404 Not Found` |
| Model not served by the provider in the environment (blocked or not selected) | `404 Not Found` |
| Input guardrail violation (PII or blocklist) | `400 Bad Request` |
| Output guardrail violation (non-streaming) | `422 Unprocessable Entity` |
| Request's wire format differs from the provider's (`x-to11-error-code: cross_dialect`) | `400 Bad Request` |
| Upstream provider 4xx | Same status, passed through (e.g. `401`, `404`, `429`) |
| Upstream provider 5xx | `502 Bad Gateway` (message redacted) |

Errors are returned as a JSON object with a top-level `error` key, in the caller's SDK shape:

```json theme={null}
{ "error": { "type": "...", "code": "...", "message": "<description>" } }
```

The stable classification lives in the `x-to11-error-code` header rather than the body text. See [Error handling](/docs/reference/error-handling) for the full error-code taxonomy, when an error body is rewritten into your SDK's envelope, and retry guidance.


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