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

# Chat Service API

> API reference for managing chat sessions, messages, file uploads, and AI conversations

The Chat Service provides comprehensive endpoints for creating and managing conversational AI interactions. It supports multi-turn dialogues with LLM models and AI agents, file uploads, knowledge base integration, real-time streaming, and audio transcription.

## Chat System Overview

```mermaid theme={null}
sequenceDiagram
    participant User
    participant ChatAPI as Chat API
    participant LLM as LLM/Agent
    participant KB as Knowledge Base
    participant Storage as File Storage

    User->>ChatAPI: Create Chat Session
    ChatAPI-->>User: Session Created

    User->>Storage: Upload Files
    Storage-->>User: File URLs

    User->>ChatAPI: Send Message (with files, KB IDs)
    ChatAPI->>KB: Search Knowledge Bases
    KB-->>ChatAPI: Relevant Context
    ChatAPI->>LLM: Generate Response (streaming)

    loop Streaming
        LLM-->>ChatAPI: Token Chunk
        ChatAPI-->>User: SSE Stream
    end

    LLM-->>ChatAPI: Complete
    ChatAPI-->>User: DONE Signal
```

## Authentication

All endpoints require a valid Bearer token in the Authorization header and appropriate RBAC permissions.

**Required Permissions:**

* `chats:read` - Read chat sessions and messages
* `chats:write` - Create chats and send messages
* `chats:delete` - Delete chat sessions

## Base URL

```
/api/chat
```

## Chat Session Management

### Create Chat Session

Create a new chat session for organizing conversations.

<CodeGroup>
  ```bash curl theme={null}
  curl -X POST {{baseUrl}}/api/chat?org_id=your-org-id \
    -H "Authorization: Bearer YOUR_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
      "title": "Product Design Discussion",
      "status": "ACTIVE",
      "settings": {
        "temperature": 0.7,
        "max_tokens": 2000,
        "top_p": 0.9
      }
    }'
  ```

  ```python python theme={null}
  import requests

  url = "{{baseUrl}}/api/chat"
  headers = {
      "Authorization": "Bearer YOUR_TOKEN",
      "Content-Type": "application/json"
  }
  params = {
      "org_id": "your-org-id"
  }
  data = {
      "title": "Product Design Discussion",
      "status": "ACTIVE",
      "settings": {
          "temperature": 0.7,
          "max_tokens": 2000,
          "top_p": 0.9
      }
  }

  response = requests.post(url, headers=headers, params=params, json=data)
  print(response.json())
  ```

  ```typescript typescript theme={null}
  interface ChatSettings {
    temperature?: number;
    max_tokens?: number;
    top_p?: number;
  }

  interface CreateChatRequest {
    title?: string;
    status?: 'ACTIVE' | 'ARCHIVED' | 'DELETED';
    settings?: ChatSettings;
  }

  const createChat = async (orgId: string, data: CreateChatRequest) => {
    const response = await fetch(`{{baseUrl}}/api/chat?org_id=${orgId}`, {
      method: 'POST',
      headers: {
        'Authorization': 'Bearer YOUR_TOKEN',
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(data),
    });

    return await response.json();
  };

  // Usage
  const chat = await createChat('your-org-id', {
    title: "Product Design Discussion",
    status: "ACTIVE",
    settings: {
      temperature: 0.7,
      max_tokens: 2000,
      top_p: 0.9
    }
  });
  ```

  ```go go theme={null}
  package main

  import (
      "bytes"
      "encoding/json"
      "fmt"
      "net/http"
  )

  type ChatSettings struct {
      Temperature *float64 `json:"temperature,omitempty"`
      MaxTokens   *int     `json:"max_tokens,omitempty"`
      TopP        *float64 `json:"top_p,omitempty"`
  }

  type CreateChatRequest struct {
      Title    *string       `json:"title,omitempty"`
      Status   *string       `json:"status,omitempty"`
      Settings *ChatSettings `json:"settings,omitempty"`
  }

  func createChat(baseURL, orgID, token string, data CreateChatRequest) error {
      url := fmt.Sprintf("%s/api/chat?org_id=%s", baseURL, orgID)

      jsonData, _ := json.Marshal(data)
      req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
      req.Header.Set("Authorization", "Bearer "+token)
      req.Header.Set("Content-Type", "application/json")

      client := &http.Client{}
      resp, err := client.Do(req)
      if err != nil {
          return err
      }
      defer resp.Body.Close()

      fmt.Println("Chat created successfully!")
      return nil
  }

  func main() {
      temp := 0.7
      maxTokens := 2000
      topP := 0.9
      title := "Product Design Discussion"
      status := "ACTIVE"

      data := CreateChatRequest{
          Title:  &title,
          Status: &status,
          Settings: &ChatSettings{
              Temperature: &temp,
              MaxTokens:   &maxTokens,
              TopP:        &topP,
          },
      }

      createChat("{{baseUrl}}", "your-org-id", "YOUR_TOKEN", data)
  }
  ```

  ```json Response theme={null}
  {
    "id": "a1b2c3d4-e5f6-7g8h-9i0j-k1l2m3n4o5p6",
    "message": "Chat session created successfully"
  }
  ```
</CodeGroup>

**Endpoint:** `POST /api/chat`

**Query Parameters:**

| Parameter | Required | Type | Description     |
| --------- | -------- | ---- | --------------- |
| `org_id`  | Yes      | UUID | Organization ID |

**Request Body:**

| Field                  | Type   | Required | Description                               |
| ---------------------- | ------ | -------- | ----------------------------------------- |
| `title`                | string | No       | Chat session title (default: "New Chat")  |
| `status`               | string | No       | Session status: ACTIVE, ARCHIVED, DELETED |
| `settings`             | object | No       | LLM generation settings                   |
| `settings.temperature` | number | No       | Sampling temperature (0.0-1.0)            |
| `settings.max_tokens`  | number | No       | Maximum response tokens                   |
| `settings.top_p`       | number | No       | Nucleus sampling threshold                |

### Get Chat Session

Retrieve a single chat session with all its messages and file uploads.

<CodeGroup>
  ```bash Request theme={null}
  curl -X GET "{{baseUrl}}/api/chat?chat_id=a1b2c3d4-e5f6-7g8h-9i0j-k1l2m3n4o5p6&org_id=your-org-id" \
    -H "Authorization: Bearer YOUR_TOKEN"
  ```

  ```python Python theme={null}
  import requests

  url = "{{baseUrl}}/api/chat"
  headers = {
      "Authorization": "Bearer YOUR_TOKEN"
  }
  params = {
      "chat_id": "a1b2c3d4-e5f6-7g8h-9i0j-k1l2m3n4o5p6",
      "org_id": "your-org-id"
  }

  response = requests.get(url, headers=headers, params=params)
  print(response.json())
  ```

  ```javascript JavaScript theme={null}
  const axios = require('axios');

  const url = "{{baseUrl}}/api/chat";
  const headers = {
      Authorization: "Bearer YOUR_TOKEN"
  };
  const params = {
      chat_id: "a1b2c3d4-e5f6-7g8h-9i0j-k1l2m3n4o5p6",
      org_id: "your-org-id"
  };

  axios.get(url, { headers, params })
      .then(response => console.log(response.data))
      .catch(error => console.error(error));
  ```

  ```json Response theme={null}
  {
    "id": "a1b2c3d4-e5f6-7g8h-9i0j-k1l2m3n4o5p6",
    "title": "Product Design Discussion",
    "status": "ACTIVE",
    "org_id": "your-org-id",
    "user_id": "user-uuid",
    "metadata": {
      "settings": {
        "temperature": 0.7,
        "max_tokens": 2000,
        "top_p": 0.9
      },
      "usage": {
        "input_tokens": 1500,
        "output_tokens": 3200,
        "total_tokens": 4700,
        "cached_tokens": 200
      }
    },
    "settings": {
      "temperature": 0.7,
      "max_tokens": 2000,
      "top_p": 0.9
    },
    "created_at": "2024-01-15T10:30:00Z",
    "updated_at": "2024-01-15T14:25:00Z",
    "messages": [
      {
        "id": "msg-uuid-1",
        "content": "Can you help me design a new product feature?",
        "role": "USER",
        "chat_session_id": "a1b2c3d4-e5f6-7g8h-9i0j-k1l2m3n4o5p6",
        "parent_message_id": null,
        "model_id": "model-uuid",
        "agent_id": null,
        "prompt_data": null,
        "metadata": {
          "knowledge_base_ids": ["kb-uuid-1"]
        },
        "created_at": "2024-01-15T10:31:00Z"
      },
      {
        "id": "msg-uuid-2",
        "content": "I'd be happy to help! Let's start by understanding your requirements...",
        "role": "MODEL",
        "chat_session_id": "a1b2c3d4-e5f6-7g8h-9i0j-k1l2m3n4o5p6",
        "parent_message_id": "msg-uuid-1",
        "model_id": "model-uuid",
        "agent_id": null,
        "prompt_data": null,
        "metadata": {},
        "created_at": "2024-01-15T10:31:15Z"
      }
    ],
    "uploads": [
      {
        "id": "upload-uuid-1",
        "message_id": "msg-uuid-1",
        "filename": "requirements.pdf",
        "file_size": 245760,
        "content_type": "application/pdf",
        "url": "https://storage.googleapis.com/..."
      }
    ]
  }
  ```
</CodeGroup>

**Endpoint:** `GET /api/chat`

**Query Parameters:**

| Parameter | Required | Type | Description     |
| --------- | -------- | ---- | --------------- |
| `chat_id` | Yes      | UUID | Chat session ID |
| `org_id`  | Yes      | UUID | Organization ID |

### List Chat Sessions

Retrieve all chat sessions for the authenticated user.

<CodeGroup>
  ```bash Request theme={null}
  curl -X GET "{{baseUrl}}/api/chat/list?org_id=your-org-id&status=ACTIVE" \
    -H "Authorization: Bearer YOUR_TOKEN"
  ```

  ```python Python theme={null}
  import requests

  url = "{{baseUrl}}/api/chat/list"
  headers = {
      "Authorization": "Bearer YOUR_TOKEN"
  }
  params = {
      "org_id": "your-org-id",
      "status": "ACTIVE"  # Optional filter
  }

  response = requests.get(url, headers=headers, params=params)
  print(response.json())
  ```

  ```javascript JavaScript theme={null}
  const axios = require('axios');

  const url = "{{baseUrl}}/api/chat/list";
  const headers = {
      Authorization: "Bearer YOUR_TOKEN"
  };
  const params = {
      org_id: "your-org-id",
      status: "ACTIVE"  // Optional filter
  };

  axios.get(url, { headers, params })
      .then(response => console.log(response.data))
      .catch(error => console.error(error));
  ```

  ```json Response theme={null}
  [
    {
      "id": "a1b2c3d4-e5f6-7g8h-9i0j-k1l2m3n4o5p6",
      "title": "Product Design Discussion",
      "status": "ACTIVE",
      "org_id": "your-org-id",
      "user_id": "user-uuid",
      "metadata": {
        "settings": {
          "temperature": 0.7,
          "max_tokens": 2000
        }
      },
      "settings": {
        "temperature": 0.7,
        "max_tokens": 2000
      },
      "created_at": "2024-01-15T10:30:00Z",
      "updated_at": "2024-01-15T14:25:00Z"
    },
    {
      "id": "b2c3d4e5-f6g7-8h9i-0j1k-l2m3n4o5p6q7",
      "title": "Marketing Strategy",
      "status": "ACTIVE",
      "org_id": "your-org-id",
      "user_id": "user-uuid",
      "metadata": {},
      "settings": null,
      "created_at": "2024-01-14T09:15:00Z",
      "updated_at": "2024-01-14T16:42:00Z"
    }
  ]
  ```
</CodeGroup>

**Endpoint:** `GET /api/chat/list`

**Query Parameters:**

| Parameter | Required | Type   | Description                                 |
| --------- | -------- | ------ | ------------------------------------------- |
| `org_id`  | Yes      | UUID   | Organization ID                             |
| `status`  | No       | string | Filter by status: ACTIVE, ARCHIVED, DELETED |

### Update Chat Session

Update an existing chat session's title, status, or settings.

<CodeGroup>
  ```bash Request theme={null}
  curl -X PUT "{{baseUrl}}/api/chat?chat_id=a1b2c3d4-e5f6-7g8h-9i0j-k1l2m3n4o5p6&org_id=your-org-id" \
    -H "Authorization: Bearer YOUR_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
      "title": "Updated Product Design Discussion",
      "status": "ACTIVE",
      "settings": {
        "temperature": 0.8,
        "max_tokens": 3000
      }
    }'
  ```

  ```python Python theme={null}
  import requests

  url = "{{baseUrl}}/api/chat"
  headers = {
      "Authorization": "Bearer YOUR_TOKEN",
      "Content-Type": "application/json"
  }
  params = {
      "chat_id": "a1b2c3d4-e5f6-7g8h-9i0j-k1l2m3n4o5p6",
      "org_id": "your-org-id"
  }
  data = {
      "title": "Updated Product Design Discussion",
      "status": "ACTIVE",
      "settings": {
          "temperature": 0.8,
          "max_tokens": 3000
      }
  }

  response = requests.put(url, headers=headers, params=params, json=data)
  print(response.json())
  ```

  ```javascript JavaScript theme={null}
  const axios = require('axios');

  const url = "{{baseUrl}}/api/chat";
  const headers = {
      Authorization: "Bearer YOUR_TOKEN",
      "Content-Type": "application/json"
  };
  const params = {
      chat_id: "a1b2c3d4-e5f6-7g8h-9i0j-k1l2m3n4o5p6",
      org_id: "your-org-id"
  };
  const data = {
      title: "Updated Product Design Discussion",
      status: "ACTIVE",
      settings: {
          temperature: 0.8,
          max_tokens: 3000
      }
  };

  axios.put(url, data, { headers, params })
      .then(response => console.log(response.data))
      .catch(error => console.error(error));
  ```

  ```json Response theme={null}
  {
    "id": "a1b2c3d4-e5f6-7g8h-9i0j-k1l2m3n4o5p6",
    "message": "Chat session updated successfully"
  }
  ```
</CodeGroup>

**Endpoint:** `PUT /api/chat`

**Query Parameters:**

| Parameter | Required | Type | Description     |
| --------- | -------- | ---- | --------------- |
| `chat_id` | Yes      | UUID | Chat session ID |
| `org_id`  | Yes      | UUID | Organization ID |

**Request Body:**

| Field      | Type   | Required | Description                           |
| ---------- | ------ | -------- | ------------------------------------- |
| `title`    | string | No       | New chat title                        |
| `status`   | string | No       | New status: ACTIVE, ARCHIVED, DELETED |
| `settings` | object | No       | Updated LLM settings                  |

### Delete Chat Session

Delete a single chat session and all its messages.

<CodeGroup>
  ```bash Request theme={null}
  curl -X DELETE "{{baseUrl}}/api/chat/delete_session?session_id=a1b2c3d4-e5f6-7g8h-9i0j-k1l2m3n4o5p6" \
    -H "Authorization: Bearer YOUR_TOKEN"
  ```

  ```python Python theme={null}
  import requests

  url = "{{baseUrl}}/api/chat/delete_session"
  headers = {
      "Authorization": "Bearer YOUR_TOKEN"
  }
  params = {
      "session_id": "a1b2c3d4-e5f6-7g8h-9i0j-k1l2m3n4o5p6"
  }

  response = requests.delete(url, headers=headers, params=params)
  print(response.json())
  ```

  ```javascript JavaScript theme={null}
  const axios = require('axios');

  const url = "{{baseUrl}}/api/chat/delete_session";
  const headers = {
      Authorization: "Bearer YOUR_TOKEN"
  };
  const params = {
      session_id: "a1b2c3d4-e5f6-7g8h-9i0j-k1l2m3n4o5p6"
  };

  axios.delete(url, { headers, params })
      .then(response => console.log(response.data))
      .catch(error => console.error(error));
  ```

  ```json Response theme={null}
  {
    "message": "Chat session deleted successfully"
  }
  ```
</CodeGroup>

**Endpoint:** `DELETE /api/chat/delete_session`

**Query Parameters:**

| Parameter    | Required | Type | Description               |
| ------------ | -------- | ---- | ------------------------- |
| `session_id` | Yes      | UUID | Chat session ID to delete |

### Bulk Delete Chat Sessions

Delete multiple chat sessions in a single request.

<CodeGroup>
  ```bash Request theme={null}
  curl -X POST "{{baseUrl}}/api/chat/bulk_delete_sessions" \
    -H "Authorization: Bearer YOUR_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
      "chat_ids": [
        "a1b2c3d4-e5f6-7g8h-9i0j-k1l2m3n4o5p6",
        "b2c3d4e5-f6g7-8h9i-0j1k-l2m3n4o5p6q7",
        "c3d4e5f6-g7h8-9i0j-1k2l-m3n4o5p6q7r8"
      ]
    }'
  ```

  ```python Python theme={null}
  import requests

  url = "{{baseUrl}}/api/chat/bulk_delete_sessions"
  headers = {
      "Authorization": "Bearer YOUR_TOKEN",
      "Content-Type": "application/json"
  }
  data = {
      "chat_ids": [
          "a1b2c3d4-e5f6-7g8h-9i0j-k1l2m3n4o5p6",
          "b2c3d4e5-f6g7-8h9i-0j1k-l2m3n4o5p6q7",
          "c3d4e5f6-g7h8-9i0j-1k2l-m3n4o5p6q7r8"
      ]
  }

  response = requests.post(url, headers=headers, json=data)
  print(response.json())
  ```

  ```typescript TypeScript theme={null}
  interface BulkDeleteRequest {
    chat_ids: string[];
  }

  const bulkDeleteChats = async (chatIds: string[]) => {
    const response = await fetch('{{baseUrl}}/api/chat/bulk_delete_sessions', {
      method: 'POST',
      headers: {
        'Authorization': 'Bearer YOUR_TOKEN',
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ chat_ids: chatIds }),
    });

    return await response.json();
  };

  // Usage
  const result = await bulkDeleteChats([
    "a1b2c3d4-e5f6-7g8h-9i0j-k1l2m3n4o5p6",
    "b2c3d4e5-f6g7-8h9i-0j1k-l2m3n4o5p6q7",
    "c3d4e5f6-g7h8-9i0j-1k2l-m3n4o5p6q7r8"
  ]);
  ```

  ```json Response theme={null}
  {
    "message": "3 chat sessions deleted successfully"
  }
  ```
</CodeGroup>

**Endpoint:** `POST /api/chat/bulk_delete_sessions`

**Request Body:**

| Field      | Type  | Required | Description                           |
| ---------- | ----- | -------- | ------------------------------------- |
| `chat_ids` | array | Yes      | Array of chat session UUIDs to delete |

## Message Operations

### Send Message

Send a message in a chat session and receive a streaming AI response. This is the primary endpoint for conversational interactions.

<CodeGroup>
  ```bash curl theme={null}
  curl -X POST "{{baseUrl}}/api/chat/send_message?org_id=your-org-id&model_id=model-uuid&chat_id=chat-uuid" \
    -H "Authorization: Bearer YOUR_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
      "content": "What are the best practices for API design?",
      "thinking": false,
      "file_uploads": ["upload-uuid-1", "upload-uuid-2"],
      "knowledge_base_ids": ["kb-uuid-1", "kb-uuid-2"]
    }'
  ```

  ```python Python theme={null}
  import requests

  url = "{{baseUrl}}/api/chat/send_message"
  headers = {
      "Authorization": "Bearer YOUR_TOKEN",
      "Content-Type": "application/json"
  }
  params = {
      "org_id": "your-org-id",
      "model_id": "model-uuid",
      "chat_id": "chat-uuid",  # Optional: creates new chat if not provided
      "instruction_id": "prompt-uuid",  # Optional
      "temperature": 0.7,  # Optional: overrides session settings
      "max_tokens": 2000,  # Optional
      "top_p": 0.9  # Optional
  }
  data = {
      "content": "What are the best practices for API design?",
      "thinking": False,
      "file_uploads": ["upload-uuid-1", "upload-uuid-2"],
      "knowledge_base_ids": ["kb-uuid-1", "kb-uuid-2"]
  }

  # Stream response
  response = requests.post(url, headers=headers, params=params, json=data, stream=True)

  for line in response.iter_lines():
      if line:
          decoded_line = line.decode('utf-8')
          if decoded_line.startswith('data: '):
              print(decoded_line[6:])  # Remove 'data: ' prefix
  ```

  ```typescript TypeScript theme={null}
  interface MessageCreate {
    content: string;
    thinking?: boolean;
    file_uploads?: string[];
    knowledge_base_ids?: string[];
  }

  interface SendMessageParams {
    org_id: string;
    model_id?: string;
    agent_id?: string;
    chat_id?: string;
    instruction_id?: string;
    temperature?: number;
    max_tokens?: number;
    top_p?: number;
  }

  const sendMessage = async (
    params: SendMessageParams,
    message: MessageCreate
  ) => {
    const queryString = new URLSearchParams(
      params as Record<string, string>
    ).toString();

    const response = await fetch(
      `{{baseUrl}}/api/chat/send_message?${queryString}`,
      {
        method: 'POST',
        headers: {
          'Authorization': 'Bearer YOUR_TOKEN',
          'Content-Type': 'application/json',
        },
        body: JSON.stringify(message),
      }
    );

    const reader = response.body?.getReader();
    const decoder = new TextDecoder();

    while (true) {
      const { value, done } = await reader!.read();
      if (done) break;

      const chunk = decoder.decode(value);
      const lines = chunk.split('\n');

      for (const line of lines) {
        if (line.startsWith('data: ')) {
          const data = JSON.parse(line.slice(6));

          if (data.message === 'DONE') {
            console.log('Stream complete');
            break;
          }

          if (data.error) {
            console.error('Error:', data.error);
            break;
          }

          if (data.type === 'reasoning') {
            console.log('Reasoning:', data.message);
          } else if (data.message) {
            console.log('Token:', data.message);
          }
        }
      }
    }
  };

  // Usage with model
  await sendMessage(
    {
      org_id: "your-org-id",
      model_id: "model-uuid",
      chat_id: "chat-uuid",
      temperature: 0.7
    },
    {
      content: "What are the best practices for API design?",
      thinking: false,
      knowledge_base_ids: ["kb-uuid-1"]
    }
  );

  // Usage with agent
  await sendMessage(
    {
      org_id: "your-org-id",
      agent_id: "agent-uuid",
      chat_id: "chat-uuid"
    },
    {
      content: "Help me debug this code"
    }
  );
  ```

  ```go go theme={null}
  package main

  import (
      "bufio"
      "encoding/json"
      "fmt"
      "net/http"
      "strings"
  )

  type MessageCreate struct {
      Content          string   `json:"content"`
      Thinking         bool     `json:"thinking"`
      FileUploads      []string `json:"file_uploads,omitempty"`
      KnowledgeBaseIDs []string `json:"knowledge_base_ids,omitempty"`
  }

  type StreamData struct {
      Message   string `json:"message,omitempty"`
      Error     string `json:"error,omitempty"`
      Type      string `json:"type,omitempty"`
      MediaData map[string]interface{} `json:"media,omitempty"`
  }

  func sendMessage(baseURL, orgID, modelID, chatID, token string, msg MessageCreate) error {
      url := fmt.Sprintf(
          "%s/api/chat/send_message?org_id=%s&model_id=%s&chat_id=%s",
          baseURL, orgID, modelID, chatID,
      )

      jsonData, _ := json.Marshal(msg)
      req, _ := http.NewRequest("POST", url, strings.NewReader(string(jsonData)))
      req.Header.Set("Authorization", "Bearer "+token)
      req.Header.Set("Content-Type", "application/json")

      client := &http.Client{}
      resp, err := client.Do(req)
      if err != nil {
          return err
      }
      defer resp.Body.Close()

      // Read streaming response
      scanner := bufio.NewScanner(resp.Body)
      for scanner.Scan() {
          line := scanner.Text()
          if strings.HasPrefix(line, "data: ") {
              data := strings.TrimPrefix(line, "data: ")

              var streamData StreamData
              if err := json.Unmarshal([]byte(data), &streamData); err == nil {
                  if streamData.Message == "DONE" {
                      fmt.Println("\nStream complete")
                      break
                  }
                  if streamData.Error != "" {
                      fmt.Printf("Error: %s\n", streamData.Error)
                      break
                  }
                  if streamData.Type == "reasoning" {
                      fmt.Printf("[Reasoning] %s\n", streamData.Message)
                  } else if streamData.Message != "" {
                      fmt.Print(streamData.Message)
                  }
              }
          }
      }

      return scanner.Err()
  }

  func main() {
      msg := MessageCreate{
          Content:          "What are the best practices for API design?",
          Thinking:         false,
          KnowledgeBaseIDs: []string{"kb-uuid-1"},
      }

      sendMessage("{{baseUrl}}", "your-org-id", "model-uuid", "chat-uuid", "YOUR_TOKEN", msg)
  }
  ```

  ```text Streaming Response Format theme={null}
  data: {"message": "API"}
  data: {"message": " design"}
  data: {"message": " best"}
  data: {"message": " practices"}
  data: {"message": " include"}
  data: {"message": "..."}
  data: {"message": "DONE"}

  # With reasoning enabled
  data: {"type": "reasoning", "message": "Let me think about this systematically..."}
  data: {"message": "Based"}
  data: {"message": " on"}
  data: {"message": "..."}

  # Image generation
  data: {"media": {"type": "image", "progress": 0.5, "successful": false}}
  data: {"media": {"type": "image", "progress": 1.0, "successful": true, "url": "https://..."}}
  data: {"message": "DONE"}

  # Error handling
  data: {"error": "LLM provider openai is not configured correctly. Please contact support."}
  ```
</CodeGroup>

**Endpoint:** `POST /api/chat/send_message`

**Query Parameters:**

| Parameter        | Required    | Type  | Description                                       |
| ---------------- | ----------- | ----- | ------------------------------------------------- |
| `org_id`         | Yes         | UUID  | Organization ID                                   |
| `model_id`       | Conditional | UUID  | LLM model ID (required if agent\_id not provided) |
| `agent_id`       | Conditional | UUID  | Agent ID (required if model\_id not provided)     |
| `chat_id`        | No          | UUID  | Chat session ID (creates new if not provided)     |
| `instruction_id` | No          | UUID  | Prompt/instruction ID to guide response           |
| `temperature`    | No          | float | Override temperature (0.0-1.0)                    |
| `max_tokens`     | No          | int   | Override max response tokens                      |
| `top_p`          | No          | float | Override nucleus sampling (0.0-1.0)               |

**Request Body:**

| Field                | Type    | Required | Description                                   |
| -------------------- | ------- | -------- | --------------------------------------------- |
| `content`            | string  | Yes      | Message content/question                      |
| `thinking`           | boolean | No       | Enable reasoning mode (for compatible models) |
| `file_uploads`       | array   | No       | Array of upload UUIDs to attach               |
| `knowledge_base_ids` | array   | No       | Array of KB UUIDs to search                   |

**Response Format:**

Server-Sent Events (SSE) stream with the following data formats:

| Type      | Format                                    | Description               |
| --------- | ----------------------------------------- | ------------------------- |
| Token     | `{"message": "text"}`                     | Regular text token        |
| Reasoning | `{"type": "reasoning", "message": "..."}` | Reasoning step            |
| Image     | `{"media": {...}}`                        | Image generation progress |
| Video     | `{"media": {...}}`                        | Video generation progress |
| Complete  | `{"message": "DONE"}`                     | Stream finished           |
| Error     | `{"error": "message"}`                    | Error occurred            |

**Features:**

* **Auto-Chat Creation**: Creates new chat if chat\_id not provided
* **Auto-Title Generation**: Generates meaningful title for new chats
* **Knowledge Base Search**: Searches specified KBs and enhances prompt
* **File Content Extraction**: Extracts text from uploaded files
* **Billing Integration**: Tracks token usage and credits
* **WebSocket Broadcasting**: Broadcasts title updates
* **Firebase Sync**: Syncs chat updates to Firebase
* **Model Feature Detection**: Automatically handles text/image/video generation
* **Error Recovery**: Gracefully handles LLM provider errors

## File Upload Operations

### Upload File

Upload a file to be attached to chat messages.

<CodeGroup>
  ```bash curl theme={null}
  curl -X POST "{{baseUrl}}/api/chat/upload_file?org_id=your-org-id&chat_id=chat-uuid" \
    -H "Authorization: Bearer YOUR_TOKEN" \
    -F "file=@/path/to/document.pdf"
  ```

  ```python Python theme={null}
  import requests

  url = "{{baseUrl}}/api/chat/upload_file"
  headers = {
      "Authorization": "Bearer YOUR_TOKEN"
  }
  params = {
      "org_id": "your-org-id",
      "chat_id": "chat-uuid"  # Optional
  }
  files = {
      "file": open("document.pdf", "rb")
  }

  response = requests.post(url, headers=headers, params=params, files=files)
  print(response.json())
  ```

  ```typescript TypeScript theme={null}
  const uploadFile = async (
    orgId: string,
    file: File,
    chatId?: string
  ) => {
    const formData = new FormData();
    formData.append('file', file);

    const params = new URLSearchParams({ org_id: orgId });
    if (chatId) params.append('chat_id', chatId);

    const response = await fetch(
      `{{baseUrl}}/api/chat/upload_file?${params.toString()}`,
      {
        method: 'POST',
        headers: {
          'Authorization': 'Bearer YOUR_TOKEN',
        },
        body: formData,
      }
    );

    return await response.json();
  };

  // Usage
  const fileInput = document.getElementById('file') as HTMLInputElement;
  const file = fileInput.files[0];

  const result = await uploadFile('your-org-id', file, 'chat-uuid');
  console.log('Upload ID:', result.id);
  console.log('File URL:', result.url);
  ```

  ```go go theme={null}
  package main

  import (
      "bytes"
      "fmt"
      "io"
      "mime/multipart"
      "net/http"
      "os"
  )

  func uploadFile(baseURL, orgID, chatID, token, filePath string) error {
      file, err := os.Open(filePath)
      if err != nil {
          return err
      }
      defer file.Close()

      body := &bytes.Buffer{}
      writer := multipart.NewWriter(body)

      part, err := writer.CreateFormFile("file", filePath)
      if err != nil {
          return err
      }

      io.Copy(part, file)
      writer.Close()

      url := fmt.Sprintf(
          "%s/api/chat/upload_file?org_id=%s&chat_id=%s",
          baseURL, orgID, chatID,
      )

      req, _ := http.NewRequest("POST", url, body)
      req.Header.Set("Authorization", "Bearer "+token)
      req.Header.Set("Content-Type", writer.FormDataContentType())

      client := &http.Client{}
      resp, err := client.Do(req)
      if err != nil {
          return err
      }
      defer resp.Body.Close()

      fmt.Println("File uploaded successfully!")
      return nil
  }

  func main() {
      uploadFile("{{baseUrl}}", "your-org-id", "chat-uuid", "YOUR_TOKEN", "document.pdf")
  }
  ```

  ```json Response theme={null}
  {
    "id": "upload-uuid",
    "url": "https://storage.googleapis.com/bucket/org-id/chat-id/file.pdf?signature=..."
  }
  ```
</CodeGroup>

**Endpoint:** `POST /api/chat/upload_file`

**Query Parameters:**

| Parameter | Required | Type | Description                             |
| --------- | -------- | ---- | --------------------------------------- |
| `org_id`  | Yes      | UUID | Organization ID                         |
| `chat_id` | No       | UUID | Chat session ID (for organized storage) |

**Request Body:**

Multipart form data with file field.

**Response:**

| Field | Type   | Description                             |
| ----- | ------ | --------------------------------------- |
| `id`  | UUID   | Upload record ID (use in send\_message) |
| `url` | string | Presigned URL for file access (7 days)  |

**Supported File Types:**

* Documents: PDF, TXT, DOCX, XLSX, CSV, MD
* Images: JPG, PNG, GIF, WebP, SVG
* Audio: MP3, WAV, M4A, OGG, FLAC
* Video: MP4, WebM, MOV, AVI

**Storage:**

* Files stored in GCP Cloud Storage
* Organized by: `{org_id}/{chat_id}/{filename}`
* Presigned URLs expire in 7 days
* Content extraction for compatible formats

## Audio Operations

### Transcribe Audio

Convert audio files or raw audio data to text.

<CodeGroup>
  ```bash curl theme={null}
  curl -X POST "{{baseUrl}}/api/chat/transcribe?language=en-US" \
    -H "Authorization: Bearer YOUR_TOKEN" \
    -F "file=@/path/to/audio.mp3"
  ```

  ```python Python theme={null}
  import requests

  url = "{{baseUrl}}/api/chat/transcribe"
  headers = {
      "Authorization": "Bearer YOUR_TOKEN"
  }
  params = {
      "language": "en-US"  # Optional, default: en-US
  }
  files = {
      "file": open("audio.mp3", "rb")
  }

  response = requests.post(url, headers=headers, params=params, files=files)
  result = response.json()
  print(result["text"])
  ```

  ```typescript TypeScript theme={null}
  const transcribeAudio = async (audioFile: File, language = 'en-US') => {
    const formData = new FormData();
    formData.append('file', audioFile);

    const response = await fetch(
      `{{baseUrl}}/api/chat/transcribe?language=${language}`,
      {
        method: 'POST',
        headers: {
          'Authorization': 'Bearer YOUR_TOKEN',
        },
        body: formData,
      }
    );

    return await response.json();
  };

  // Usage with file input
  const audioInput = document.getElementById('audio') as HTMLInputElement;
  const audioFile = audioInput.files[0];

  const result = await transcribeAudio(audioFile, 'en-US');
  console.log('Transcribed text:', result.text);

  // Use transcribed text in chat
  await sendMessage(
    { org_id: 'your-org-id', model_id: 'model-uuid' },
    { content: result.text }
  );
  ```

  ```go go theme={null}
  package main

  import (
      "bytes"
      "encoding/json"
      "fmt"
      "io"
      "mime/multipart"
      "net/http"
      "os"
  )

  type TranscribeResponse struct {
      Text   string `json:"text"`
      Status string `json:"status"`
  }

  func transcribeAudio(baseURL, token, filePath, language string) (string, error) {
      file, err := os.Open(filePath)
      if err != nil {
          return "", err
      }
      defer file.Close()

      body := &bytes.Buffer{}
      writer := multipart.NewWriter(body)

      part, err := writer.CreateFormFile("file", filePath)
      if err != nil {
          return "", err
      }

      io.Copy(part, file)
      writer.Close()

      url := fmt.Sprintf("%s/api/chat/transcribe?language=%s", baseURL, language)
      req, _ := http.NewRequest("POST", url, body)
      req.Header.Set("Authorization", "Bearer "+token)
      req.Header.Set("Content-Type", writer.FormDataContentType())

      client := &http.Client{}
      resp, err := client.Do(req)
      if err != nil {
          return "", err
      }
      defer resp.Body.Close()

      var result TranscribeResponse
      json.NewDecoder(resp.Body).Decode(&result)

      return result.Text, nil
  }

  func main() {
      text, err := transcribeAudio("{{baseUrl}}", "YOUR_TOKEN", "audio.mp3", "en-US")
      if err != nil {
          fmt.Printf("Error: %v\n", err)
          return
      }
      fmt.Printf("Transcribed: %s\n", text)
  }
  ```

  ```json Response theme={null}
  {
    "text": "Hello, this is a test of the audio transcription service. The quick brown fox jumps over the lazy dog.",
    "status": "success"
  }
  ```
</CodeGroup>

**Endpoint:** `POST /api/chat/transcribe`

**Query Parameters:**

| Parameter  | Required | Type   | Description                      |
| ---------- | -------- | ------ | -------------------------------- |
| `language` | No       | string | Language code (default: "en-US") |

**Request Body:**

Multipart form data with file field, OR raw bytes with content\_type parameter.

**Supported Languages:**

* `en-US` - English (US)
* `en-GB` - English (UK)
* `es-ES` - Spanish
* `fr-FR` - French
* `de-DE` - German
* `it-IT` - Italian
* `pt-BR` - Portuguese (Brazil)
* `ja-JP` - Japanese
* `ko-KR` - Korean
* `zh-CN` - Chinese (Simplified)

**Supported Audio Formats:**

* MP3
* WAV
* M4A
* OGG
* FLAC
* WebM

## Prompt Operations

### Generate Prompts

Generate AI-powered prompts based on input text with streaming response.

<CodeGroup>
  ```bash curl theme={null}
  curl -X POST "{{baseUrl}}/api/chat/prompt" \
    -H "Authorization: Bearer YOUR_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
      "text": "artificial intelligence in healthcare",
      "num_prompts": 3,
      "prompt_type": "creative",
      "model": "chat"
    }'
  ```

  ```python Python theme={null}
  import requests

  url = "{{baseUrl}}/api/chat/prompt"
  headers = {
      "Authorization": "Bearer YOUR_TOKEN",
      "Content-Type": "application/json"
  }
  data = {
      "text": "artificial intelligence in healthcare",
      "num_prompts": 3,
      "prompt_type": "creative",  # creative, task, question, continuation
      "model": "chat"  # chat or reason
  }

  response = requests.post(url, headers=headers, json=data, stream=True)

  for line in response.iter_lines():
      if line:
          decoded = line.decode('utf-8')
          if decoded.startswith('data: '):
              import json
              data = json.loads(decoded[6:])
              if data.get('content') == 'DONE':
                  print('\n--- Complete ---')
              else:
                  print(data.get('content'), end='')
  ```

  ```typescript TypeScript theme={null}
  interface PromptRequest {
    text: string;
    num_prompts?: number;
    prompt_type?: 'creative' | 'task' | 'question' | 'continuation';
    model?: 'chat' | 'reason';
  }

  const generatePrompts = async (request: PromptRequest) => {
    const response = await fetch('{{baseUrl}}/api/chat/prompt', {
      method: 'POST',
      headers: {
        'Authorization': 'Bearer YOUR_TOKEN',
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        num_prompts: 1,
        prompt_type: 'task',
        model: 'chat',
        ...request,
      }),
    });

    const reader = response.body?.getReader();
    const decoder = new TextDecoder();
    let fullPrompt = '';

    while (true) {
      const { value, done } = await reader!.read();
      if (done) break;

      const chunk = decoder.decode(value);
      const lines = chunk.split('\n');

      for (const line of lines) {
        if (line.startsWith('data: ')) {
          const data = JSON.parse(line.slice(6));

          if (data.content === 'DONE') {
            console.log('\n--- Prompt Generation Complete ---');
            return fullPrompt;
          }

          if (data.error) {
            throw new Error(data.error);
          }

          fullPrompt += data.content;
          console.log(data.content);
        }
      }
    }

    return fullPrompt;
  };

  // Usage
  const prompt = await generatePrompts({
    text: "artificial intelligence in healthcare",
    num_prompts: 3,
    prompt_type: "creative"
  });
  ```

  ```json Streaming Response theme={null}
  data: {"content": "1."}
  data: {"content": " Explore"}
  data: {"content": " the"}
  data: {"content": " ethical"}
  data: {"content": " implications"}
  data: {"content": " of"}
  data: {"content": " AI-powered"}
  data: {"content": " diagnosis"}
  data: {"content": "\n\n2."}
  data: {"content": " How"}
  data: {"content": " can"}
  data: {"content": " machine"}
  data: {"content": " learning"}
  data: {"content": "..."}
  data: {"content": "DONE"}
  ```
</CodeGroup>

**Endpoint:** `POST /api/chat/prompt`

**Request Body:**

| Field         | Type   | Required | Description                                                  |
| ------------- | ------ | -------- | ------------------------------------------------------------ |
| `text`        | string | Yes      | Input text to generate prompts from                          |
| `num_prompts` | number | No       | Number of prompts to generate (default: 1)                   |
| `prompt_type` | string | No       | Type: creative, task, question, continuation (default: task) |
| `model`       | string | No       | Model: chat, reason (default: chat)                          |

**Response:**

Server-Sent Events stream with format:

```json theme={null}
data: {"content": "token"}
data: {"content": "DONE"}
```

## Knowledge Base Operations

### Get Available Knowledge Bases

Retrieve knowledge bases available for chat integration.

<CodeGroup>
  ```bash Request theme={null}
  curl -X GET "{{baseUrl}}/api/chat/available_knowledge_bases?org_id=your-org-id" \
    -H "Authorization: Bearer YOUR_TOKEN"
  ```

  ```python Python theme={null}
  import requests

  url = "{{baseUrl}}/api/chat/available_knowledge_bases"
  headers = {
      "Authorization": "Bearer YOUR_TOKEN"
  }
  params = {
      "org_id": "your-org-id"
  }

  response = requests.get(url, headers=headers, params=params)
  knowledge_bases = response.json()

  # Use in chat
  kb_ids = [kb["id"] for kb in knowledge_bases[:2]]  # Use first 2 KBs
  ```

  ```javascript JavaScript theme={null}
  const getAvailableKBs = async (orgId) => {
    const response = await fetch(
      `{{baseUrl}}/api/chat/available_knowledge_bases?org_id=${orgId}`,
      {
        headers: {
          'Authorization': 'Bearer YOUR_TOKEN',
        },
      }
    );

    return await response.json();
  };

  // Usage
  const kbs = await getAvailableKBs('your-org-id');
  console.log('Available Knowledge Bases:', kbs);

  // Use in message
  const kbIds = kbs.map(kb => kb.id).slice(0, 2);
  ```

  ```json Response theme={null}
  [
    {
      "id": "kb-uuid-1",
      "name": "Product Documentation",
      "description": "Comprehensive product documentation and guides",
      "chunk_count": 1250,
      "created_at": "2024-01-10T08:00:00Z"
    },
    {
      "id": "kb-uuid-2",
      "name": "Customer FAQs",
      "description": "Frequently asked questions from customers",
      "chunk_count": 340,
      "created_at": "2024-01-12T10:30:00Z"
    }
  ]
  ```
</CodeGroup>

**Endpoint:** `GET /api/chat/available_knowledge_bases`

**Query Parameters:**

| Parameter | Required | Type | Description     |
| --------- | -------- | ---- | --------------- |
| `org_id`  | Yes      | UUID | Organization ID |

## Error Responses

| Status Code | Description           | Example                            |
| ----------- | --------------------- | ---------------------------------- |
| 400         | Bad Request           | Missing required parameter         |
| 401         | Unauthorized          | Invalid or missing token           |
| 402         | Payment Required      | Insufficient credits               |
| 403         | Forbidden             | Insufficient permissions           |
| 404         | Not Found             | Chat session or resource not found |
| 500         | Internal Server Error | Server-side error                  |

**Error Response Format:**

```json theme={null}
{
  "detail": "Error message describing what went wrong"
}
```

**Common Error Messages:**

```json theme={null}
// Insufficient credits
{
  "detail": "Insufficient credits to use this model."
}

// Model/Agent required
{
  "detail": "Either model_id or agent_id must be provided"
}

// Chat not found
{
  "detail": "Chat session not found"
}

// LLM provider error
{
  "detail": "LLM provider openai is not configured correctly. Please contact support."
}
```

## Implementation Notes

### Streaming Response Handling

All streaming endpoints use Server-Sent Events (SSE) format:

```javascript theme={null}
// Browser example
const evtSource = new EventSource('/api/chat/send_message?...');

evtSource.onmessage = (event) => {
  const data = JSON.parse(event.data);

  if (data.message === 'DONE') {
    evtSource.close();
    return;
  }

  console.log(data.message);
};

evtSource.onerror = (error) => {
  console.error('Stream error:', error);
  evtSource.close();
};
```

### Billing Integration

Every chat interaction is billed:

1. **HOLD** created at message start (qty=1)
2. Tokens counted during generation
3. **DEBIT** finalized with actual token usage
4. Usage metadata updated in chat session

**Token Calculation:**

```python theme={null}
weighted_total = (input_tokens * input_ratio) + (output_tokens * output_ratio)
```

### File Content Extraction

Files are automatically processed:

* **Text files**: Content extracted and appended to prompt
* **Images**: Passed to vision-capable models
* **Documents**: Text extraction for PDF, DOCX, etc.
* **DeepSeek models**: Special handling for file content

### Knowledge Base Integration

KB search happens automatically:

1. Semantic search on user query
2. Top N chunks retrieved (configurable, default: 10)
3. Context injected into prompt
4. LLM generates KB-aware response

**Search Parameters:**

* `limit`: Number of chunks (default: 10)
* `score_threshold`: Minimum similarity (default: 0.1)

### Auto-Title Generation

For new chats:

1. Wait for first AI response
2. Generate title using LLM
3. Update database
4. Broadcast via WebSocket
5. Sync to Firebase

### Model Feature Detection

System automatically detects model capabilities:

* **Text models**: Standard chat
* **Image models**: Image generation with progress
* **Video models**: Video generation with GCP upload
* **Vision models**: Image analysis

### Agent Integration

When using agents:

1. Agent must be active
2. Request sent to agent runtime
3. Response streamed back
4. Token usage tracked from Agno session

## Rate Limiting

Rate limits enforced via feature flags:

* `daily_chat_limit`: Daily message limit
* `file_upload`: File upload quota
* `chat_uploads`: Chat-specific upload quota

## Next Steps

Explore related APIs and features:

* [**Knowledge Base Service**](/pages/api-reference/kb-service) - Manage knowledge bases
* [**Agents Service**](/pages/api-reference/agents-service) - Create and deploy agents
* [**LLM Service**](/pages/api-reference/llm-service) - Manage LLM models
* [**WebSocket Service**](/pages/api-reference/ws-service) - Real-time updates

Ready to start building? Check out our [**Chat Concepts**](/pages/concepts/chat) guide or [**Getting Started**](/pages/getting-started/quickstart) tutorial.
