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

# Create Chat Completion

> Generate a model response from a message array, with support for token streaming, JSON Patch streaming, and tool calling.

Use this endpoint for real-time chat generations on the OpenAI-compatible API.

This documentation covers the OpenAI-compatible `chat/completions` endpoint. If an SDK defaults to the newer OpenAI Responses API, configure it to use chat completions instead.

## Base URL

`https://api.dottxt.ai/v1`

## Structured output

Use `response_format` with `type: "json_schema"` to constrain the model output to your schema.

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
curl https://api.dottxt.ai/v1/chat/completions \
  -H "Authorization: Bearer $DOTTXT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-oss-20b",
    "messages": [
      { "role": "user", "content": "Classify: My card was charged twice for order ORD-9842. Need refund today." }
    ],
    "response_format": {
      "type": "json_schema",
      "json_schema": {
        "name": "ticket",
        "schema": {
          "type": "object",
          "properties": {
            "category": {
              "type": "string",
              "enum": ["billing", "technical", "account", "shipping"]
            },
            "priority": {
              "type": "string",
              "enum": ["low", "medium", "high", "urgent"]
            },
            "summary": {
              "type": "string",
              "minLength": 10,
              "maxLength": 120
            },
            "tags": {
              "type": "array",
              "items": { "type": "string" },
              "minItems": 1,
              "maxItems": 4
            }
          },
          "required": ["category", "priority", "summary", "tags"],
          "additionalProperties": false
        }
      }
    }
  }'
```

```json Response theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
{
  "choices": [
    {
      "index": 0,
      "finish_reason": "stop",
      "message": {
        "role": "assistant",
        "content": "{\"category\": \"billing\", \"priority\": \"high\", \"summary\": \"Customer reports duplicate card charge on order ORD-9842, requesting refund\", \"tags\": [\"refund\", \"duplicate-charge\"]}"
      }
    }
  ]
}
```

`category` is always one of the four enum values. `summary` is between 10 and 120 characters. `tags` has 1–4 items. See the [supported features](/supported-features) for the full list of enforceable constraints.

## JSON Patch streaming

Set `stream: "patch"` alongside a `response_format` JSON schema to stream the structured response field-by-field as JSON Patch operations instead of returning a single completion. The server emits one RFC 6902 `add` operation per field as the model generates it, so downstream work (routing, dispatching, UI updates) can begin the moment the relevant field lands.

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
curl https://api.dottxt.ai/v1/chat/completions \
  -H "Authorization: Bearer $DOTTXT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-oss-20b",
    "messages": [
      { "role": "user", "content": "I was charged twice this month. Refund the duplicate." }
    ],
    "stream": "patch",
    "response_format": {
      "type": "json_schema",
      "json_schema": {
        "name": "ticket",
        "schema": {
          "type": "object",
          "properties": {
            "intent":  { "type": "string", "enum": ["billing", "technical", "account"] },
            "urgency": { "type": "string", "enum": ["low", "medium", "high", "critical"] },
            "reply":   { "type": "string", "maxLength": 400 }
          },
          "required": ["intent", "urgency", "reply"],
          "additionalProperties": false
        }
      }
    }
  }'
```

`stream: "patch"` is the only request difference from a normal structured-output call — `messages`, `temperature`, `max_tokens`, `seed`, and the rest of the chat-completions parameters all behave the same way.

### Wire format

The default response framing is **NDJSON** (`Content-Type: application/x-ndjson`): one JSON object per line, no `event:` prefix, no trailing terminator record — the stream ends when the connection closes.

```ndjson Response (NDJSON) theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
{"op":"add","path":"","value":{}}
{"op":"add","path":"/intent","value":"billing"}
{"op":"add","path":"/urgency","value":"high"}
{"op":"add","path":"/reply","value":"Hi Jane, I've processed the refund..."}
```

The endpoint also speaks **Server-Sent Events** for clients that prefer SSE framing. Send `Accept: text/event-stream` on the request, and you'll get:

```sse Response (SSE) theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
event: patch
data: {"op":"add","path":"","value":{}}

event: patch
data: {"op":"add","path":"/intent","value":"billing"}

event: patch
data: {"op":"add","path":"/urgency","value":"high"}

event: patch
data: {"op":"add","path":"/reply","value":"Hi Jane, I've processed the refund..."}

event: done
data: {}
```

The JSON Patch payloads are identical between the two framings — only the transport differs. SSE adds a final `event: done` record before the connection closes; NDJSON closes silently.

### Operation shape

Every record is an RFC 6902 `add` operation:

```json theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
{
  "op": "add",
  "path": "<JSON Pointer>",
  "value": "<field value>"
}
```

* **`op`** — always `"add"` in this mode.
* **`path`** — JSON Pointer to the location being filled in. The root document arrives first as `path: ""` with `value: {}` (or `value: []` for array-rooted schemas).
* **`value`** — the value being inserted. For leaf fields, the JSON primitive (string, number, boolean, null). For nested objects and arrays, an empty container that subsequent ops will fill.

### Order of operations

Operations arrive in schema order:

1. **Root seed** — `{"op":"add","path":"","value":{}}` opens the document. For array-rooted schemas, `value` is `[]`.
2. **Leaf adds in schema order** — top-level scalar fields like `intent`, `urgency`, `reply`.
3. **Container seeds + items** — when the schema contains nested objects or arrays, the container is seeded first with `{}` or `[]`, then each item arrives as a separate add (`/steps/0`, `/steps/1`, ...). Nested objects work the same way (`/address`, then `/address/city`, `/address/zip`).

A field's position in the schema determines when it streams. Design the schema so high-priority fields (routing keys, classifications, gates) come first; long-form fields (replies, explanations) come last.

Example for a `{intent, urgency, steps: [...], reply}` schema:

```ndjson theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
{"op":"add","path":"","value":{}}
{"op":"add","path":"/intent","value":"billing"}
{"op":"add","path":"/urgency","value":"high"}
{"op":"add","path":"/steps","value":[]}
{"op":"add","path":"/steps/0","value":"verify charge"}
{"op":"add","path":"/steps/1","value":"issue refund"}
{"op":"add","path":"/reply","value":"Hi Jane, I've processed the refund..."}
```

### Reconstructing the document

Each op is applied to the document state from the previous op. If you collect every op and apply them in order, you end up with the same JSON object a non-streaming request would have returned. The Python SDK exposes the running snapshot directly via `event.snapshot`; see [JSON Patch Streaming](/json-schema/streaming) for details.

### Patch streaming errors

* The stream opens with `200 OK` once the model starts emitting. Validation errors (bad schema, malformed request, auth failure) come back as the standard JSON error response before any patch records are sent.
* A non-200 status means no patch records will arrive; read the body for the error payload.
* Connection failures mid-stream surface as a closed stream without a terminator. The Python SDK turns these into `dottxt.PatchStreamError`.

## Plain chat

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
curl https://api.dottxt.ai/v1/chat/completions \
  -H "Authorization: Bearer $DOTTXT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-oss-20b",
    "messages": [
      { "role": "system", "content": "You are a concise assistant." },
      { "role": "user", "content": "Summarize why batch processing is useful." }
    ],
    "temperature": 0.3,
    "max_tokens": 180
  }'
```

## Example response shape

```json theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
{
  "id": "chatcmpl-abc123",
  "object": "chat.completion",
  "created": 1703187200,
  "model": "openai/gpt-oss-20b",
  "choices": [
    {
      "index": 0,
      "finish_reason": "stop",
      "message": {
        "role": "assistant",
        "content": "Batch processing reduces cost and improves throughput for non-urgent workloads."
      }
    }
  ],
  "usage": {
    "prompt_tokens": 24,
    "completion_tokens": 36,
    "total_tokens": 60
  }
}
```

## Notes

* Set `stream: true` to receive token deltas as server-sent events; set `stream: "patch"` for [JSON Patch streaming](#json-patch-streaming).
* For the Python SDK helper that consumes patch streams into `PatchEvent` objects, see [JSON Patch Streaming](/json-schema/streaming).
* For model discovery, call [`GET /models`](/api/list-models).
* For auth setup, see [Authentication](/api/authentication).
* For failures, inspect the HTTP status and the `error` object in the response body.


## OpenAPI

````yaml ../openapi/dottxt-openapi.json POST /chat/completions
openapi: 3.1.0
info:
  title: dottxt API
  description: The dottxt API
  version: 1.0.0
servers:
  - url: https://api.dottxt.ai/v1
    description: dottxt API
security: []
tags:
  - name: files
    description: >-
      Upload and manage JSONL files for batch processing.


      Each line in the file should be a JSON object with:

      - `custom_id` - your identifier for tracking the request

      - `method` - HTTP method (POST)

      - `url` - endpoint path (e.g., `/v1/chat/completions`)

      - `body` - the request payload


      [Learn more about the JSONL file format
      →](https://docs.doubleword.ai/batches/jsonl-files)
  - name: batches
    description: >-
      Process large volumes of requests asynchronously.


      Batch processing is ideal when you:

      - Have many requests that don't need immediate responses

      - Want to process data in bulk (e.g., embeddings for a document corpus)

      - Are running offline evaluations or data pipelines


      Choose your completion window: 1 hour or 24 hours. You can track progress,
      cancel in-flight batches, and retry failed requests.


      [Getting started with the Batch API
      →](https://docs.doubleword.ai/batches/getting-started-with-batched-api)
  - name: chat
    description: |-
      Create model responses for chat conversations.

      Supports:
      - **Multi-turn dialogue** with conversation history
      - **System prompts** to control model behavior
      - **Tool calling** for function execution and structured outputs
      - **Streaming** for real-time token delivery
      - **Sampling parameters** like temperature, top_p, and frequency penalties
  - name: embeddings
    description: |-
      Generate vector representations of text.

      Use embeddings for:
      - **Semantic search** - find content by meaning, not just keywords
      - **Clustering** - group similar documents together
      - **Classification** - categorize text based on similarity to examples
      - **Recommendations** - suggest related content
  - name: models
    description: >-
      List and retrieve information about available models.


      Use these endpoints to discover which models you have access to and their
      capabilities.
  - name: responses-api
    description: >-
      Create model responses with enhanced capabilities.


      Open Responses compatible endpoint providing advanced features:


      - **Reasoning models** - Control computational effort with `reasoning`
      parameter

      - **Stateful conversations** - Maintain context across turns with
      `previous_response_id`

      - **Flexible input** - Use simple strings or full message arrays

      - **Text output configuration** - Structured outputs via `text` parameter

      - **Context management** - Handle overflow with `truncation` parameter


      [Open Responses API Reference →](https://www.openresponses.org/reference)
paths:
  /chat/completions:
    post:
      tags:
        - chat
      summary: Create chat completion
      description: >-
        Creates a model response for the given chat conversation.


        The conversation is provided as an array of messages, where each message
        has a `role` (system, user, assistant, or tool) and `content`.


        Set `stream: true` to receive partial responses as server-sent events.
      operationId: chat_completions
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ChatCompletionRequest'
        required: true
      responses:
        '200':
          description: >-
            Chat completion generated successfully. Response framing depends on
            the `stream` parameter and `Accept` header:


            - Default (`stream` unset or `false`): a single JSON
            `ChatCompletionResponse`.

            - `stream: true`: an SSE stream of token deltas.

            - `stream: "patch"`: an NDJSON stream of `JsonPatchOperation`
            records (one per line), or SSE if `Accept: text/event-stream` is
            sent.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ChatCompletionResponse'
            application/x-ndjson:
              schema:
                $ref: '#/components/schemas/JsonPatchOperation'
            text/event-stream:
              schema:
                $ref: '#/components/schemas/JsonPatchOperation'
        '400':
          description: >-
            Invalid request - check that your messages array is properly
            formatted and all required fields are present.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OpenAIErrorResponse'
        '401':
          description: >-
            Invalid or missing API key. Ensure your `Authorization` header is
            set to `Bearer YOUR_API_KEY`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OpenAIErrorResponse'
        '402':
          description: >-
            Insufficient credits. Top up your account to continue making
            requests.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OpenAIErrorResponse'
        '403':
          description: Your API key does not have access to the requested model.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OpenAIErrorResponse'
        '404':
          description: >-
            The specified model does not exist. Use `GET /models` to list
            available models.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OpenAIErrorResponse'
        '429':
          description: Rate limit exceeded. Back off and retry after a short delay.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OpenAIErrorResponse'
        '500':
          description: >-
            An unexpected error occurred. Retry the request or contact support
            if the issue persists.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OpenAIErrorResponse'
      security:
        - BearerAuth: []
components:
  schemas:
    ChatCompletionRequest:
      type: object
      description: Request body for chat completions.
      required:
        - model
        - messages
      properties:
        frequency_penalty:
          type:
            - number
            - 'null'
          format: float
          description: >-
            Number between -2.0 and 2.0. Positive values penalize new tokens
            based on

            their existing frequency in the text so far.
          example: 0
        max_tokens:
          type:
            - integer
            - 'null'
          format: int32
          description: The maximum number of tokens to generate in the chat completion.
          example: 256
        messages:
          type: array
          items:
            $ref: '#/components/schemas/ChatMessage'
          description: A list of messages comprising the conversation so far.
        model:
          type: string
          description: ID of the model to use.
          example: Qwen/Qwen3-30B-A3B-FP8
        'n':
          type:
            - integer
            - 'null'
          format: int32
          description: How many chat completion choices to generate for each input message.
          example: 1
        presence_penalty:
          type:
            - number
            - 'null'
          format: float
          description: >-
            Number between -2.0 and 2.0. Positive values penalize new tokens
            based on

            whether they appear in the text so far.
          example: 0
        stop:
          type:
            - array
            - 'null'
          items:
            type: string
          description: Up to 4 sequences where the API will stop generating further tokens.
        response_format:
          description: >-
            Output format for structured responses. Set to `{"type":
            "json_schema", "json_schema": {...}}` to constrain the response to a
            JSON schema. Required when `stream` is `"patch"`.
        seed:
          type:
            - integer
            - 'null'
          format: int64
          description: >-
            Random seed for sampling. If provided and supported by the model,
            sampling is deterministic.
        stream:
          oneOf:
            - type: boolean
              description: >-
                Set to `true` to receive partial token deltas as Server-Sent
                Events.
            - type: string
              enum:
                - patch
              description: >-
                Set to `"patch"` to stream the structured response
                field-by-field as RFC 6902 JSON Patch `add` operations. Requires
                `response_format` with a JSON schema. Defaults to NDJSON
                framing; send `Accept: text/event-stream` for SSE.
            - type: 'null'
          description: >-
            Streaming mode. `false`/unset returns a single JSON response. `true`
            streams token deltas as SSE. `"patch"` streams one JSON Patch `add`
            per schema field — see the [JSON Patch streaming
            reference](https://docs.doubleword.ai/api/chat-completions#json-patch-streaming).
          example: false
        temperature:
          type:
            - number
            - 'null'
          format: float
          description: What sampling temperature to use, between 0 and 2.
          example: 0.7
        tool_choice:
          description: Controls which (if any) tool is called by the model.
        tools:
          type:
            - array
            - 'null'
          items:
            $ref: '#/components/schemas/Tool'
          description: A list of tools the model may call.
        top_p:
          type:
            - number
            - 'null'
          format: float
          description: >-
            An alternative to sampling with temperature, called nucleus
            sampling.
          example: 1
        user:
          type:
            - string
            - 'null'
          description: A unique identifier representing your end-user.
      example:
        max_tokens: 256
        messages:
          - content: You are a helpful assistant.
            role: system
          - content: What is a doubleword?
            role: user
        model: Qwen/Qwen3-30B-A3B-FP8
        temperature: 0.7
    ChatCompletionResponse:
      type: object
      description: Response from chat completions.
      required:
        - id
        - object
        - created
        - model
        - choices
      properties:
        choices:
          type: array
          items:
            $ref: '#/components/schemas/ChatChoice'
          description: A list of chat completion choices.
        created:
          type: integer
          format: int64
          description: The Unix timestamp of when the chat completion was created.
          example: 1703187200
        id:
          type: string
          description: A unique identifier for the chat completion.
          example: chatcmpl-abc123
        model:
          type: string
          description: The model used for the chat completion.
          example: Qwen/Qwen3-30B-A3B-FP8
        object:
          type: string
          description: The object type, always "chat.completion".
          example: chat.completion
        system_fingerprint:
          type:
            - string
            - 'null'
          description: The system fingerprint of the model.
        usage:
          oneOf:
            - type: 'null'
            - $ref: '#/components/schemas/Usage'
              description: Usage statistics for the completion request.
      example:
        choices:
          - finish_reason: stop
            index: 0
            message:
              content: >-
                A doubleword is a data unit that is twice the size of a standard
                word in computer architecture, typically 32 or 64 bits depending
                on the system.
              role: assistant
        created: 1703187200
        id: chatcmpl-abc123
        model: Qwen/Qwen3-30B-A3B-FP8
        object: chat.completion
        usage:
          completion_tokens: 36
          prompt_tokens: 24
          total_tokens: 60
    JsonPatchOperation:
      type: object
      description: >-
        An RFC 6902 JSON Patch operation, emitted one per line (NDJSON) or per
        SSE event when `stream: "patch"` is set on `/chat/completions`. The
        first record seeds the document root (`path: ""` with `value: {}` for
        object-rooted schemas, `[]` for array-rooted). Subsequent records fill
        in leaf fields and seed nested containers in schema order. Applying the
        ops in order reconstructs the same document a non-streaming request
        would return.
      required:
        - op
        - path
        - value
      properties:
        op:
          type: string
          enum:
            - add
          description: The RFC 6902 operation. Always `"add"` in patch streaming mode.
          example: add
        path:
          type: string
          description: >-
            JSON Pointer to the location being filled in. Empty string for the
            root seed; otherwise a leading `/` followed by the field key (e.g.,
            `/intent`, `/steps/0`, `/address/city`).
          example: /intent
        value:
          description: >-
            The inserted value. For leaf fields, a JSON primitive (string,
            number, boolean, null). For nested objects and arrays, an empty
            container (`{}` or `[]`) that subsequent ops will fill.
      example:
        op: add
        path: /intent
        value: billing
    OpenAIErrorResponse:
      type: object
      description: OpenAI-compatible error response.
      required:
        - error
      properties:
        error:
          $ref: '#/components/schemas/OpenAIError'
          description: The error details.
      example:
        error:
          code: invalid_api_key
          message: Invalid API key provided
          type: authentication_error
    ChatMessage:
      type: object
      description: A message in a chat conversation.
      required:
        - role
      properties:
        content:
          type:
            - string
            - 'null'
          description: The content of the message.
          example: What is a doubleword?
        name:
          type:
            - string
            - 'null'
          description: The name of the author (for function/tool messages).
        role:
          type: string
          description: >-
            The role of the message author (system, user, assistant, tool,
            function).
          example: user
        tool_call_id:
          type:
            - string
            - 'null'
          description: The ID of the tool call this message is responding to.
        tool_calls:
          type:
            - array
            - 'null'
          items:
            $ref: '#/components/schemas/ToolCall'
          description: Tool calls made by the assistant.
      example:
        content: What is a doubleword?
        role: user
    Tool:
      type: object
      description: A tool that the model may call.
      required:
        - type
        - function
      properties:
        function:
          $ref: '#/components/schemas/FunctionDefinition'
          description: The function definition.
        type:
          type: string
          description: The type of tool (currently only "function").
          example: function
      example:
        function:
          description: Get the current weather in a location
          name: get_weather
          parameters:
            properties:
              location:
                description: City name
                type: string
            required:
              - location
            type: object
        type: function
    ChatChoice:
      type: object
      description: A chat completion choice.
      required:
        - index
        - message
      properties:
        finish_reason:
          type:
            - string
            - 'null'
          description: The reason the model stopped generating tokens.
          example: stop
        index:
          type: integer
          format: int32
          description: The index of the choice in the list of choices.
          example: 0
        message:
          $ref: '#/components/schemas/ChatMessage'
          description: The chat completion message generated by the model.
      example:
        finish_reason: stop
        index: 0
        message:
          content: >-
            A doubleword is a data unit that is twice the size of a standard
            word in computer architecture.
          role: assistant
    Usage:
      type: object
      description: Token usage statistics.
      required:
        - prompt_tokens
        - completion_tokens
        - total_tokens
      properties:
        completion_tokens:
          type: integer
          format: int32
          description: Number of tokens in the generated completion.
          example: 36
        prompt_tokens:
          type: integer
          format: int32
          description: Number of tokens in the prompt.
          example: 24
        total_tokens:
          type: integer
          format: int32
          description: Total number of tokens used in the request.
          example: 60
      example:
        completion_tokens: 36
        prompt_tokens: 24
        total_tokens: 60
    OpenAIError:
      type: object
      description: OpenAI-compatible error details.
      required:
        - message
        - type
      properties:
        code:
          type:
            - string
            - 'null'
          description: The error code.
          example: invalid_api_key
        message:
          type: string
          description: The error message.
          example: Invalid API key provided
        param:
          type:
            - string
            - 'null'
          description: The parameter that caused the error, if applicable.
        type:
          type: string
          description: The type of error.
          example: authentication_error
      example:
        code: invalid_api_key
        message: Invalid API key provided
        type: authentication_error
    ToolCall:
      type: object
      description: A tool call made by the model.
      required:
        - id
        - type
        - function
      properties:
        function:
          $ref: '#/components/schemas/FunctionCall'
          description: The function that was called.
        id:
          type: string
          description: The ID of the tool call.
          example: call_abc123
        type:
          type: string
          description: The type of tool (currently only "function").
          example: function
      example:
        function:
          arguments: '{"location": "San Francisco"}'
          name: get_weather
        id: call_abc123
        type: function
    FunctionDefinition:
      type: object
      description: Definition of a function that can be called by the model.
      required:
        - name
      properties:
        description:
          type:
            - string
            - 'null'
          description: A description of what the function does.
          example: Get the current weather in a location
        name:
          type: string
          description: The name of the function.
          example: get_weather
        parameters:
          description: The parameters the function accepts, as a JSON Schema object.
      example:
        description: Get the current weather in a location
        name: get_weather
        parameters:
          properties:
            location:
              description: City name
              type: string
          required:
            - location
          type: object
    FunctionCall:
      type: object
      description: A function call within a tool call.
      required:
        - name
        - arguments
      properties:
        arguments:
          type: string
          description: The arguments to pass to the function, as a JSON string.
          example: '{"location": "San Francisco"}'
        name:
          type: string
          description: The name of the function to call.
          example: get_weather
      example:
        arguments: '{"location": "San Francisco"}'
        name: get_weather
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: API Key
      description: |-
        API key authentication. Include your key in the `Authorization` header:

        ```
        Authorization: Bearer YOUR_API_KEY
        ```

        API keys can be created and managed in the dashboard.

````