API Endpoints
Canvases
List Canvases
GET /api/v1/canvases
Response (2xx)
{
"success": true,
"data": {
"canvases": [
{
"id": "...",
"name": "Energy Audit",
"displayOrder": 0,
"isDefault": true,
"widgetCount": 5,
"widgetLimit": 10
}
]
}
}
Create Canvas
POST /api/v1/canvases
Body
{
"name": "My Analysis"
}
Rename Canvas
PATCH /api/v1/canvases/:canvasId
Body
{
"name": "New Name"
}
Delete Canvas
DELETE /api/v1/canvases/:canvasId
- Cannot delete the default Energy Audit canvas
- Deletes all widgets and conversations under this canvas
Widgets
List Widgets in Canvas
GET /api/v1/canvases/:canvasId/widgets
Response (2xx)
{
"success": true,
"data": {
"widgets": [
{
"id": "...",
"title": "TC Trends — Line Chart",
"type": "chart",
"chartType": "line",
"position": 0,
"conversationId": "..."
}
]
}
}
Get Widget Data (Execute SQL)
GET /api/v1/widgets/:widgetId/data
Query
?limit=50&offset=0 (for tables only)
Response (2xx)
{
"success": true,
"data": {
"rows": [...],
"totalCount": 264
}
}
Update Widget Name
PATCH /api/v1/widgets/:widgetId
Body
{
"title": "Updated Widget Name"
}
Delete Widget
DELETE /api/v1/widgets/:widgetId
- Repositions remaining widgets in the canvas
- Deletes associated conversation
Conversations / Chat
Start New Conversation
POST /api/v1/conversations
Body
{
"canvasId": "...",
"message": "Show me TC trends over time"
}
- Fails if user already has an active conversation
- Fails if canvas not found or not owned by user
- Fails if canvas has reached widget limit
Send Message (Continue Conversation)
POST /api/v1/conversations/:conversationId/messages
Body
{
"message": "Last 3 months"
}
Response — Clarification
{
"success": true,
"data": {
"type": "clarification",
"message": "What month range should this cover?",
"message": "What month range should this cover?"
}
}
Response — Widget Generated
{
"success": true,
"data": {
"type": "chart",
"widget": {
"id": "...",
"title": "TC Trends — Line Chart",
"type": "chart",
"chartType": "line",
"sql": "SELECT ...",
"chartConfig": { ... },
"position": 3
},
"rows": [...],
"conversationName": "TC trends over time"
}
}
Get Conversation (for widget editing)
GET /api/v1/conversations/:conversationId
Response (2xx)
{
"success": true,
"data": {
"conversation": {
"id": "...",
"name": "TC trends over time",
"status": "completed",
"widgetId": "...",
"messages": [
{ "role": "user", "content": "Show me TC trends", "timestamp": "..." },
{ "role": "assistant", "content": "What month range?", "timestamp": "..." },
{ "role": "user", "content": "Last 3 months", "timestamp": "..." },
{ "role": "assistant", "content": "Widget generated", "sql": "...", "chartConfig": { ... }, "timestamp": "..." }
]
}
}
}
Reopen Conversation (Edit Widget)
POST /api/v1/conversations/:conversationId/messages
- Same endpoint as "Send Message"
- If conversation is completed, it gets reopened to "active" status
- User sends edit instruction → AI modifies SQL → widget updates
Health / Info
Inherited from slim-bp-v2 boilerplate:
GET /api/v1/general/info
GET /api/v1/general/health/service
GET /api/v1/general/health/mongo