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

# Chat Completions

> OpenAI-compatible chat endpoint. Any provider, any model.

`POST /v1/chat/completions`

Send a chat request to any supported provider through the gateway. The response format is identical to OpenAI's chat completions API regardless of which provider handles the request.

## Auth

All three schemes are accepted:

```http theme={null}
Authorization: GatelitKey sk_live_...
Authorization: GatelitSigned <signed-token>
```

<Info>
  `Bearer` (OIDC) is supported but in **Alpha**. Contact us if you need OIDC auth.
</Info>

## Request

| Field         | Type      | Required | Description                                  |
| ------------- | --------- | -------- | -------------------------------------------- |
| `model`       | `string`  | Yes      | Provider/model in `provider/model-id` format |
| `messages`    | `array`   | Yes      | Array of `{role, content}` objects           |
| `max_tokens`  | `integer` | No       | Max output tokens                            |
| `temperature` | `number`  | No       | 0–2, stripped for reasoning models           |
| `stream`      | `boolean` | No       | Enable SSE streaming                         |

### Gateway-specific fields

| Field                      | Description                                                    |
| -------------------------- | -------------------------------------------------------------- |
| `x-gatelit-output-schema`  | Structured output config (`json_object` or `json_schema` mode) |
| `x-gatelit-prompt-id`      | Tag request with a saved prompt's slug for log correlation     |
| `x-gatelit-fallback-chain` | Ordered fallback models with trigger conditions                |

## Response

### Non-streaming

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

### Response headers

| Header                      | Description                                  |
| --------------------------- | -------------------------------------------- |
| `x-gatelit-request-id`      | Unique request ID for log lookup             |
| `x-gatelit-model`           | Resolved model in `provider/model` format    |
| `x-gatelit-auth-mode`       | `Bearer`, `GatelitSigned`, or `GatelitKey`   |
| `x-gatelit-fallback`        | `"true"` when a fallback model was used      |
| `x-gatelit-fallback-reason` | `rate_limit`, `provider_error`, or `timeout` |
| `x-gatelit-fallback-model`  | The fallback model that responded            |

### Streaming

When `stream: true`, the response is an OpenAI-compatible SSE stream. Each `data:` line is a JSON chunk. Final line is `data: [DONE]`.

## Examples

```bash theme={null}
curl https://gateway.gatelit.dev/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: GatelitKey sk_live_..." \
  -d '{
    "model": "openai/gpt-4o",
    "messages": [{"role": "user", "content": "Hello!"}]
  }'
```

```ts theme={null}
import { GatelitClient } from "@gatelit/sdk"

const client = new GatelitClient({
  gatewayUrl: "https://gateway.gatelit.dev",
  getToken: async () => ({ token: "sk_live_...", scheme: "GatelitKey" }),
})

const response = await client.chat({
  model: "openai/gpt-4o",
  messages: [{ role: "user", content: "Hello!" }],
})
```

### Structured output

```bash theme={null}
curl https://gateway.gatelit.dev/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: GatelitKey sk_live_..." \
  -d '{
    "model": "openai/gpt-4o",
    "messages": [{"role": "user", "content": "Alice is 30."}],
    "x-gatelit-output-schema": {
      "mode": "json_schema",
      "type": "object",
      "properties": {
        "name": {"type": "string"},
        "age": {"type": "integer"}
      },
      "required": ["name", "age"]
    }
  }'
```

### With fallback chain

```bash theme={null}
curl https://gateway.gatelit.dev/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: GatelitKey sk_live_..." \
  -d '{
    "model": "openai/gpt-4o",
    "messages": [{"role": "user", "content": "Explain TCP"}],
    "x-gatelit-fallback-chain": [
      {"model": "anthropic/claude-3-5-haiku-20241022", "triggers": ["rate_limit"]},
      {"model": "google/gemini-2.5-flash"}
    ]
  }'
```

## Errors

| Status | Code             | Meaning                                |
| ------ | ---------------- | -------------------------------------- |
| 400    | `gateway_error`  | Invalid model format or missing fields |
| 401    | `unauthorized`   | Missing, invalid, or expired token     |
| 502    | `provider_error` | Upstream provider returned an error    |


## OpenAPI

````yaml post /v1/chat/completions
openapi: 3.1.0
info:
  title: Gatelit Gateway API
  version: '1.0'
  description: |
    The Gatelit gateway is a single HTTP endpoint that routes AI requests to any
    supported provider. It handles authentication, provider key resolution,
    request transformation, stream normalisation, spend tracking, and logging.

    All requests must include an `Authorization` header. Three auth schemes are
    supported — choose based on your deployment scenario.
servers:
  - url: https://gateway.yourapp.com
    description: Your gateway URL
security: []
paths:
  /v1/chat/completions:
    post:
      summary: Chat completions
      description: >
        Send a chat request to any supported provider through the gateway.


        The gateway handles:

        - **Auth** — verify token, resolve identity

        - **Provider routing** — resolve org-scoped API key → upstream provider

        - **Param clamping** — strip unsupported params, clamp values in range

        - **Request transform** — reshape to upstream provider's native format

        - **Response normalisation** — back to OpenAI format (including SSE
        streams)

        - **Logging** — usage, latency, and cost estimates logged to Supabase


        Providers: `openai`, `anthropic`, `google`, `mistral`.
      operationId: chatCompletions
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ChatCompletionsRequest'
            examples:
              simple:
                summary: Simple chat
                value:
                  model: openai/gpt-4o
                  messages:
                    - role: user
                      content: What is the capital of France?
              streaming:
                summary: Streaming
                value:
                  model: anthropic/claude-3-5-haiku-20241022
                  messages:
                    - role: user
                      content: Write a haiku about cloud infrastructure.
                  stream: true
                  max_tokens: 100
              json_schema:
                summary: Structured JSON output
                value:
                  model: openai/gpt-4o
                  messages:
                    - role: user
                      content: 'Extract the name and age: "Alice is 30 years old."'
                  x-gatelit-output-schema:
                    mode: json_schema
                    type: object
                    properties:
                      name:
                        type: string
                      age:
                        type: integer
                    required:
                      - name
                      - age
              fallback:
                summary: Fallback chain
                value:
                  model: openai/gpt-4o
                  messages:
                    - role: user
                      content: Hello
                  x-gatelit-fallback-chain:
                    - model: anthropic/claude-3-5-haiku-20241022
                      triggers:
                        - rate_limit
                        - provider_error
                    - model: google/gemini-2.5-flash
              with_prompt_id:
                summary: Linked to a saved prompt (log correlation only)
                value:
                  model: openai/gpt-4o
                  messages:
                    - role: user
                      content: Summarize this document
                  x-gatelit-prompt-id: my-summarizer
      responses:
        '200':
          description: |
            Successful response.

            - **Non-streaming:** `Content-Type: application/json`
            - **Streaming:** `Content-Type: text/event-stream`

            Response headers always include:
            - `x-gatelit-request-id` — use for log lookup in the dashboard
            - `x-gatelit-model` — the provider/model that responded
            - `x-gatelit-auth-mode` — `Bearer`, `GatelitSigned`, or `GatelitKey`
          headers:
            x-gatelit-request-id:
              schema:
                type: string
              description: Unique request ID — look up in dashboard logs
            x-gatelit-model:
              schema:
                type: string
              description: Resolved model in `provider/model` format
            x-gatelit-auth-mode:
              schema:
                type: string
              description: Auth scheme used
            x-gatelit-fallback:
              schema:
                type: string
              description: Present only when a fallback model was used
            x-gatelit-fallback-reason:
              schema:
                type: string
              description: >-
                Why the fallback triggered (`rate_limit`, `provider_error`,
                `timeout`)
            x-gatelit-fallback-model:
              schema:
                type: string
              description: The fallback model that responded
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ChatCompletionsResponse'
              example:
                id: chatcmpl-abc123
                object: chat.completion
                created: 1717776000
                model: openai/gpt-4o
                choices:
                  - index: 0
                    message:
                      role: assistant
                      content: The capital of France is Paris.
                    finish_reason: stop
                usage:
                  prompt_tokens: 15
                  completion_tokens: 8
                  total_tokens: 23
            text/event-stream:
              schema:
                type: string
                description: >
                  OpenAI-compatible SSE stream. Each `data:` line is a JSON
                  object.

                  The final line is `data: [DONE]`.


                  ```sse

                  data:
                  {"id":"chatcmpl-abc","choices":[{"delta":{"content":"The"},"index":0}]}

                  data: {"id":"chatcmpl-abc","choices":[{"delta":{"content":"
                  capital"},"index":0}]}

                  data: {"id":"chatcmpl-abc","choices":[{"delta":{"content":"
                  of"},"index":0}]}

                  ...

                  data:
                  {"id":"chatcmpl-abc","choices":[{"delta":{},"finish_reason":"stop"}],"usage":{"prompt_tokens":15,"completion_tokens":8,"total_tokens":23}}

                  data: [DONE]

                  ```
        '400':
          description: >-
            Bad request — invalid model format, missing fields, or malformed
            JSON.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GatelitError'
              example:
                error: true
                code: gateway_error
                message: >-
                  Missing or invalid 'model' field. Expected format:
                  'provider/model-name'
        '401':
          description: Authentication failed — missing, invalid, or expired token.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GatelitError'
              example:
                error: true
                code: unauthorized
                message: Invalid or expired token
        '502':
          description: >-
            Upstream provider returned an error or was unreachable. Check
            fallback chains.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GatelitError'
              example:
                error: true
                code: provider_error
                message: Upstream error 503 — Service Unavailable
      security:
        - BearerToken: []
        - GatelitSigned: []
        - GatelitKey: []
      x-codeSamples:
        - lang: curl
          label: curl — service key
          source: |
            curl https://gateway.yourapp.com/v1/chat/completions \
              -H "Content-Type: application/json" \
              -H "Authorization: GatelitKey sk_live_your_service_key" \
              -d '{
                "model": "openai/gpt-4o",
                "messages": [{"role": "user", "content": "What is the capital of France?"}]
              }'
        - lang: curl
          label: curl — signed token
          source: >
            # First, have your backend issue a token (shown here for
            illustration).

            # In practice, this happens on a server endpoint.


            TOKEN=$(node -e "
              const { signToken } = require('@gatelit/sdk/sign');
              signToken({ sub: 'user_123', ttl: 60 }, 'your-secret-at-least-32-chars')
                .then(t => console.log(t))
            ")


            curl https://gateway.yourapp.com/v1/chat/completions \
              -H "Content-Type: application/json" \
              -H "Authorization: GatelitSigned $TOKEN" \
              -d '{
                "model": "openai/gpt-4o",
                "messages": [{"role": "user", "content": "Hello!"}]
              }'
        - lang: ts
          label: SDK — non-streaming
          source: >
            import { GatelitClient } from "@gatelit/sdk"


            const client = new GatelitClient({
              gatewayUrl: "https://gateway.yourapp.com",
              getToken: async () => ({
                token: "sk_live_...",
                scheme: "GatelitKey",
              }),
            })


            const response = await client.chat({
              model: "openai/gpt-4o",
              messages: [{ role: "user", content: "What is the capital of France?" }],
            })


            console.log(response.content)   // "The capital of France is Paris."

            console.log(response.usage)     // { inputTokens: 15, outputTokens:
            8, totalTokens: 23 }
        - lang: ts
          label: SDK — streaming
          source: |
            import { GatelitClient } from "@gatelit/sdk"

            const client = new GatelitClient({
              gatewayUrl: "https://gateway.yourapp.com",
              getToken: async () => {
                const res = await fetch("/api/ai-token")
                const { token } = await res.json()
                return { token, scheme: "GatelitSigned" }
              },
            })

            for await (const chunk of client.stream({
              model: "anthropic/claude-3-5-haiku-20241022",
              messages: [{ role: "user", content: "Write a haiku about clouds." }],
            })) {
              process.stdout.write(chunk.delta)
            }
        - lang: ts
          label: SDK — typed JSON
          source: >
            import { GatelitClient } from "@gatelit/sdk"


            const client = new GatelitClient({
              gatewayUrl: "https://gateway.yourapp.com",
              getToken: async () => ({
                token: "sk_live_...",
                scheme: "GatelitKey",
              }),
            })


            const result = await client.chatJson<{ name: string; age: number
            }>({
              model: "openai/gpt-4o",
              messages: [{ role: "user", content: "Alice is 30 years old." }],
              outputSchema: {
                mode: "json_schema",
                type: "object",
                properties: {
                  name: { type: "string" },
                  age: { type: "integer" },
                },
                required: ["name", "age"],
              },
            })


            console.log(result.name, result.age) // Alice 30
components:
  schemas:
    ChatCompletionsRequest:
      type: object
      required:
        - model
        - messages
      properties:
        model:
          type: string
          description: |
            Model in `provider/model-id` format.
            Supported providers: `openai`, `anthropic`, `google`, `mistral`.
          examples:
            - openai/gpt-4o
            - anthropic/claude-3-5-sonnet-20241022
            - google/gemini-2.5-flash
            - mistral/mistral-large-latest
        messages:
          type: array
          items:
            $ref: '#/components/schemas/ChatMessage'
          minItems: 1
        max_tokens:
          type: integer
          description: |
            Maximum tokens to generate. The gateway maps this to the correct
            upstream parameter — `max_completion_tokens` for OpenAI reasoning
            models, `max_tokens` for everything else.
          example: 1024
        temperature:
          type: number
          minimum: 0
          maximum: 2
          description: >
            Sampling temperature. Omit for reasoning models (o3, o3-mini,
            o4-mini)

            — the gateway strips it automatically based on the model catalog.
          example: 0.7
        top_p:
          type: number
          minimum: 0
          maximum: 1
          description: Nucleus sampling. Supported by all providers.
        stream:
          type: boolean
          default: false
          description: >
            When true, the response is an OpenAI-compatible SSE stream.

            Each `data:` line is a JSON object regardless of the upstream
            provider.
        x-gatelit-output-schema:
          type: object
          description: |
            Structured output configuration. The gateway translates to the
            correct provider-specific format automatically.
          properties:
            mode:
              type: string
              enum:
                - json_object
                - json_schema
              description: >
                `json_object` — model must return valid JSON (any shape).

                `json_schema` — model must return JSON matching the provided
                schema.
            type:
              type: string
              description: JSON Schema `type` for `json_schema` mode.
            properties:
              type: object
              additionalProperties: true
              description: JSON Schema `properties` for `json_schema` mode.
            required:
              type: array
              items:
                type: string
          required:
            - mode
        x-gatelit-prompt-id:
          type: string
          description: >
            Associates this request with a saved prompt in the dashboard.

            The prompt's content is not used — only the ID is logged for
            correlation.
        x-gatelit-fallback-chain:
          type: array
          description: |
            Ordered list of fallback models to try if the primary model fails.
            Each entry specifies a model and the error types that trigger it.
          items:
            type: object
            required:
              - model
            properties:
              model:
                type: string
                description: Fallback model in `provider/model-id` format.
              triggers:
                type: array
                items:
                  type: string
                  enum:
                    - rate_limit
                    - provider_error
                    - timeout
                    - context_limit
                description: |
                  Error types that trigger this fallback.
                  Omit to trigger on any error from the previous model.
    ChatCompletionsResponse:
      type: object
      description: |
        OpenAI-compatible chat completion response.
        Returned when `stream` is false (default).
      properties:
        id:
          type: string
        object:
          type: string
          example: chat.completion
        created:
          type: integer
        model:
          type: string
          description: The upstream model that handled the request.
        choices:
          type: array
          items:
            type: object
            properties:
              index:
                type: integer
              message:
                $ref: '#/components/schemas/ChatMessage'
              finish_reason:
                type: string
                enum:
                  - stop
                  - length
                  - tool_calls
                  - content_filter
        usage:
          $ref: '#/components/schemas/Usage'
    GatelitError:
      type: object
      required:
        - error
        - code
        - message
      properties:
        error:
          type: boolean
          enum:
            - true
        code:
          type: string
          enum:
            - unauthorized
            - gateway_error
            - provider_error
            - forbidden
            - policy_violation
            - rate_limit_exceeded
            - model_not_allowed
            - token_limit_exceeded
        message:
          type: string
    ChatMessage:
      type: object
      required:
        - role
        - content
      properties:
        role:
          type: string
          enum:
            - system
            - user
            - assistant
        content:
          type: string
      example:
        role: user
        content: Explain quantum entanglement in one sentence.
      x-codeSample: |
        // SDK
        const msg: ChatMessage = {
          role: "user",
          content: "Explain quantum entanglement in one sentence."
        }
    Usage:
      type: object
      properties:
        prompt_tokens:
          type: integer
          description: Tokens consumed by the input (system prompt + messages).
        completion_tokens:
          type: integer
          description: Tokens generated in the response.
        total_tokens:
          type: integer
  securitySchemes:
    BearerToken:
      type: http
      scheme: bearer
      description: >
        OIDC JWT issued by your auth provider (Alpha).

        Full self-serve configuration is coming soon — contact us for early
        access.

        Use this for browser/frontend clients where a user is signed in.
    GatelitSigned:
      type: apiKey
      in: header
      name: Authorization
      description: |
        Short-lived HMAC-signed token issued by your backend.
        Format: `GatelitSigned <token>`

        Generate with `signToken()` from `@gatelit/sdk`:
        ```ts
        import { signToken } from "@gatelit/sdk/sign"
        const token = await signToken(
          { sub: "user-123", orgId: "org-abc", ttl: 60 },
          process.env.GATELIT_SIGNING_SECRET!
        )
        ```
    GatelitKey:
      type: apiKey
      in: header
      name: Authorization
      description: |
        Long-lived service key for backend-to-backend use.
        Format: `GatelitKey sk_live_...`

        Create service keys in the dashboard under Settings → Service Keys.

````