Skip to main content

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 via aiMetadata.emptyResultRetry on 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 on conversation.totalCacheReadInputTokens / totalCacheCreationInputTokens.

Flow

Mermaid editor

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."