Docs · Render API

POST a spec, download a chart

For pipelines, reports and anything that wants an image instead of an embed: a small HTTP service that turns the same JSON spec into a PNG or an SVG.

Self-hosted — free, MIT

Your machine, your copy

Everything below runs a copy of the service on YOUR computer — localhost:8787 is your own machine, not our server. No account, no key, and nothing you render ever reaches us. That is the open-source deal: you get the engine itself, not access to ours.

Hosted — planned

Our endpoint, your API key

For teams that would rather not run anything: a hosted render endpoint with real API keys and quotas is the paid layer on this roadmap. This page will grow a "get a key" path the day it exists.


Run it

One container: a headless Chromium stays warm inside it, renders arrive as a queue, and the fonts ship in the image so output is identical on every machine.

# from the repository root
docker compose up render-api
# -> listening on http://localhost:8787

GET /healthz answers {"ok": true} once the service is up.


PNG

curl -X POST http://localhost:8787/render \
  -H "Content-Type: application/json" \
  -d '{
    "spec": {
      "type": "column",
      "theme": "editorial",
      "title": "Weekly signups",
      "data": {
        "labels": ["Mon", "Tue", "Wed", "Thu", "Fri"],
        "series": [{ "name": "Signups", "values": [12, 19, 14, 27, 22] }]
      }
    }
  }' \
  --output chart.png
# -> a 1920x1080 PNG (960x540 at 2x, the defaults)
ParameterDefaultBounds
specrequiredthe same spec the spec reference documents
width96064–4096
height54064–4096
scale21–4 (device-pixel multiplier; final PNG is width×scale by height×scale)

SVG

Add "format": "svg" and the browser is skipped entirely — parsing, scene building and serialization are pure computation, so SVG renders are cheap and exact. scale is ignored (vectors have no pixels); font families are referenced by name, not embedded.

curl -X POST http://localhost:8787/render \
  -H "Content-Type: application/json" \
  -d '{ "format": "svg", "spec": { ...same spec... } }'
# -> a standalone <svg>, no browser involved

Limits, all of them

The service treats every request as untrusted and refuses oversized work before running the expensive parts:

LimitValueOn breach
Request body1 MiB413
Total values across all series10,000400, structured error
Drawn dots (dotplot)10,000400, structured error
Final PNG area (width×scale × height×scale)16,777,216 px400, structured error

Errors

Invalid input returns 400 with the same {path, message, hint} list as everywhere else in the project; unknown routes 404; unexpected failures 500. Nothing about a bad spec is ever a crash:

{
  "errors": [{
    "path": "type",
    "message": "Unknown chart type \"pei\"",
    "hint": "Use one of: line, area, bar, column, stacked, donut, scatter, number, dotplot"
  }]
}

Self-hosted today. When a hosted endpoint exists, this page will document it.