---
title: "Create a chat completion"
method: POST
path: "/chat/completions"
tags: ["Chat"]
---

# Create a chat completion

`POST /chat/completions`

OpenAI-compatible chat completions. Supports:

- Streaming (`stream: true`, SSE)
- Tool / function calling (`tools`, `tool_choice`)
- Structured outputs (`response_format`)
- **Multimodal** — send images via `content: [{type: "image_url", ...}]`
  (see `ChatMessageContentPart` schema below). `https://` URLs
  work against every vision-capable model; OrcaRouter's
  translation layer adapts the content part for each upstream
  (OpenAI, Anthropic, Google, xAI Grok).
- OrcaRouter fallback chains via `extra_body.models`.

Use provider-prefixed model names (`openai/gpt-4o-mini`,
`anthropic/claude-sonnet-4.6`, `google/gemini-2.5-flash`), plain
bare-name aliases when available, or named routers
(`orcarouter/auto`).

## Request body

- ChatCompletionRequest
  - `model` string, required — Model ID. Supports three forms: - Provider-prefixed (default): `openai/gpt-4o-mini`, `anthropic/claude-sonnet-4.6`, `google/gemini-2.5-flash` - Plain alias: `gpt-4o-mini` (when a bare-name alias is available) - Named router: `orcarouter/{name}` (resolves to a model at request time; `orcarouter/auto` is seeded on signup for every account and picks the cheapest live chat model)
  - `messages` ChatMessage[], required
    - `role` 'system' | 'user' | 'assistant' | 'tool' | 'function', required
    - `content` union
      - string
      - ChatMessageContentPart[]
        - union — A single part of a multimodal message. Use an **array** of parts as `ChatMessage.content` when sending anything beyond plain text — images, audio, or any mix. Use a **plain string** for simple text. The gateway accepts OpenAI's content-part format for every upstream (OpenAI / Anthropic / Google). OrcaRouter's translation layer adapts: - → OpenAI: native target — content parts land in OpenAI's shape. - → Anthropic: `image_url` becomes `{type: image, source: ...}`. - → Google Gemini: `image_url` becomes `inline_data`; `input_audio` becomes `inline_data` with the right MIME. Clients don't need provider-specific code.
          - object
            - `type` 'text', required
            - `text` string, required
          - object — Send an image to a vision-capable model. Two URL forms are accepted: 1. **Remote URL**: any publicly-reachable `https://` link. The upstream provider fetches the bytes. 2. **Inline data URI**: `data:image/png;base64,iVBORw0...` (or `image/jpeg`, `image/gif`, `image/webp`). Use this when you don't want to host the image somewhere. Each upstream enforces its own per-image size cap. OrcaRouter respects the upstream's limit, so exceeding it surfaces as a 400 from the provider. Check the upstream's current vision documentation for the exact number.
            - `type` 'image_url', required
            - `image_url` object, required
              - …
          - object — Inline audio for OpenAI audio-input models and Gemini multimodal models. `format` accepts `mp3` / `wav` / `flac` / `ogg` / `webm`.
            - `type` 'input_audio', required
            - `input_audio` object, required
              - …
    - `name` string
    - `tool_calls` ToolCall[]
      - `id` string, required
      - `type` 'function', required
      - `function` object, required
        - `name` string, required
        - `arguments` string, required — JSON-encoded argument object
    - `tool_call_id` string
  - `stream` boolean — When true, response is streamed as server-sent events.
  - `stream_options` object — Only applies when `stream: true`.
    - `include_usage` boolean — When true, the final streamed chunk (before `[DONE]`) includes the `usage` object with token counts.
  - `tools` Tool[]
    - `type` 'function', required
    - `function` object, required
      - `name` string, required
      - `description` string
      - `parameters` object — JSON Schema
      - `strict` boolean
  - `tool_choice` union
    - 'auto' | 'none' | 'required'
    - object
      - `type` 'function'
      - `function` object
        - `name` string
  - `parallel_tool_calls` boolean
  - `response_format` union
    - object
      - `type` 'text'
    - object
      - `type` 'json_object'
    - object
      - `type` 'json_schema', required
      - `json_schema` object, required
        - `name` string, required
        - `description` string
        - `schema` object, required
        - `strict` boolean
  - `temperature` number
  - `top_p` number
  - `max_tokens` integer
  - `max_completion_tokens` integer — Preferred over `max_tokens` for reasoning models.
  - `n` integer
  - `stop` union
    - string
    - string[]
  - `seed` integer — For deterministic sampling.
  - `logprobs` boolean
  - `top_logprobs` integer
  - `presence_penalty` number
  - `frequency_penalty` number
  - `logit_bias` object
  - `user` string
  - `reasoning_effort` 'low' | 'medium' | 'high' — For OpenAI reasoning models (`o1`, `o3*`, `o4*`, `gpt-5*-pro`, etc.). Anthropic Claude uses the `thinking` field instead; Gemini uses provider-specific configuration.
  - `web_search_options` object — Enable web search on a Chat Completions request. The Responses API uses `tools: [{"type": "web_search"}]` instead. Honored by OpenAI search-preview models, OpenAI models that accept the modern `web_search` tool, and Anthropic models (translated to Anthropic's native `web_search` server-tool).
    - `search_context_size` 'low' | 'medium' | 'high' — Controls search depth. Pricing for `web_search` is the same regardless.
    - `user_location` object — Hint about the caller's location for localized results.
      - `approximate` object
        - `country` string
        - `region` string
        - `city` string
        - `timezone` string
  - `web_search` unknown
  - `extra_body` OrcaExtraBody — OrcaRouter-specific request extensions. Place these under the `extra_body` top-level key of your chat completion request.
    - `models` string[] — Ordered fallback chain. If the primary `model` fails, OrcaRouter tries each model in sequence until one succeeds or the list is exhausted. Maximum 5 models.
    - `route` 'fallback' — Set to `"fallback"` to enable the `models` chain.

## Response `200`

Successful completion. Streaming responses use SSE (`text/event-stream`).

- ChatCompletionResponse
  - `id` string
  - `object` 'chat.completion'
  - `created` integer
  - `model` string
  - `choices` object[]
    - `index` integer
    - `message` ChatMessage
      - `role` 'system' | 'user' | 'assistant' | 'tool' | 'function', required
      - `content` union
        - string
        - ChatMessageContentPart[]
          - union — A single part of a multimodal message. Use an **array** of parts as `ChatMessage.content` when sending anything beyond plain text — images, audio, or any mix. Use a **plain string** for simple text. The gateway accepts OpenAI's content-part format for every upstream (OpenAI / Anthropic / Google). OrcaRouter's translation layer adapts: - → OpenAI: native target — content parts land in OpenAI's shape. - → Anthropic: `image_url` becomes `{type: image, source: ...}`. - → Google Gemini: `image_url` becomes `inline_data`; `input_audio` becomes `inline_data` with the right MIME. Clients don't need provider-specific code.
            - object
              - …
            - object — Send an image to a vision-capable model. Two URL forms are accepted: 1. **Remote URL**: any publicly-reachable `https://` link. The upstream provider fetches the bytes. 2. **Inline data URI**: `data:image/png;base64,iVBORw0...` (or `image/jpeg`, `image/gif`, `image/webp`). Use this when you don't want to host the image somewhere. Each upstream enforces its own per-image size cap. OrcaRouter respects the upstream's limit, so exceeding it surfaces as a 400 from the provider. Check the upstream's current vision documentation for the exact number.
              - …
            - object — Inline audio for OpenAI audio-input models and Gemini multimodal models. `format` accepts `mp3` / `wav` / `flac` / `ogg` / `webm`.
              - …
      - `name` string
      - `tool_calls` ToolCall[]
        - `id` string, required
        - `type` 'function', required
        - `function` object, required
          - `name` string, required
          - `arguments` string, required — JSON-encoded argument object
      - `tool_call_id` string
    - `finish_reason` 'stop' | 'length' | 'content_filter' | 'tool_calls' | 'function_call'
  - `usage` Usage
    - `prompt_tokens` integer
    - `completion_tokens` integer
    - `total_tokens` integer

## Other responses

- `400` — Invalid request parameters.
- `401` — Missing or invalid API key.
- `402` — Account quota exhausted.
- `429` — Rate limit exceeded. Retry after the delay in `Retry-After` header.
- `502` — All upstream providers failed (including any `extra_body.models` fallback chain). Response includes a description of the last upstream error encountered.

---

[API](https://skmtc.dev/orcarouter/apis/orcarouter-api.md) · [All operations](https://skmtc.dev/orcarouter/apis/orcarouter-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/orcarouter/orcarouter-api/revisions/9c5cc5d00311/schema)
