POST a small JSON description and get back a deck-ready PNG (or SVG). The endpoint is open and CORS-enabled, so it works from browsers, scripts, CI and anywhere else you can make an HTTP call. The same JSON opens in the builder.
| Field | Type | Description |
|---|---|---|
| title | string | Heading shown top-left of the chart at 22px bold. Every chart has one title row; an empty string hides it. max 140 chars · default "Valuation summary" |
| width | integer | Chart width in pixels (640–2400, default 1280, which suits a 16:9 slide). PNG output renders at 2x. Height is computed from the number of rows. 640–2400 · default 1280 |
| palette | string[] | Hex colours. Every bar takes the FIRST palette colour unless the row sets its own colour, so a brand colour as the first entry recolours the whole chart. Default: indigo, sky, emerald, amber, red, gray. max 12 items · default ["#4f46e5","#0ea5e9","#10b981","#f59e0b","#ef4444","#6b7280"] |
| rowsrequired | object[] | The valuation methods, top to bottom (1–12; extra rows are dropped with a warning). Each row is one horizontal bar from low to high on the shared axis, e.g. { "method": "Trading comps", "detail": "8.0x–10.0x EV/EBITDA", "low": 42, "high": 51 }. A row whose low is above its high is swapped and reported as a warning. max 12 items |
| markers | object[] | Optional vertical dashed reference lines across every row (0–3), each labelled at the top with its label and value, e.g. [{ "label": "Current price", "value": 45.1 }, { "label": "Offer", "value": 52 }]. Default: none. max 3 items · default [] |
| range | object | Optional shaded band behind every row, e.g. the implied valuation range: { "low": 48, "high": 55, "label": "Implied range" }. Its label and values are shown above the band. Omit for none (the default). |
| prefix | string | Text put before every value, default "$". Use "€", "£" or "" (none), e.g. "" for multiples. max 6 chars · default "$" |
| suffix | string | Text put after every value, default "" (none). E.g. "m" for $ millions, "/sh" for per share, "x" for multiples, "%" for percentages. max 6 chars · default "" |
| decimals | integer | Decimal places for every value (0–3), e.g. 2 shows 45.10. Omit (the default) to show each value as given, rounded to at most 2 decimals. 0–3 |
| showValues | boolean | Print the low and high values just outside each end of every bar. Default true. default true |
| axisMin | number | Optional left end of the value axis, e.g. 30. Omit (recommended) and the axis starts at a round number slightly below the smallest value. Bars beyond the axis are cut off with a warning. -1000000000000–1000000000000 |
| axisMax | number | Optional right end of the value axis, e.g. 70. Omit (recommended) and the axis ends at a round number slightly above the largest value. -1000000000000–1000000000000 |
| Field | Type | Description |
|---|---|---|
| methodrequired | string | Method name shown left of the bar at 14px bold, e.g. "DCF (perpetuity growth)" or "52-week trading range". Wraps to two lines when long. max 60 chars |
| detail | string | Optional muted line under the method name with the key assumption, e.g. "8.0x–10.0x EV/EBITDA" or "WACC 9–11%, g 2–3%". Omit for none. max 80 chars |
| low | number | Low end of the range, in the chart's units (the prefix and suffix are added for display), e.g. 42 for $42/share or 1250 for $1,250m. Numeric strings are accepted. -1000000000000–1000000000000 |
| high | number | High end of the range, in the same units as low, e.g. 58. Swapped with low (and warned) if it is the smaller. -1000000000000–1000000000000 |
| color | string | Optional hex colour for this bar, e.g. "#0ea5e9" to set one method apart (such as the 52-week range). Default: the first palette colour. max 40 chars |
| Field | Type | Description |
|---|---|---|
| labelrequired | string | Marker name shown above its line, followed by the formatted value, e.g. "Current price" or "Offer price". max 40 chars |
| value | number | Where the line sits on the value axis, in the chart's units, e.g. 45.1. -1000000000000–1000000000000 |
| color | string | Optional hex colour for the line and its label. Default: dark slate for the first marker, red for the second, gray for the third. max 40 chars |
| Field | Type | Description |
|---|---|---|
| low | number | Low end of the shaded band, e.g. 48. -1000000000000–1000000000000 |
| high | number | High end of the shaded band, e.g. 55. -1000000000000–1000000000000 |
| label | string | Optional name shown above the band before its values, e.g. "Implied range" or "Proposed offer range". max 40 chars |
POST /api/render/footballfield returns image/png; add ?format=svg for SVG.GET /footballfield.png?d=<payload> and /footballfield.svg?d=<payload> render a chart from a link. The payload is the JSON body, raw-deflated and base64url-encoded. Nothing is stored: links are permanent and cached for a year./footballfield#d=<payload> opens the same chart in the builder for editing.GET /api/render/footballfield?demo=1 returns the demo chart.GET /api/schema/footballfield returns the JSON Schema, for code generators and AIs.Input is lenient where the intent is clear: numeric strings become numbers, out-of-range values are clamped, and unknown fields are ignored. Adjustments are listed in the X-Render-Warnings header. Anything unclear returns a 400 that says how to fix it:
{
"error": "Invalid payload",
"issues": [{ "path": "tasks", "message": "must be an array" }],
"example": { … }
}
Use the hosted MCP server instead. It gives Claude, Cursor and other MCP clients a create_football_field tool that returns the image plus image, SVG and edit links. See the MCP page →