Skip to main content

AI chart rendering

Pass a natural-language description and optional raw data. Chart-Output generates a validated chart spec and renders it in the same request. Response shape mirrors /api/v1/render, so you can swap endpoints without changing the rest of your code path.

What this endpoint does

  1. Runs your description (and any data you attach) through our AI layer to produce chart JSON.
  2. Parses the response as JSON and runs it through the same Zod schema as the standard render endpoint.
  3. If validation fails, retries once with the Zod errors fed back to the model.
  4. Hands the validated spec to the existing renderer and returns the image bytes.

The model never renders anything itself. Every image you receive was produced by the same deterministic renderer used by /api/v1/render.

Request shape

POST /api/v1/ai/render

json
{ "description": string, // natural-language prompt, 1–4000 chars "data": unknown, // optional: CSV string, JSON array, or object "brandKitId": string, // optional: UUID of a saved brand kit "width": number, // optional: 100–4000, default 800 "height": number, // optional: 100–4000, default 400 "format": "png" | "jpeg" | "svg" | "webp" | "pdf", "returnUrl": boolean // optional: return { url } JSON instead of bytes }

Response headers include X-Ai-Chart-Type (the chart type the model chose) and X-Ai-Generation-Ms (time spent in the model, excluding render).

Examples

Description only

typescript
const res = await fetch('https://chart-output.com/api/v1/ai/render', { method: 'POST', headers: { Authorization: `Bearer ${process.env.CHART_OUTPUT_API_KEY}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ description: 'Monthly active users for 2024, rising from 12k in Jan to 24k in Dec. Use a calm blue palette.', format: 'png', width: 800, height: 400, }), }); if (!res.ok) { const err = await res.json(); throw new Error(err.details ?? err.error); } const buffer = Buffer.from(await res.arrayBuffer()); const chartType = res.headers.get('x-ai-chart-type'); const generationMs = res.headers.get('x-ai-generation-ms');

Description + structured data, persisted URL

typescript
await fetch('https://chart-output.com/api/v1/ai/render', { method: 'POST', headers: { Authorization: `Bearer ${process.env.CHART_OUTPUT_API_KEY}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ description: 'Revenue by region, ranked highest to lowest.', data: [ { region: 'Americas', revenue: 420 }, { region: 'EMEA', revenue: 310 }, { region: 'APAC', revenue: 280 }, { region: 'Other', revenue: 90 }, ], returnUrl: true, }), });

How validation works

Chart-Output validates the model output with the same Zod schema that powers /api/v1/render. If the first attempt fails, the endpoint retries once with the specific Zod errors appended to the prompt. If the retry still fails, the request returns 422 Unprocessable Entity with the underlying errors — we do not ship a broken spec to the renderer.

This means every image you receive from the AI endpoint would also be renderable via the manual JSON API. There is no path by which the model can cause an invalid render.

Limits and pitfalls

  • The model is limited to the six supported chart types: line, bar, pie, doughnut, radar, polarArea.
  • Chart.js plugins not represented in the schema (e.g. custom scale plugins) cannot be requested.
  • Attached data is serialized and truncated at 2,000 characters before being sent to the model. For very large datasets, pre-aggregate server-side.
  • Descriptions over 4,000 characters are rejected at request time.
  • Each call incurs a model round-trip. Typical end-to-end latency is 1–4 seconds; synchronous, not asynchronous.
  • The AI generation endpoint uses a curated set of models selected and validated by Chart Output. Model selection is handled automatically based on request complexity.

Plan gating & quotas

AI rendering is available on the Pro and Business plans. Trial and Starter keys receive 403 with an upgrade URL.

AI renders have their own monthly cap separate from the general render quota — each AI generation call has real per-request cost, so the limit is intentionally tighter:

PlanAI renders / monthGeneral renders / month
Pro500100,000
Business2,000500,000

Exceeding the AI quota returns 429 with currentAiUsage and aiLimit in the body. Successful responses carry X-Ai-Renders-Used, X-Ai-Renders-Limit, and X-Ai-Renders-Remaining headers so you can monitor usage programmatically.