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 "Comparison" |
| criteriarequired | string[] | Column headings, left to right: what each option is scored on, e.g. ["Cost", "Ease of use", "Integrations"]. 1–8 criteria, up to 40 characters each; long names wrap to two lines. max 8 items |
| rowsrequired | object[] | The options being compared, top to bottom (2–12). Each has a name and one score per criterion, in the same order as `criteria`. max 12 items |
| style | string | Cell style for the whole grid: "harvey" (Harvey balls, scores 0–4 from empty to full), "check" (a tick for 1, nothing for 0) or "dots" (0–5 filled dots out of five). Default "harvey". "harvey", "check", "dots" · default "harvey" |
| notes | boolean | Show the Notes column on the right. true shows it even when no row has a note yet; false hides it (any row notes are kept but not drawn). When omitted, the column appears automatically as soon as any row has a note, so you can simply set rows[].notes. |
| legend | boolean | Show a one-line legend under the grid explaining the scale. Default true. default true |
| width | integer | Chart width in pixels (640–2400, default 1280, which suits a 16:9 slide). PNG output renders at 2x. Height is always computed from the content. 640–2400 · default 1280 |
| palette | string[] | Hex colours applied in order to items that have no colour of their own. Pass the user's brand colours here when they name them. Default: indigo, sky, emerald, amber, red, gray. max 12 items · default ["#4f46e5","#0ea5e9","#10b981","#f59e0b","#ef4444","#6b7280"] |
| Field | Type | Description |
|---|---|---|
| namerequired | string | Option name shown in the left column (up to 40 characters; long names wrap to two lines). max 40 chars |
| scores | (number | null)[] | One score per criterion, in criteria order. Range depends on `style`: harvey 0–4 (0 empty ring … 4 full ball), check 0/1 (1 draws a tick), dots 0–5 (filled dots). null leaves a cell blank (drawn as a muted dash). Values outside the style's range are clamped with a warning; a shorter array leaves the remaining cells blank, a longer one is truncated. max 8 items · default [] |
| highlight | boolean | Tint this row and tag it "Recommended". Use it on the option you are recommending (normally just one). Default false. default false |
| notes | string | Optional short comment shown in the Notes column on the right (wrapped to two lines, up to 160 characters). See the top-level `notes` field for when that column appears. max 160 chars |
| color | string | Optional hex colour for this row's balls, ticks or dots, e.g. "#10b981". Default: the first palette colour (or dark slate if that colour is too light to read). max 40 chars |
POST /api/render/harvey returns image/png; add ?format=svg for SVG.GET /harvey.png?d=<payload> and /harvey.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./harvey#d=<payload> opens the same chart in the builder for editing.GET /api/render/harvey?demo=1 returns the demo chart.GET /api/schema/harvey 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_harvey_matrix tool that returns the image plus image, SVG and edit links. See the MCP page →