API Reference
REST API endpoints for chart rendering and management.
OpenAPI 3.1 specification – Use with Swagger UI, Redoc, or code generators.
Postman collection – Import into Postman to test all endpoints. Set baseUrl, apiKey, and sessionToken variables.
POST /api/v1/render
Renders a chart from a JSON specification. Returns the image as binary (PNG, JPEG, SVG, WebP, or PDF) or JSON with a CDN URL when returnUrl: true.
Request Body
{
"type": "line" | "bar" | "pie" | "doughnut" | "radar" | "polarArea",
"width": 800,
"height": 400,
"format": "png" | "jpeg" | "svg" | "webp" | "pdf",
"data": {
"labels": ["Jan", "Feb", "Mar"],
"datasets": [{
"label": "Revenue",
"data": [12000, 15000, 18000]
}]
},
"brandKitId": "uuid-or-preset",
"devicePixelRatio": 1,
"returnUrl": false,
"options": {}
}See Chart Specifications and Card Composition for the full field reference. Authentication: Authorization: Bearer pk_live_... (optional — anonymous renders are allowed at starter plan limits).
Response Headers
Content-Type–image/png,image/jpeg,image/svg+xml,image/webp, orapplication/pdfX-Render-Time-Ms– Render latency in millisecondsX-Cache–HITorMISSwhen Redis caching is enabledX-Request-Id– Unique request ID for debugging and supportETag– MD5 of the spec for client-side caching
GET /api/v1/render
Renders a chart from URL parameters. Ideal for <img src="..."> embeds in emails, Slack, Markdown, and forums.
Supports two formats: base64-encoded JSON (full spec) or simple query parameters (basic charts). URL length limit: 2000 characters — use POST for complex specs that exceed this.
Authentication
Browsers cannot send Authorization headers with image requests. Pass your API key as a query parameter instead:
key–?key=pk_live_...apiKey– Alias forkey:?apiKey=pk_live_...
Format 1: Base64-encoded JSON
Encode your full chart spec as base64url. Use chart or the alias c.
GET /api/v1/render?key=pk_live_YOUR_KEY&chart=eyJ0eXBlIjoibGluZSIsIndpZHRoIjo4MDAsImhlaWdodCI6NDAwLCJkYXRhIjp7ImxhYmVscyI6WyJKYW4iLCJGZWIiLCJNYXIiXSwiZGF0YXNldHMiOlt7ImxhYmVsIjoiUmV2ZW51ZSIsImRhdGEiOlsxMjAwMCwxNTAwMCwxODAwMF19XX19Format 2: Query Parameters
Simple charts with comma-separated values. Best for quick embeds.
typeorcht– line, bar, pie, doughnut, radar, polarArealabelsorl– Comma-separated labelsdataord– Comma-separated numberstitleort– Chart titlewidth,height– Dimensions (100–4000 px)format– png, jpeg, svg, webp, pdfbrandKitId– UUID or preset name (obsidian, linen, polar, studio, ember, harbor)returnUrl– Return JSON with CDN URL instead of the image
GET /api/v1/render?key=pk_live_YOUR_KEY&type=bar&labels=Q1,Q2,Q3,Q4&data=100,150,120,180&title=Revenue&format=png&width=600&height=300Email Embedding
Use the GET endpoint in HTML emails. PNG format recommended for best compatibility across Gmail, Outlook, and Apple Mail.
<img
src="https://chart-output.com/api/v1/render?key=pk_live_YOUR_KEY&type=bar&labels=Jan,Feb,Mar&data=10,20,30&format=png"
alt="Monthly stats"
width="600"
height="300"
/>URL-encode special characters in labels (spaces → %20). Keep URLs under 2000 characters; use POST for complex charts.
GET /api/v1/templates/:templateId/render
Renders a built-in or custom template with optional query parameter overrides.
Query Parameters
labels– Comma-separated labelsdata– Comma-separated valuestitle– Chart titlewidth,heightformat– png, jpeg, svg, webpbrandKitId– UUID of brand kit or preset (obsidian, linen, polar, studio, ember, harbor)scale/devicePixelRatio– 1–4; defaults to 2 on this route (retina output)palette– Comma-separated hex colors (URL-encode#as%23)
Management APIs (Dashboard)
These endpoints require a session JWT (from the dashboard) or API key.
- GET /api/v1/stats – Overview stats (renders this month, success rate, avg latency)
- GET /api/v1/renders?limit=10 – Recent render history
- GET /api/v1/usage – Usage data for current month
- GET/POST/DELETE /api/v1/api-keys – API key management
- GET/POST/PUT/DELETE /api/v1/brand-kits – Brand kit CRUD
- GET/POST/DELETE /api/v1/webhooks – Webhook subscriptions
- GET/POST/PUT/DELETE /api/v1/templates – Custom template CRUD
- GET /api/v1/audit-logs – Audit log for account actions
- GET/PUT /api/v1/settings/custom-domain – Custom CDN domain for returnUrl
- POST /api/v1/jobs – Async render (returns 202 +
jobId). Results arrive within ~60 seconds viarender.completewebhook or GET /api/v1/jobs/:id polling. This is a known characteristic of the Vercel cron minimum interval. - GET /api/v1/jobs/:id – Poll async job status and result URL
- POST /api/v1/ai/render – Natural-language chart generation (Pro/Business). Has a separate AI render quota; see the AI rendering guide.
Error Responses
400 Bad Request
Invalid chart specification or malformed JSON.
401 Unauthorized
An Authorization header was present but the key was invalid. Requests with no auth at all return 200 at anonymous limits, not 401.
403 Forbidden
Valid key, but the operation is not allowed for this plan (e.g. expired account, PDF on Pro tier, non-PNG on trial).
Subscription required
{
"error": "Subscription required. Please upgrade to continue.",
"plan": "expired",
"upgradeUrl": "/app/usage-billing"
}PDF / plan feature
{
"error": "PDF output requires the Business plan",
"plan": "starter",
"upgradeUrl": "/pricing"
}429 Too Many Requests
Rate limiting (100 requests / 15 min) or render quota (trial cap / billing period). Check the error body.
Billing-period quota
{
"error": "Render quota exceeded for your billing period. Upgrade or wait for renewal.",
"currentUsage": 100000,
"limit": 100000,
"plan": "starter"
}Rate limit
{ "error": "Rate limit exceeded", "retryAfter": 120 }Retry-After– Seconds until the window resetsX-RateLimit-Limit– Request limit per window (100)X-RateLimit-Remaining– Requests remaining in current windowX-RateLimit-Reset– ISO timestamp of window reset
500 Internal Server Error
Server error during rendering. Include X-Request-Id when reporting issues.