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
| Environment | URL |
|---|---|
| Development | http://localhost:8000 |
| Production | Set 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
| Method | Path | Description |
|---|---|---|
POST | /api/chat | Send a message and stream Casey's response |
GET | /api/conversations | List the user's conversations |
POST | /api/conversations | Create a new conversation |
GET | /api/conversations/{id} | Get a conversation with messages |
GET | /health | Health 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.
Last updated Mar 26, 2026
Built with Documentation.AI