Visit Later
N/a
General Notes
- Fails if the user already has an active conversation (status: "active") anywhere
- Fails if the canvas has reached its widgetLimit
- Sends the user's message to Claude API along with the DuckDB schema context
- AI may respond with a clarification (needs more info) or a widget (SQL + config generated)
- If the generated SQL executes but returns 0 rows, the handler retries the AI once (adaptive thinking on Opus 4.7, scaled down on other models per
modelCapabilities.js) to re-examine filters/joins. Flagged viaaiMetadata.emptyResultRetryon the persisted assistant message. - System prompt is sent with
cache_control: ephemeral— the static prefix is served from cache on retries and multi-turn conversations. Cache read/write tokens accumulate onconversation.totalCacheReadInputTokens/totalCacheCreationInputTokens.
Flow
Test cases
Method & URL
POST v1/conversations
Request
Headers
authorization
- Required
- Type : <string>
- Bearer session token
Query
Body
canvasId
- Required
- Type : <string>
- The ID of the canvas to create the widget in
message
- Required
- Type : <string>
- The user's prompt describing the desired widget
Path parameter
(none)
Response
2xx
success
- Type : true (boolean)
- This indicates that request was executed successfully
message
- Type : <string> | null
- Generic message
data
- Type : <object>
data.type
- Type : "clarification" | "chart" | "table" (string)
data.conversationId
- Type : <string>
- ID of the created conversation (to continue messaging)
data.message
- Type : <string> | null
- Present when data.type is "clarification"
- The AI's clarification question
data.widget
- Type : <object> | null
- Present when data.type is "chart" or "table"
- The created widget document
data.widget.id
- Type : <string>
data.widget.title
- Type : <string>
- AI-generated widget title
data.widget.type
- Type : <string>
- Enum : chart | table
data.widget.chartType
- Type : <string> | null
- Enum : line | bar | pie | donut | stackedBar | scatterPlot
- null when type is "table"
- scatterPlot supports up to 50 data points (all other chart types are limited to 10)
data.widget.chartConfig
- Type : <object> | null
- Frontend rendering config (axes, colors, etc.)
- null when type is "table"
- stackedBar requires a stackField property in chartConfig (the field used to split bar segments)
data.widget.columns
- Type : <object>[] | null
- Array of column definitions for table rendering
- Populated when type is "table", null when type is "chart"
data.widget.columns[].field
- Type : <string>
- Key used to read the value from each row object — must exactly match the SQL column alias
data.widget.columns[].label
- Type : <string>
- String displayed as the column header in the UI
data.widget.position
- Type : <number>
- Position within the canvas
data.widget.latestExplanation
- Type : <string> | null
- Plain-language explanation of the chart, up to 5000 chars
- Populated for type "chart" only, always null for type "table"
data.widget.latestExplanationGeneratedAt
- Type : <string (ISO timestamp)> | null
- When the explanation was generated
- Populated for type "chart" only, always null for type "table"
data.rows
- Type : <object>[] | null
- Present when data.type is "chart" or "table"
- Query result rows from executing the SQL
data.totalCount
- Type : <number> | null
- Present when data.type is "table"
- Total matching rows (for pagination)
400
success
- Type : false (boolean)
message
- Type : <string>
- "You already have an active conversation" or "This tab has reached its widget limit"
404
success
- Type : false (boolean)
message
- Type : <string>
- "Something went wrong. We're on it."