Skip to main content
The Trellis chat API enables natural language conversations with your databases. You can choose between two streaming protocols:
ProtocolEndpointBest for
SSEPOST /v1/chatsSimple integrations, one message at a time
WebSocketWS /v1/chats/wsReal-time apps, multiple messages per connection
Both protocols deliver the same events and provide identical functionality. Choose based on your application’s needs.

How it works

Event Types

Both SSE and WebSocket deliver the same event types. The format differs slightly by protocol:
EventDescription
chat_metadataContains the chat ID (id) and the persisted user message ID (user_message_id). Emitted at the start of every response, including continued conversations and message edits.
processingStatus updates while the AI is working. Use to show loading indicators.
visualizationSent when a chart or table is generated. Contains the full structured payload ready to render. See Visualizations.
messageThe final response from the AI. This is the primary content to display.
errorAn error occurred during processing.

Event format by protocol

SSE events are delivered as text with event: and data: lines:
event: chat_metadata
data: {"id": "chat_abc123", "user_message_id": "msg_001"}

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

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

event: visualization
data: {"id": "ab12xy3456", "type": "chart", "chart_type": "bar", "title": "Orders by Region", "data": {"values": [{"label": "North", "value": 412}, {"label": "South", "value": 289}, {"label": "East", "value": 531}], "x_axis_label": "Region", "y_axis_label": "Orders"}}

event: message
data: {"content": "There were 1,232 orders placed last month, with the East region leading at 531.", "id": "msg_005"}

Code Examples

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

async function sendChatMessage(
  message: string,
  integrationId: string,
  token: string,
  onEvent: (event: ChatEvent) => 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 ChatEvent["type"], data });
        currentEvent = "";
      }
    }
  }
}

// Handle each event type
sendChatMessage("Show me orders by region", "integration_id", "token", (event) => {
  switch (event.type) {
    case "chat_metadata":
      console.log("Chat ID:", event.data.id, "| User message:", event.data.user_message_id);
      break;
    case "processing":
      showLoadingIndicator(event.data.status);
      break;
    case "visualization":
      if (event.data.type === "table") {
        renderTable(event.data.headers, event.data.rows);
      } else if (event.data.type === "chart") {
        renderChart(event.data.chart_type, event.data.title, event.data.data);
      }
      break;
    case "message":
      displayMessage(event.data.content);
      hideLoadingIndicator();
      break;
    case "error":
      showError(event.data.error);
      break;
  }
});

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. Edit messages - Use PATCH /v1/chats/{id}/messages/{id} to edit a user message and re-stream the response
  6. Manage chats - Update titles, delete chats, delete messages, 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