Chart Generation

The Chart Generation endpoint takes the SQL result of an assistant message and returns it as a chart, in one of three formats: a Chart.js config for frontend rendering, raw PNG bytes, or an authenticated URL that serves a server-rendered PNG on demand.

Chart operates on message items produced by the Text-to-SQL agent — any message without a sql_query returns MessageNoSQLQueryError (see Errors).


POST/api/v1/conversations/{conversation_id}/items/{message_id}/chart

Generate Chart

Generates a chart from a message's SQL query results. The output field in the request body controls the response format.

Path parameters

  • Name
    conversation_id
    Type
    string (UUID)
    Required
    Description

    ID of the conversation containing the message.

  • Name
    message_id
    Type
    string (UUID)
    Required
    Description

    ID of the assistant message that contains the SQL query result.

Authorization

Request body

  • Name
    intent
    Type
    object
    Required
    Description

    The chart specification. Its required fields depend on intent.type — see the chart-type sections below.

  • Name
    output
    Type
    string
    Required
    Description

    Response format. One of "chartjs" (default), "png", or "image_url". See Choosing the right output format below.

Choosing the right output format

  • chartjs (default): Best when you have a frontend capable of rendering Chart.js charts. Gives full control over styling and interactivity.
  • png: Best when you need a static image immediately — e.g. embedding in a Slack message, email, or PDF report.
  • image_url: Best when an authenticated client wants to defer fetching the image until it's viewed. The URL requires authentication, so it can't be dropped into an HTML <img> tag — to embed in HTML, fetch the PNG and re-host it.

Bar and Line Charts

Bar charts are best for categorical comparisons. Line charts are best for time-series data and trends. Both share the same intent structure.

  • Name
    type
    Type
    "bar" | "line"
    Required
    Description

    Chart type.

  • Name
    x
    Type
    string
    Required
    Description

    Column name for the X-axis.

  • Name
    y
    Type
    string | string[]
    Required
    Description

    Column name(s) for Y-axis values. Use an array to plot multiple metrics as separate series.

  • Name
    series
    Type
    string
    Required
    Description

    Column to split data into multiple series. Ignored if y is an array.

  • Name
    aggregate
    Type
    string
    Required
    Description

    Aggregation function: "sum", "avg", "count", "min", "max". Defaults to "sum".

  • Name
    limit
    Type
    integer
    Required
    Description

    Maximum categories / points to display (1–10000). Defaults to 50 for bar, 365 for line (time-series).

  • Name
    max_series
    Type
    integer
    Required
    Description

    Maximum series to display (1–100). Defaults to 12.

  • Name
    title
    Type
    string
    Required
    Description

    Chart title.

Temporal columns on line charts are auto-detected from native datetime types or from string values that parse as dates (≥80% success rate). Numeric columns are never interpreted as timestamps.

Pie Chart

Best for showing composition or distribution of a whole. Recommended for fewer than 8 categories.

  • Name
    type
    Type
    "pie"
    Required
    Description

    Chart type.

  • Name
    label
    Type
    string
    Required
    Description

    Column name for category labels.

  • Name
    value
    Type
    string
    Required
    Description

    Column name for numeric values.

  • Name
    aggregate
    Type
    string
    Required
    Description

    Aggregation function. Defaults to "sum".

  • Name
    limit
    Type
    integer
    Required
    Description

    Maximum slices (1–10000). Defaults to 12. Excess categories are grouped into "Other".

  • Name
    title
    Type
    string
    Required
    Description

    Chart title.

Scatter Chart

Best for showing correlation between two numeric variables.

  • Name
    type
    Type
    "scatter"
    Required
    Description

    Chart type.

  • Name
    x
    Type
    string
    Required
    Description

    Column name for the X-axis (must be numeric).

  • Name
    y
    Type
    string
    Required
    Description

    Column name for the Y-axis (must be numeric).

  • Name
    series
    Type
    string
    Required
    Description

    Column to split data into multiple series.

  • Name
    limit
    Type
    integer
    Required
    Description

    Maximum data points (1–10000). Defaults to 1000.

  • Name
    max_series
    Type
    integer
    Required
    Description

    Maximum series (1–100). Defaults to 12.

  • Name
    title
    Type
    string
    Required
    Description

    Chart title.

Metadata object

Both chartjs and image_url responses include a meta object:

FieldTypeDescription
row_countintegerTotal rows in the source data
used_rowsintegerRows processed after null removal
pointsintegerNumber of data points in the chart
seriesintegerNumber of series / datasets
fieldsobjectField type hints (temporal, quantitative, nominal)

Warning codes

CodeDescription
ROW_LIMITData exceeded the 10,000-row processing limit
TRUNCATEDData points truncated to the configured limit
SERIES_TRUNCATEDNumber of series truncated to the configured max_series
SERIES_IGNOREDseries column ignored because y is an array
UNKNOWN_SERIESSpecified series column not found in the data

Error responses

StatusCause
400Invalid chart intent, invalid SQL query, invalid chart image token, or message lacks a SQL query
404Conversation or message not found
500Server-side error during chart generation

See the Errors reference for the shared {"detail": "..."} response format.

Request

POST
/api/v1/conversations/{conversation_id}/items/{message_id}/chart
curl --request POST \
--url 'https://mdb.ai/api/v1/conversations/123e4567-e89b-12d3-a456-426614174000/items/123e4567-e89b-12d3-a456-426614174001/chart' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer MINDS_API_KEY' \
--data '{
  "intent": {
    "type": "bar",
    "x": "month",
    "y": "total_sales",
    "title": "Monthly Sales"
  },
  "output": "chartjs"
}'

Response (chartjs)

{
  "format": "chartjs",
  "config": {
    "type": "bar",
    "data": {
      "labels": ["Jan", "Feb", "Mar"],
      "datasets": [
        { "label": "Total Sales", "data": [50000, 62000, 71000] }
      ]
    },
    "options": {}
  },
  "meta": {
    "row_count": 1000,
    "used_rows": 500,
    "points": 3,
    "series": 1,
    "fields": {
      "month": "temporal",
      "total_sales": "quantitative"
    }
  },
  "warnings": []
}

Response (png)

HTTP/1.1 200 OK
Content-Type: image/png
Cache-Control: no-store

<raw PNG bytes — 1600x800px at 100 DPI>

Response (image_url)

{
  "image_url": "/api/v1/conversations/{conversation_id}/items/{message_id}/chart?token={token}",
  "meta": {
    "row_count": 1000,
    "used_rows": 500,
    "points": 3,
    "series": 1
  },
  "warnings": []
}


GET/api/v1/conversations/{conversation_id}/items/{message_id}/chart

Serve Chart Image

Serves a server-rendered PNG for a chart whose POST response was output: "image_url". The chart is rendered on demand each time the URL is fetched — the token does not cache an image.

Path parameters

  • Name
    conversation_id
    Type
    string (UUID)
    Required
    Description

    ID of the conversation containing the message.

  • Name
    message_id
    Type
    string (UUID)
    Required
    Description

    ID of the assistant message whose chart should be served.

Query parameters

  • Name
    token
    Type
    string
    Required
    Description

    Opaque chart token returned by the POST endpoint when output is image_url. An invalid token returns 400.

Authorization

  • Name
    MINDS_API_KEY
    Type
    string
    Required
    Description

    The GET endpoint requires the same authentication header as POST. The token alone is not sufficient.

Response

Returns raw PNG bytes with Content-Type: image/png and Cache-Control: private, no-store. Image dimensions are 1600×800 at 100 DPI.

Request

GET
/api/v1/conversations/{conversation_id}/items/{message_id}/chart
curl --request GET \
--url 'https://mdb.ai/api/v1/conversations/123e4567-e89b-12d3-a456-426614174000/items/123e4567-e89b-12d3-a456-426614174001/chart?token=<token>' \
--header 'Authorization: Bearer MINDS_API_KEY' \
--output chart.png

Response

HTTP/1.1 200 OK
Content-Type: image/png
Cache-Control: private, no-store

<raw PNG bytes — 1600x800px at 100 DPI>


Processing limits

LimitValue
Maximum rows processed10,000
Default series limit12
Default categorical limit (bar)50
Default temporal limit (line)365
Default scatter limit1,000
Default pie limit12
Server-rendered image size1600 × 800 px at 100 DPI

Usage examples

Multi-metric line chart as PNG

Each entry in the y array becomes a separate series.

{
  "intent": {
    "type": "line",
    "x": "month",
    "y": ["revenue", "expenses", "profit"],
    "title": "Monthly Financial Overview"
  },
  "output": "png"
}

Grouped bar chart via image URL

Splits revenue by product_line, capped at 5 series.

{
  "intent": {
    "type": "bar",
    "x": "quarter",
    "y": "revenue",
    "series": "product_line",
    "aggregate": "sum",
    "max_series": 5,
    "title": "Quarterly Revenue by Product Line"
  },
  "output": "image_url"
}

Two-step image URL flow

Step 1 — request an image URL:

POST /api/v1/conversations/{conversation_id}/items/{message_id}/chart

{
  "intent": { "type": "bar", "x": "region", "y": "total_sales", "title": "Sales by Region" },
  "output": "image_url"
}

Step 2 — fetch the image with the returned token:

GET /api/v1/conversations/{conversation_id}/items/{message_id}/chart?token={token}
Authorization: Bearer MINDS_API_KEY

The GET request must include the same authentication headers as the POST. The response is raw PNG bytes.

Was this page helpful?