Render trustworthy charts from JSON.
ChartRelay accepts one small chart specification and returns raw SVG, durable SVG and PNG URLs, accessible text, and an explainable QA report.
Quickstart
Create an account, copy the API key once, and send it as a Bearer token. Never expose a production key in browser code.
curl -X POST http://localhost:3000/api/v1/charts \
-H "Authorization: Bearer $CHARTRELAY_KEY" \
-H "Content-Type: application/json" \
--data '{
"type": "bar",
"title": "Monthly recurring revenue",
"subtitle": "Revenue grew 84% over six months",
"width": 900,
"height": 520,
"theme": "light",
"showLegend": true,
"showValues": true,
"series": [{
"name": "MRR",
"color": "#6C5CE7",
"data": [
{ "label": "August", "value": 31200 },
{ "label": "September", "value": 33900 }
]
}]
}'Chart schema
| Field | Type | Rules |
|---|---|---|
type | string | bar, line, area, pie, or scatter. Every type uses a categorical axis; scatter plots each value at its label in input order and has no numeric x-axis. |
title | string | Up to 120 characters. Defaults to “Untitled chart”, which QA flags as missing-title. |
subtitle | string | Optional, up to 180 characters |
width | integer | 320–2400, defaults to 900 |
height | integer | 240–1600, defaults to 520 |
theme | string | light or dark, defaults to light |
showLegend | boolean | Defaults to true. Pie legends name the slices; without a legend, pie slices are labeled directly. |
showValues | boolean | Defaults to false. Prints each value on the chart. |
series | array | 1–12 series, each with 1–100 data points. Points are matched to categories by label, in first-seen order across all series. |
series[].name | string | 1–80 characters |
series[].color | string | Optional six-digit hex such as #6C5CE7 (three-digit hex is rejected). Ignored by pie charts, which color each slice from the palette. |
series[].data[].label | string | 1–80 characters. Axis labels longer than 12 characters are shortened. |
series[].data[].value | number | Any finite number. Pie values must not be negative. |
Response
A successful request returns HTTP 201. The raw SVG is included for immediate use. The QA array contains errors, warnings, or tips with a concrete correction.
{
"id": "V1StGXR8_Z5jdH",
"svg": "<svg ...>...</svg>",
"altText": "Monthly recurring revenue...",
"warnings": [{
"severity": "tip",
"code": "healthy",
"message": "No structural chart problems detected.",
"suggestion": "Verify the source data..."
}],
"urls": {
"svg": "https://.../api/v1/charts/V1StGXR8_Z5jdH?format=svg",
"png": "https://.../api/v1/charts/V1StGXR8_Z5jdH?format=png"
},
"usage": { "used": 17, "limit": 100 }
}Asset URLs
Generated assets are immutable. The only supported query parameter is format; any other parameter is rejected with 400. Use the SVG URL for responsive product interfaces and the PNG URL for email, social posts, and systems that reject SVG.
Errors
| Status | Meaning |
|---|---|
| 400 | The chart specification failed validation. details.issues lists each problem with the path to the field, such as series.1.data.3.label. |
| 401 | The Bearer API key is missing or invalid. |
| 404 | The requested asset does not exist. |
| 413 | The request body is larger than 256 KB. |
| 429 | The workspace reached its monthly render limit. Only quota exhaustion returns 429. |
| 500 | A server error. It is not a quota problem and does not count against usage; retry later. |
If a response still makes no sense after checking this table, support explains what to send us — and what never to include in a report.