Skip to main content
The Trellis chat API enables natural language conversations with your databases. Messages are sent via POST and responses stream back using Server-Sent Events (SSE) for real-time display.

How it works

Server-Sent Events (SSE)

When you send a chat message, the response is a stream of events. Each event has a type and JSON data payload:
event: <event_type>
data: <json_payload>

Event types

EventDescription
chat_metadataContains the chat ID. Only sent when creating a new chat.
processingStatus updates while the AI is working. Use to show loading indicators.
visualizationSent when a chart or graph is generated. Contains an ID for retrieval.
messageThe final response from the AI. This is the primary content to display.
errorAn error occurred during processing.

Example event stream

event: chat_metadata
data: {"id": "chat_abc123"}

event: processing
data: {"status": "thinking"}

event: processing
data: {"status": "analyzing"}

event: visualization
data: {"id": "viz_xyz789"}

event: message
data: {"content": "There were 1,523 orders placed last month.", "id": "msg_005"}

Handling SSE in your application

JavaScript/TypeScript

interface SSEEvent {
  type: "chat_metadata" | "processing" | "visualization" | "message" | "error";
  data: any;
}

async function sendChatMessage(
  message: string,
  integrationId: string,
  token: string,
  onEvent: (event: SSEEvent) => void
): Promise<void> {
  const response = await fetch("https://api.trellis.sh/v1/chats", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${token}`,
      "Content-Type": "application/json",
      Accept: "text/event-stream",
    },
    body: JSON.stringify({
      message,
      integration_id: integrationId,
    }),
  });

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

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

    buffer += decoder.decode(value, { stream: true });
    const lines = buffer.split("\n");
    buffer = lines.pop() || "";

    let currentEvent = "";
    for (const line of lines) {
      if (line.startsWith("event: ")) {
        currentEvent = line.slice(7);
      } else if (line.startsWith("data: ") && currentEvent) {
        const data = JSON.parse(line.slice(6));
        onEvent({ type: currentEvent as SSEEvent["type"], data });
        currentEvent = "";
      }
    }
  }
}

// Usage
sendChatMessage(
  "Show me top 10 customers by revenue",
  "integration_id_here",
  "your_token",
  (event) => {
    switch (event.type) {
      case "chat_metadata":
        console.log("New chat:", event.data.id);
        break;
      case "processing":
        showLoadingIndicator();
        break;
      case "message":
        displayMessage(event.data.content);
        break;
      case "error":
        showError(event.data.error);
        break;
    }
  }
);

Python

import requests
import json

def send_chat_message(message: str, integration_id: str, token: str):
    """Send a chat message and stream the response."""
    
    response = requests.post(
        "https://api.trellis.sh/v1/chats",
        headers={
            "Authorization": f"Bearer {token}",
            "Content-Type": "application/json",
            "Accept": "text/event-stream",
        },
        json={
            "message": message,
            "integration_id": integration_id,
        },
        stream=True
    )
    
    current_event = None
    
    for line in response.iter_lines(decode_unicode=True):
        if not line:
            continue
            
        if line.startswith("event: "):
            current_event = line[7:]
        elif line.startswith("data: ") and current_event:
            data = json.loads(line[6:])
            yield {"type": current_event, "data": data}
            current_event = None


# Usage
for event in send_chat_message(
    "Show me revenue by month",
    "integration_id_here",
    "your_token"
):
    print(f"{event['type']}: {event['data']}")

Chat lifecycle

  1. Create a chat - Send the first message with POST /v1/chats (no chat_id)
  2. Receive chat ID - The chat_metadata event contains the new chat’s ID
  3. Continue conversation - Include the chat_id in subsequent messages
  4. View history - Use GET /v1/chats/{id} to retrieve all messages
  5. Manage chats - Update titles, delete chats, or provide feedback on messages

Message roles

Messages in a chat have one of two roles:
RoleDescription
userMessages sent by the user
assistantResponses from the AI