# API Compatibility

The endpoints we serve, and the ones we don't.


The gateway speaks three wire formats. Point an OpenAI SDK at our base URL and existing chat-completions code works unchanged. The same service also serves the Anthropic Messages API and the Responses subset Codex CLI uses.

## Supported

| Endpoint | Notes |
| --- | --- |
| `POST /v1/chat/completions` | Streaming and non-streaming. Returns exact token counts in `usage`. |
| `POST /v1/responses` | Codex-compatible: streaming, instructions, text input, function tools, reasoning effort. |
| `POST /v1/messages` | Anthropic Messages format: streaming, non-streaming, `system`, tool use. |
| `POST /v1/messages/count_tokens` | Counts input tokens without running the request. |
| `POST /v1/systemone` | System One decision models such as Laya: typed questions in, probabilities out. See [System One](/docs/system-one). |
| `GET /v1/models` | Live model list with `pricing` per million tokens and `context_length`. |
| `GET /v1/model/info` | Same lineup with metadata: rates, context window, capability flags. What harnesses read to self-configure. |

## Not supported

The gateway does not serve Responses features outside the Codex-compatible subset, [`/v1/embeddings`], [`/v1/completions`], [`/v1/batches`], [`/v1/fine-tuning/jobs`], [`/v1/images/generations`], and [`/v1/audio/speech`]. [Tell us](/support) if your workload needs one.

## Responses API and Codex CLI

`POST /v1/responses` serves the Codex-compatible subset: streamed request lifecycle, instructions, text input, function tools, and `function_call_output`. Codex works against it as is.

This does not expose OpenAI-hosted tools, server-side conversation persistence, or other provider-native Responses features. Codex uses local compaction with a custom provider, so `/v1/responses/compact` is not required.

## Reasoning control

On chat completions, set `reasoning_effort` to disable or tune thinking:

```json
{
  "model": "glm-5.2",
  "messages": [{ "role": "user", "content": "Reply with only the answer: 17 × 23" }],
  "reasoning_effort": "low"
}
```

Values: `none`, `low`, `medium`, `high`. Leave it unset for the model default. The setting survives failover to a standby.

On Responses, put the same value inside the standard object: `"reasoning": { "effort": "none" }`.

## Output length

`max_tokens` may go up to the model's [context length](/models). Prompt and completion share that window.

Your team's [tokens-per-minute limit](/docs/rate-limits) is charged on what a request actually used, minus any prompt tokens served from cache. A long request is not refused for its size. It uses up the window, and the requests after it wait.

A reasoning model spends the same budget on thinking as on its reply. Size `max_tokens` for both. A budget sized for the answer alone comes back empty, with `length` as the finish reason.

## Anthropic Messages API

Send your key as `x-api-key` or `Authorization: Bearer`. Use a model ID exactly as [Models](/models) lists it, including for the Claude models we serve.

The Anthropic SDKs append `/v1/messages` themselves, so they take the gateway root. An OpenAI SDK takes `https://api.inference.boundless.network/v1`.

Responses are Anthropic-shaped: `content` blocks, `stop_reason`, `tool_use`, and `usage` keyed `input_tokens` / `output_tokens`. Streaming gives the standard Anthropic SSE events.

`max_tokens` is required and must cover thinking plus reply. Give reasoning models 1024 or more.

## The `usage` object

Every chat-completions response (including the final stream chunk) carries:

```json
{
  "usage": {
    "prompt_tokens": 42,
    "completion_tokens": 128,
    "total_tokens": 170
  }
}
```

These numbers are what you are billed on. Multiply by the [rate card](/docs/pricing) to verify any charge. Messages responses use `input_tokens` / `output_tokens`.

## Request ids and per-request cost

Every inference response carries `Inference-Id` (and `X-Request-Id` with the same value). Utility routes (`/v1/models`, `/v1/messages/count_tokens`) carry neither.

Non-streamed responses also report cost:

```http
Inference-Id: 789a9551-4e61-45d6-8857-fc08cb7e7f68
X-Response-Cost: 0.00007228
X-Key-Spend: 0.00012594
```

`X-Response-Cost` is that request's charge in dollars. `X-Key-Spend` is the running total for the key. Both are plain decimals.

The cost header is left out, rather than set to zero, when the charge is not known at response start. That happens on a streamed response, which sends headers before the first token. A `0` means the request really was free, such as a fully cached read.

## Versioning and deprecation

The wire version is in the URL path. Every inference endpoint is under `/v1`. Breaking changes take a new prefix; they never land on `/v1`.

While the first accounts are onboarded, the model lineup, prices, and base URL may change. Nothing is withdrawn silently: deprecated endpoints carry a `Deprecation` header, and once a removal date is set, a [`Sunset`](https://www.rfc-editor.org/rfc/rfc8594.html) header carries it. Nothing is deprecated today, so neither header appears yet.

Model identifiers follow the same process. `GET /v1/models` is the live list; [`GET /api/catalog`](/api/catalog) is the machine-readable form.

## Rate limits on public endpoints

The [admission caps](/docs/rate-limits) on your team are enforced across requests, token throughput, and concurrency. A capped key carries `RateLimit-Policy` and `RateLimit` headers. A refusal is 429 with `Retry-After`. Credits exhaustion has no `Retry-After`.

Public endpoints (`/api/catalog`, MCP endpoints, `/a2a/v1`, `/ask`) are capped per caller in requests:

```http
RateLimit-Policy: "agent";q=120;w=60
RateLimit: "agent";r=118;t=42
```

`q` = quota, `w` = window in seconds, `r` = remaining, `t` = seconds to reset. The values are advisory snapshots: pace against them, but don't treat them as a contract.
