logo
Casey AIOverview

Casey AI — API Reference

Integration guide for the Casey AI chat service. Everything the frontend needs to connect, stream, and render.

Casey is Play Money's AI assistant. It runs as a standalone service that the frontend connects to via SSE (Server-Sent Events). The frontend sends messages, Casey streams responses back with text tokens, tool indicators, and widget hints.

Base URL

EnvironmentURL
Developmenthttp://localhost:8000
ProductionSet via CASEY_API_URL env var

Authentication

Casey shares the same JWT as Rails. Send the user's existing JWT in the Authorization header — no new auth system.

Authorization: Bearer <jwt_token>

The JWT must contain person_id (or sub) and email. Casey decodes it with the shared JWT_SECRET.

Endpoints

MethodPathDescription
POST/api/chatSend a message and stream Casey's response
GET/api/conversationsList the user's conversations
POST/api/conversationsCreate a new conversation
GET/api/conversations/{id}Get a conversation with messages
GET/healthHealth check

All endpoints except /health require authentication via the JWT header.

Quick Start

// 1. Send a message
const response = await fetch(`${CASEY_URL}/api/chat`, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${jwt}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    message: "What's my portfolio looking like?",
    context: { page: "portfolio" },
  }),
});

// 2. Read the SSE stream
const reader = response.body.getReader();
const decoder = new TextDecoder();

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

  const lines = decoder.decode(value).split("
");
  for (const line of lines) {
    if (!line.startsWith("data: ")) continue;
    const event = JSON.parse(line.slice(6));

    switch (event.type) {
      case "metadata":
        // Save conversation ID for future messages
        setConversationId(event.conversation_id);
        break;
      case "token":
        // Append text to the message
        appendText(event.content);
        break;
      case "tool_start":
        // Show loading indicator
        showToolIndicator(event.label);
        break;
      case "tool_end":
        // Hide loading indicator
        hideToolIndicator(event.tool);
        break;
      case "widget":
        // Render a widget component
        renderWidget(event.widget);
        break;
      case "sources":
        // Store sources for [N] citation links
        setSources(event.sources);
        break;
      case "error":
        showError(event.message);
        break;
      case "done":
        finalizeMessage();
        break;
    }
  }
}

// 3. Post-process the message text for inline markers
//    - [deal:ID] → clickable deal links
//    - [N] → clickable source citation links (using sources from step 2)

Casey embeds [deal:ID] markers next to deal names and [N] source citation markers in its responses. Parse these after streaming completes to render interactive links. See Chat Endpoint for details.