# Wire formats (/docs/gateway/wire-formats)

The three request shapes the gateway accepts — OpenAI Chat Completions, Anthropic Messages and the OpenAI Responses API.

Pick the format your client already speaks. All three take the same bearer key, resolve the same aliases, apply the same limits and write the same usage records. Nothing in your account depends on which one you choose.

| Format | Endpoint | Best for |
| --- | --- | --- |
| OpenAI Chat Completions | `POST /v1/chat/completions` | OpenAI SDKs, LangChain, LlamaIndex, Cursor, Continue, most agent frameworks. |
| Anthropic Messages | `POST /v1/messages` | Anthropic SDKs, Claude Code, anything Anthropic-native. |
| OpenAI Responses | `POST /v1/responses` | Newer OpenAI SDKs and Copilot's `apiType: "responses"` mode. |

## OpenAI Chat Completions [#openai-chat-completions]

The gateway's native shape. Accepts `model`, `messages`, `stream`, `max_tokens` (or `max_completion_tokens`), `temperature`, `top_p`, `stop`, `tools`, `tool_choice`, `response_format`, `reasoning_effort` and `user`. Unknown fields pass through to the upstream.

<Tabs items={['Request', 'Response']}>
<Tab value="Request">

```bash
curl https://ai.codai.ro/v1/chat/completions \
  -H "Authorization: Bearer $CODAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "codai",
    "messages": [
      { "role": "system", "content": "You are a terse senior engineer." },
      { "role": "user", "content": "Explain Promise.all in three sentences." }
    ],
    "max_tokens": 300
  }'
```

</Tab>
<Tab value="Response">

```json
{
  "id": "chatcmpl_7d3c…",
  "object": "chat.completion",
  "created": 1790000000,
  "model": "codai",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "Promise.all takes an iterable of promises and returns one promise. It resolves with an array of results once every input resolves, preserving order. It rejects as soon as any input rejects."
      },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 31,
    "completion_tokens": 48,
    "total_tokens": 79,
    "prompt_tokens_details": { "cached_tokens": 0 }
  }
}
```

</Tab>
</Tabs>

### Tool calling [#tool-calling]

Standard OpenAI function tools. When you pass `tools`, the gateway treats you as the owner of the tool loop: it streams the model's `tool_calls` back untouched and never runs a second agent loop behind you.

```json
{
  "model": "codai",
  "messages": [{ "role": "user", "content": "What is the weather in Cluj?" }],
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "get_weather",
        "description": "Current weather for a city",
        "parameters": {
          "type": "object",
          "properties": { "city": { "type": "string" } },
          "required": ["city"]
        }
      }
    }
  ]
}
```

The reply carries `choices[0].message.tool_calls` and `finish_reason: "tool_calls"`. Send the result back as a `{ "role": "tool", "tool_call_id": "…", "content": "…" }` message.

### Images [#images]

Send `image_url` content parts on a user message, exactly as with OpenAI. `codai` advertises `vision: true`.

## Anthropic Messages [#anthropic-messages]

Accepts the public Anthropic Messages shape: `model`, `messages` with block content, `system`, `max_tokens` (required), `temperature`, `top_p`, `top_k`, `stop_sequences`, `stream`, `tools`, `tool_choice`, `metadata`. Auth is `Authorization: Bearer` **or** `x-api-key` — both work. Send `anthropic-version: 2023-06-01` as you would upstream.

<Tabs items={['Request', 'Response']}>
<Tab value="Request">

```bash
curl https://ai.codai.ro/v1/messages \
  -H "Authorization: Bearer $CODAI_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "codai",
    "max_tokens": 1024,
    "system": "You are a terse senior engineer.",
    "messages": [{ "role": "user", "content": "Explain Promise.all in three sentences." }]
  }'
```

</Tab>
<Tab value="Response">

```json
{
  "id": "msg_01Xf…",
  "type": "message",
  "role": "assistant",
  "model": "codai",
  "content": [
    {
      "type": "text",
      "text": "Promise.all takes an iterable of promises and returns one promise. It resolves with an array of results once every input resolves, preserving order. It rejects as soon as any input rejects."
    }
  ],
  "stop_reason": "end_turn",
  "stop_sequence": null,
  "usage": {
    "input_tokens": 31,
    "output_tokens": 48,
    "cache_read_input_tokens": 0,
    "cache_creation_input_tokens": 0
  }
}
```

</Tab>
</Tabs>

When the resolved upstream is Anthropic-native, bytes are forwarded 1:1 — lowest possible time to first token. When it is OpenAI-shaped (Gemini, for instance) the gateway translates on the fly; the response shape you see is always Anthropic.

## OpenAI Responses API [#openai-responses-api]

A translation layer over Chat Completions: the request is mapped to a chat request, re-enters the same route in-process (so auth, limits, routing, caching and usage apply unchanged), and the result is mapped back. Supported: `input` as a string or array of `{ role, content }` items, `function_call` / `function_call_output` items for agent loops, `instructions`, `tools` (function type), `tool_choice`, `max_output_tokens`, `temperature`, `top_p`, `stream` and `reasoning.effort`.

<Tabs items={['Request', 'Response']}>
<Tab value="Request">

```bash
curl https://ai.codai.ro/v1/responses \
  -H "Authorization: Bearer $CODAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "codai",
    "instructions": "You are a terse senior engineer.",
    "input": "Explain Promise.all in three sentences.",
    "reasoning": { "effort": "high" }
  }'
```

</Tab>
<Tab value="Response">

```json
{
  "id": "resp_chatcmpl_7d3c…",
  "object": "response",
  "created_at": 1790000000,
  "status": "completed",
  "model": "codai",
  "output": [
    {
      "type": "message",
      "id": "msg_chatcmpl_7d3c…",
      "role": "assistant",
      "status": "completed",
      "content": [
        {
          "type": "output_text",
          "text": "Promise.all takes an iterable of promises and returns one promise. It resolves with an array of results once every input resolves, preserving order. It rejects as soon as any input rejects.",
          "annotations": []
        }
      ]
    }
  ],
  "output_text": "Promise.all takes an iterable of promises …",
  "usage": {
    "input_tokens": 31,
    "input_tokens_details": { "cached_tokens": 0 },
    "output_tokens": 48,
    "total_tokens": 79
  }
}
```

</Tab>
</Tabs>

`reasoning.effort` follows OpenAI's vocabulary and maps onto codai tiers: `xhigh` → `max`, `none` → `minimal`; unknown values are dropped. An `X-Codai-Effort` header wins over the body.

<Callout type="warn">
Not supported, and rejected with `400 bad_request` and a clear message: `previous_response_id` chaining (send the full input each time), `background: true`, built-in tools such as `web_search`, and response retrieval.
</Callout>

## Choosing between them [#choosing-between-them]

- **Already have code?** Keep its format. There is no capability difference for chat.
- **Starting fresh?** Chat Completions has the widest tool support and is the gateway's native shape.
- **Need Claude-style block content or `x-api-key` auth?** Messages.
- **Copilot in Responses mode?** Responses — see [clients](./clients.mdx).

All three stream — see [streaming](./streaming.mdx) for the per-format SSE shapes.
