Templates and their JSON format
A template is a design with named fields. You change its draft, and each publish freezes the draft as a new version. The API and signed links draw the published version. The design itself is a JSON document called a scene.
Drafts and versions
Draft. Every template has one draft. The editor saves it as you work.
PUT /v1/templates/{id}/draftreplaces it. A draft never changes what renders and links show.Publish.
POST /v1/templates/{id}/publishcopies the draft into version 1, 2, 3 and so on. The newest version becomes the published version.Render. Renders, batches and signed links use the published version. A render or batch can name an older version with
version.
Versions are kept and never change. To use an old design again, render with its version.
The plan limits how many templates a workspace can have: Free 5, Starter 50, Pro no limit, Business no limit. Deleted templates do not count. Creating, copying or generating one more answers 402 plan_limit.
The template API
Create a template from a scene
The new template is a draft. Publish it before you render it.
curl
curl -X POST "https://mintrender.com/v1/templates" \ -H "Authorization: Bearer $MINTRENDER_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"Blog OG image","scene":{"version":1,"width":1200,"height":630,"background":{"color":"#0f172a"},"fonts":["Inter:400,700"],"sizes":[{"name":"square","width":1080,"height":1080,"layers":{"title":{"y":300,"h":400},"logo":{"y":960}}}],"pages":[{"layers":[{"id":"title","type":"text","x":80,"y":120,"w":1040,"h":260,"text":"Default title","font":"Inter","weight":700,"size":72,"fit":"shrink","minSize":36,"lineHeight":1.1,"color":"#ffffff","maxLines":3,"param":"title"},{"id":"logo","type":"image","x":80,"y":500,"w":160,"h":60,"src":"","fit":"contain","param":"logo"},{"id":"chart","type":"chart","x":700,"y":380,"w":420,"h":200,"chart":{"kind":"bar","series":[{"values":[3,5,8]}],"labels":["Jan","Feb","Mar"],"textColor":"#cbd5e1"},"param":"chart"}]}]}}'JavaScript
const res = await fetch("https://mintrender.com/v1/templates", { method: "POST", headers: { Authorization: `Bearer ${process.env.MINTRENDER_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ name: "Blog OG image", scene: { version: 1, width: 1200, height: 630, background: { color: "#0f172a", }, fonts: ["Inter:400,700"], sizes: [ { name: "square", width: 1080, height: 1080, layers: { title: { y: 300, h: 400, }, logo: { y: 960, }, }, }, ], pages: [ { layers: [ { id: "title", type: "text", x: 80, y: 120, w: 1040, h: 260, text: "Default title", font: "Inter", weight: 700, size: 72, fit: "shrink", minSize: 36, lineHeight: 1.1, color: "#ffffff", maxLines: 3, param: "title", }, { id: "logo", type: "image", x: 80, y: 500, w: 160, h: 60, src: "", fit: "contain", param: "logo", }, { id: "chart", type: "chart", x: 700, y: 380, w: 420, h: 200, chart: { kind: "bar", series: [ { values: [3, 5, 8], }, ], labels: ["Jan", "Feb", "Mar"], textColor: "#cbd5e1", }, param: "chart", }, ], }, ], }, }),});const body = await res.json();if (!res.ok) throw new Error(`${body.error.code}: ${body.error.message} (${body.error.request_id})`);console.log(body);Python
import os import requests res = requests.post( "https://mintrender.com/v1/templates", headers={"Authorization": f"Bearer {os.environ['MINTRENDER_KEY']}"}, json={ "name": "Blog OG image", "scene": { "version": 1, "width": 1200, "height": 630, "background": { "color": "#0f172a", }, "fonts": ["Inter:400,700"], "sizes": [ { "name": "square", "width": 1080, "height": 1080, "layers": { "title": { "y": 300, "h": 400, }, "logo": { "y": 960, }, }, }, ], "pages": [ { "layers": [ { "id": "title", "type": "text", "x": 80, "y": 120, "w": 1040, "h": 260, "text": "Default title", "font": "Inter", "weight": 700, "size": 72, "fit": "shrink", "minSize": 36, "lineHeight": 1.1, "color": "#ffffff", "maxLines": 3, "param": "title", }, { "id": "logo", "type": "image", "x": 80, "y": 500, "w": 160, "h": 60, "src": "", "fit": "contain", "param": "logo", }, { "id": "chart", "type": "chart", "x": 700, "y": 380, "w": 420, "h": 200, "chart": { "kind": "bar", "series": [ { "values": [3, 5, 8], }, ], "labels": ["Jan", "Feb", "Mar"], "textColor": "#cbd5e1", }, "param": "chart", }, ], }, ], }, }, timeout=120,)body = res.json()if not res.ok: raise RuntimeError(f"{body['error']['code']}: {body['error']['message']} ({body['error']['request_id']})")print(body)Publish the draft
curl
curl -X POST "https://mintrender.com/v1/templates/tpl_3k2jQ8xLm0P4nB7vR2sT/publish" \ -H "Authorization: Bearer $MINTRENDER_KEY"JavaScript
const res = await fetch("https://mintrender.com/v1/templates/tpl_3k2jQ8xLm0P4nB7vR2sT/publish", { method: "POST", headers: { Authorization: `Bearer ${process.env.MINTRENDER_KEY}`, },});const body = await res.json();if (!res.ok) throw new Error(`${body.error.code}: ${body.error.message} (${body.error.request_id})`);console.log(body);Python
import os import requests res = requests.post( "https://mintrender.com/v1/templates/tpl_3k2jQ8xLm0P4nB7vR2sT/publish", headers={"Authorization": f"Bearer {os.environ['MINTRENDER_KEY']}"}, timeout=120,)body = res.json()if not res.ok: raise RuntimeError(f"{body['error']['code']}: {body['error']['message']} ({body['error']['request_id']})")print(body){ "id": "tpl_3k2jQ8xLm0P4nB7vR2sT", "version": 1 }Get a template
curl
curl "https://mintrender.com/v1/templates/tpl_3k2jQ8xLm0P4nB7vR2sT" \ -H "Authorization: Bearer $MINTRENDER_KEY"JavaScript
const res = await fetch("https://mintrender.com/v1/templates/tpl_3k2jQ8xLm0P4nB7vR2sT", { method: "GET", headers: { Authorization: `Bearer ${process.env.MINTRENDER_KEY}`, },});const body = await res.json();if (!res.ok) throw new Error(`${body.error.code}: ${body.error.message} (${body.error.request_id})`);console.log(body);Python
import os import requests res = requests.get( "https://mintrender.com/v1/templates/tpl_3k2jQ8xLm0P4nB7vR2sT", headers={"Authorization": f"Bearer {os.environ['MINTRENDER_KEY']}"}, timeout=120,)body = res.json()if not res.ok: raise RuntimeError(f"{body['error']['code']}: {body['error']['message']} ({body['error']['request_id']})")print(body)List templates
Newest change first, at most 500. Each item has the fields of the template object without draft and versions.
curl
curl "https://mintrender.com/v1/templates" \ -H "Authorization: Bearer $MINTRENDER_KEY"JavaScript
const res = await fetch("https://mintrender.com/v1/templates", { method: "GET", headers: { Authorization: `Bearer ${process.env.MINTRENDER_KEY}`, },});const body = await res.json();if (!res.ok) throw new Error(`${body.error.code}: ${body.error.message} (${body.error.request_id})`);console.log(body);Python
import os import requests res = requests.get( "https://mintrender.com/v1/templates", headers={"Authorization": f"Bearer {os.environ['MINTRENDER_KEY']}"}, timeout=120,)body = res.json()if not res.ok: raise RuntimeError(f"{body['error']['code']}: {body['error']['message']} ({body['error']['request_id']})")print(body)Save the draft
scene is required, name is optional. The whole draft is replaced.
curl
curl -X PUT "https://mintrender.com/v1/templates/tpl_3k2jQ8xLm0P4nB7vR2sT/draft" \ -H "Authorization: Bearer $MINTRENDER_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"Blog OG image v2","scene":{"version":1,"width":1200,"height":630,"background":{"color":"#111827"},"fonts":["Inter:400,700"],"sizes":[{"name":"square","width":1080,"height":1080,"layers":{"title":{"y":300,"h":400},"logo":{"y":960}}}],"pages":[{"layers":[{"id":"title","type":"text","x":80,"y":120,"w":1040,"h":260,"text":"Default title","font":"Inter","weight":700,"size":72,"fit":"shrink","minSize":36,"lineHeight":1.1,"color":"#ffffff","maxLines":3,"param":"title"},{"id":"logo","type":"image","x":80,"y":500,"w":160,"h":60,"src":"","fit":"contain","param":"logo"},{"id":"chart","type":"chart","x":700,"y":380,"w":420,"h":200,"chart":{"kind":"bar","series":[{"values":[3,5,8]}],"labels":["Jan","Feb","Mar"],"textColor":"#cbd5e1"},"param":"chart"}]}]}}'JavaScript
const res = await fetch("https://mintrender.com/v1/templates/tpl_3k2jQ8xLm0P4nB7vR2sT/draft", { method: "PUT", headers: { Authorization: `Bearer ${process.env.MINTRENDER_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ name: "Blog OG image v2", scene: { version: 1, width: 1200, height: 630, background: { color: "#111827", }, fonts: ["Inter:400,700"], sizes: [ { name: "square", width: 1080, height: 1080, layers: { title: { y: 300, h: 400, }, logo: { y: 960, }, }, }, ], pages: [ { layers: [ { id: "title", type: "text", x: 80, y: 120, w: 1040, h: 260, text: "Default title", font: "Inter", weight: 700, size: 72, fit: "shrink", minSize: 36, lineHeight: 1.1, color: "#ffffff", maxLines: 3, param: "title", }, { id: "logo", type: "image", x: 80, y: 500, w: 160, h: 60, src: "", fit: "contain", param: "logo", }, { id: "chart", type: "chart", x: 700, y: 380, w: 420, h: 200, chart: { kind: "bar", series: [ { values: [3, 5, 8], }, ], labels: ["Jan", "Feb", "Mar"], textColor: "#cbd5e1", }, param: "chart", }, ], }, ], }, }),});const body = await res.json();if (!res.ok) throw new Error(`${body.error.code}: ${body.error.message} (${body.error.request_id})`);console.log(body);Python
import os import requests res = requests.put( "https://mintrender.com/v1/templates/tpl_3k2jQ8xLm0P4nB7vR2sT/draft", headers={"Authorization": f"Bearer {os.environ['MINTRENDER_KEY']}"}, json={ "name": "Blog OG image v2", "scene": { "version": 1, "width": 1200, "height": 630, "background": { "color": "#111827", }, "fonts": ["Inter:400,700"], "sizes": [ { "name": "square", "width": 1080, "height": 1080, "layers": { "title": { "y": 300, "h": 400, }, "logo": { "y": 960, }, }, }, ], "pages": [ { "layers": [ { "id": "title", "type": "text", "x": 80, "y": 120, "w": 1040, "h": 260, "text": "Default title", "font": "Inter", "weight": 700, "size": 72, "fit": "shrink", "minSize": 36, "lineHeight": 1.1, "color": "#ffffff", "maxLines": 3, "param": "title", }, { "id": "logo", "type": "image", "x": 80, "y": 500, "w": 160, "h": 60, "src": "", "fit": "contain", "param": "logo", }, { "id": "chart", "type": "chart", "x": 700, "y": 380, "w": 420, "h": 200, "chart": { "kind": "bar", "series": [ { "values": [3, 5, 8], }, ], "labels": ["Jan", "Feb", "Mar"], "textColor": "#cbd5e1", }, "param": "chart", }, ], }, ], }, }, timeout=120,)body = res.json()if not res.ok: raise RuntimeError(f"{body['error']['code']}: {body['error']['message']} ({body['error']['request_id']})")print(body)Copy a template
Copies the draft into a new template. The name is optional (default: "Copy of" and the old name). Versions are not copied.
curl
curl -X POST "https://mintrender.com/v1/templates/tpl_3k2jQ8xLm0P4nB7vR2sT/duplicate" \ -H "Authorization: Bearer $MINTRENDER_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"Blog OG image, dark"}'JavaScript
const res = await fetch("https://mintrender.com/v1/templates/tpl_3k2jQ8xLm0P4nB7vR2sT/duplicate", { method: "POST", headers: { Authorization: `Bearer ${process.env.MINTRENDER_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ name: "Blog OG image, dark", }),});const body = await res.json();if (!res.ok) throw new Error(`${body.error.code}: ${body.error.message} (${body.error.request_id})`);console.log(body);Python
import os import requests res = requests.post( "https://mintrender.com/v1/templates/tpl_3k2jQ8xLm0P4nB7vR2sT/duplicate", headers={"Authorization": f"Bearer {os.environ['MINTRENDER_KEY']}"}, json={ "name": "Blog OG image, dark", }, timeout=120,)body = res.json()if not res.ok: raise RuntimeError(f"{body['error']['code']}: {body['error']['message']} ({body['error']['request_id']})")print(body)Delete a template
Its renders and signed links answer 404 at once. Jobs of it that are still queued fail. Files already made stay until their time ends.
curl
curl -X DELETE "https://mintrender.com/v1/templates/tpl_3k2jQ8xLm0P4nB7vR2sT" \ -H "Authorization: Bearer $MINTRENDER_KEY"JavaScript
const res = await fetch("https://mintrender.com/v1/templates/tpl_3k2jQ8xLm0P4nB7vR2sT", { method: "DELETE", headers: { Authorization: `Bearer ${process.env.MINTRENDER_KEY}`, },});const body = await res.json();if (!res.ok) throw new Error(`${body.error.code}: ${body.error.message} (${body.error.request_id})`);console.log(body);Python
import os import requests res = requests.delete( "https://mintrender.com/v1/templates/tpl_3k2jQ8xLm0P4nB7vR2sT", headers={"Authorization": f"Bearer {os.environ['MINTRENDER_KEY']}"}, timeout=120,)body = res.json()if not res.ok: raise RuntimeError(f"{body['error']['code']}: {body['error']['message']} ({body['error']['request_id']})")print(body)The template object
{ "id": "tpl_3k2jQ8xLm0P4nB7vR2sT", "name": "Blog OG image", "sizes": ["main", "square"], "params": [ { "name": "title", "type": "text", "pages": [1], "default": "Default title" }, { "name": "logo", "type": "image", "pages": [1], "default": "" }, { "name": "chart", "type": "chart", "pages": [1], "default": { "kind": "bar", "series": [{ "values": [3, 5, 8] }], "…": "…" } } ], "newest_version": 1, "published_version": 1, "thumbnail": "https://files.mintrender.com/t/ws_9xQ2mL7kP4nB8vR3sT1a/tpl_3k2jQ8xLm0P4nB7vR2sT/1.webp", "created": "2026-11-01T09:00:00.000Z", "updated": "2026-11-01T09:05:00.000Z", "draft": { "version": 1, "width": 1200, "height": 630, "…": "…" }, "versions": [{ "version": 1, "created": "2026-11-01T09:05:00.000Z" }]}| Field | About |
|---|---|
id | tpl_ and 20 letters and digits. |
name | 1 to 100 characters. |
sizes | main and the extra size names, from the draft. |
params | The changeable layers of the published version (of the draft before the first publish): name, layer type, the pages that have it (from 1) and the value the template shows when data does not set it. |
newest_version | The number of the newest version. 0 before the first publish. |
published_version | The version renders use, or null before the first publish. |
thumbnail | A small WebP picture of page 1 of the published version (at most 400 px on its long side, without images from URLs), or null before the first publish and for a few seconds after a publish. |
created, updated | ISO 8601 UTC times. |
draft | The draft scene, with every default filled in. |
versions | Every version with the time it was made, newest first. |
The scene JSON
The editor writes the scene for you. You need it only to make or change templates with the API. This scene has a title that shrinks to fit, a logo, a bar chart and an extra square size:
{ "version": 1, "width": 1200, "height": 630, "background": { "color": "#0f172a" }, "fonts": [ "Inter:400,700" ], "sizes": [ { "name": "square", "width": 1080, "height": 1080, "layers": { "title": { "y": 300, "h": 400 }, "logo": { "y": 960 } } } ], "pages": [ { "layers": [ { "id": "title", "type": "text", "x": 80, "y": 120, "w": 1040, "h": 260, "text": "Default title", "font": "Inter", "weight": 700, "size": 72, "fit": "shrink", "minSize": 36, "lineHeight": 1.1, "color": "#ffffff", "maxLines": 3, "param": "title" }, { "id": "logo", "type": "image", "x": 80, "y": 500, "w": 160, "h": 60, "src": "", "fit": "contain", "param": "logo" }, { "id": "chart", "type": "chart", "x": 700, "y": 380, "w": 420, "h": 200, "chart": { "kind": "bar", "series": [ { "values": [ 3, 5, 8 ] } ], "labels": [ "Jan", "Feb", "Mar" ], "textColor": "#cbd5e1" }, "param": "chart" } ] } ]}Rules of a scene
- Units are px at 96 per inch. In a PDF, 1 px is 0.75 pt.
- Layers are drawn in order: the first at the back, the last on top. Groups hold their own layers.
- Every layer
idis unique in the whole scene. On one page, all layers with the sameparamhave the same type. - Fields that are not in the tables below are refused, so a typing error shows at once.
- Colours are hex (
#rgb,#rgba,#rrggbb,#rrggbbaa) ortransparent. - Fonts must be in the Google Fonts catalogue, with the weight you ask for. See Text and fonts.
- Image sources are
asset:<id>, an http(s) URL, or empty. See Images and assets. - Line and polygon points are fractions of the layer box, so they scale with it.
- At most 2,000 layers, groups 8 deep, 100 pages, 20 sizes with main, 100,000 text characters in all.
- The fields
duration,fps,start,end,in,out,keyframesand the layer typesvideoandaudioare kept for video and refused now (400reserved_for_video).
Every field
These tables come from the same schema that checks every scene, so they match the API. Required fields are marked.
The scene
| Field | Type | Default | Range | About |
|---|---|---|---|---|
version required | 1 | The format version. Always 1. | ||
width required | integer | 1 to 10,000 | The width of the main size, in px. | |
height required | integer | 1 to 10,000 | The height of the main size, in px. | |
background | object | The background of every page. No background is transparent in PNG, WebP and SVG. | ||
fonts | list of font spec | [] | at most 20 items | Font styles to load before drawing, like Inter or Inter:400,700i (i is italic). Every font a layer names is loaded anyway. |
sizes | list of object | [] | at most 19 items | Extra sizes besides main, each with its own layer changes. |
pages required | list of object | 1 to 100 items | The pages. Images draw the first page. A PDF has every page. |
background
| Field | Type | Default | Range | About |
|---|---|---|---|---|
color | colour | The page colour. A hex colour (#rgb, #rgba, #rrggbb, #rrggbbaa) or transparent. | ||
gradient | gradient | A linear or radial gradient over the page. | ||
image | image source | at most 2,048 characters | An image over the colour and gradient: asset:<id>, an http(s) URL, or empty. | |
fit | cover, contain, fill | "cover" | How the image fills the page: cover fills and crops, contain shows all of it, fill stretches it. |
A linear gradient
| Field | Type | Default | Range | About |
|---|---|---|---|---|
type required | "linear" | linear. | ||
angle | number | 0 | -360 to 360 | The direction in degrees: 0 is left to right, 90 is top to bottom. |
stops required | list of object | 2 to 16 items | The colours along the line. |
A radial gradient
| Field | Type | Default | Range | About |
|---|---|---|---|---|
type required | "radial" | radial. | ||
cx | number | 0.5 | 0 to 1 | The centre, left to right, as a fraction of the box. |
cy | number | 0.5 | 0 to 1 | The centre, top to bottom, as a fraction of the box. |
r | number | 0.5 | 0 to 2 | The radius as a fraction of the box. |
stops required | list of object | 2 to 16 items | The colours from the centre out. |
A gradient stop
| Field | Type | Default | Range | About |
|---|---|---|---|---|
offset required | number | 0 to 1 | Where the colour is, from 0 (start) to 1 (end). | |
color required | colour | A hex colour (#rgb, #rgba, #rrggbb, #rrggbbaa) or transparent. |
A page
| Field | Type | Default | Range | About |
|---|---|---|---|---|
background | object | Replaces the scene background on this page. | ||
layers required | list of layer | at most 2,000 items | The layers in drawing order: the first is at the back, the last on top. |
An extra size
| Field | Type | Default | Range | About |
|---|---|---|---|---|
name required | string | The size name used in sizes and signed links. Lowercase letters, digits, _ and -, and not main. | ||
width required | integer | 1 to 10,000 | The width in px. | |
height required | integer | 1 to 10,000 | The height in px. | |
layers | object of id → changes | {} | Layer id → the fields this size changes for that layer. |
A layer change in a size
| Field | Type | Default | Range | About |
|---|---|---|---|---|
x | number | -100,000 to 100,000 | Left edge in px for this size. | |
y | number | -100,000 to 100,000 | Top edge in px for this size. | |
w | number | 0 to 100,000 | Box width in px for this size. | |
h | number | 0 to 100,000 | Box height in px for this size. | |
rotation | number | -360 to 360 | Rotation in degrees for this size. | |
visible | boolean | Show or hide the layer in this size. | ||
size | number | 1 to 1,000 | Text size in px for this size (text layers). |
Fields of every layer
| Field | Type | Default | Range | About |
|---|---|---|---|---|
id required | string | Unique in the whole scene. Letters, digits, _ and -. Sizes and data never change it. | ||
name | string | at most 100 characters | A label for the editor's layer list. It does not change the output. | |
x | number | 0 | -100,000 to 100,000 | Left edge of the box in px. In a group, from the group's top-left corner. |
y | number | 0 | -100,000 to 100,000 | Top edge of the box in px. In a group, from the group's top-left corner. |
w required | number | 0 to 100,000 | Box width in px. | |
h required | number | 0 to 100,000 | Box height in px. | |
rotation | number | 0 | -360 to 360 | Degrees clockwise, about the box centre. |
opacity | number | 1 | 0 to 1 | 0 is invisible, 1 is solid. |
visible | boolean | true | false hides the layer. In data, true or false sets this. | |
locked | boolean | false | Editor only: the layer cannot be selected on the canvas. | |
shadow | object | A drop shadow behind the layer. | ||
blur | number | 0 | 0 to 250 | A Gaussian blur of the whole layer, in px. |
blend | normal, multiply, screen, overlay, darken, lighten | "normal" | How the layer mixes with the layers below it. | |
param | string | The name data uses to change this layer. Starts with a letter or _, then letters, digits and _. Layers on one page with the same param must be of the same type. | ||
type required | text, image, shape, chart, qr, barcode, group | The layer type. |
shadow
| Field | Type | Default | Range | About |
|---|---|---|---|---|
x | number | 0 | -1,000 to 1,000 | Offset to the right in px. |
y | number | 4 | -1,000 to 1,000 | Offset down in px. |
blur | number | 8 | 0 to 500 | Blur in px, like CSS box-shadow. |
color | colour | "#00000040" | A hex colour (#rgb, #rgba, #rrggbb, #rrggbbaa) or transparent. The default is black at 25%. |
text layer
| Field | Type | Default | Range | About |
|---|---|---|---|---|
text | string | "" | at most 10,000 characters | The text. A new line (\n) starts a new line. |
font | font family | "Inter" | A Google Fonts family name, like Inter or Noto Sans Arabic. | |
fallbackFonts | list of font family | [] | at most 4 items | Families tried in order for characters the font does not have, before the Noto fonts. |
weight | integer | 400 | 100 to 900, in steps of 100, a style the family has | The weight. The family must have it (with italic, if italic is set). |
italic | boolean | false | Italic. In a family without italic, the text is slanted by 12 degrees. | |
size | number | 32 | 1 to 1,000 | The font size in px. |
minSize | number | 1 to 1,000 | The smallest size for fit shrink. Default: a quarter of size, at least 4. Not bigger than size. | |
maxSize | number | 1 to 1,000 | The largest size for fit grow. Default: the box height, at most 1,000. Not smaller than size. | |
fit | none, shrink, grow | "none" | none keeps size. shrink makes the text smaller, down to minSize, until it fits the box and maxLines. grow makes it larger, up to maxSize, while it still fits. | |
lineHeight | number | 1.2 | 0.5 to 5 | Line height as a multiple of the size. |
letterSpacing | number | 0 | -100 to 1,000 | Extra space after each letter, in px. Below 0 brings letters closer. |
color | colour | "#000000" | The text colour. A hex colour (#rgb, #rgba, #rrggbb, #rrggbbaa) or transparent. | |
align | left, center, right | "left" | Horizontal place of each line in the box. | |
valign | top, middle, bottom | "top" | Vertical place of the text block in the box. | |
maxLines | integer | 1 to 1,000 | The most lines to draw. Text that does not fit ends with … on the last line. | |
uppercase | boolean | false | Draw the text in capitals. The data keeps its case. | |
markup | boolean | false | Read **bold**, *italic* and {color:#f00}red{/} in the text. A backslash keeps the next character as typed. Off by default, so * in data stays as typed. |
image layer
| Field | Type | Default | Range | About |
|---|---|---|---|---|
src | image source | "" | at most 2,048 characters | asset:<id> (an upload), an http(s) URL (PNG, JPEG, GIF or WebP), or empty for no image. |
fit | cover, contain, fill | "cover" | cover fills the box and crops, contain shows the whole image, fill stretches it. | |
focal | object | {"x":0.5,"y":0.5} | The point kept in view for cover, as fractions of the image: x from the left, y from the top. | |
radius | number or list of 4 numbers | 0 | 0 to 100,000 | Corner radius in px: one number, or four for top-left, top-right, bottom-right, bottom-left. |
filters | object | grayscale (0 to 1), brightness and contrast (1 is no change), blur in px. |
shape layer
| Field | Type | Default | Range | About |
|---|---|---|---|---|
shape | rect, ellipse, line, polygon | "rect" | rect, ellipse, line (needs stroke and exactly 2 points) or polygon (3 or more points). | |
fill | colour or gradient | A colour or a gradient. No fill draws no inside. | ||
stroke | object | The outline: color (required), width in px (default 1), dash (lengths in px, at most 8). | ||
radius | number or list of 4 numbers | 0 | 0 to 100,000 | Corner radius of a rect in px: one number, or four for top-left, top-right, bottom-right, bottom-left. |
points | list of [x, y] | at most 500 items | Line ends or polygon corners as [x, y] fractions of the box, so they scale with it. 0 to 1 is inside the box. |
chart layer
| Field | Type | Default | Range | About |
|---|---|---|---|---|
chart required | object | The chart: its kind, data and look. The table below lists its fields. |
chart
| Field | Type | Default | Range | About |
|---|---|---|---|---|
kind required | bar, line, area, pie, doughnut, sparkline, progress, number, scatter, histogram, boxplot, dotplot | bar, line, area, pie, doughnut, sparkline, progress (bar or ring), number (a big value with a trend arrow), scatter, histogram, boxplot or dotplot. | ||
series | list of object | [] | at most 20 items | The data series. Bar, line and area charts draw each one. Pie and doughnut use the first. |
labels | list of string | [] | at most 1,000 items | Category labels, one per value. |
orientation | vertical, horizontal | "vertical" | vertical or horizontal bars and box plots. | |
stacked | boolean | false | Stack bar or area series. | |
axis | boolean | true | Draw the axes. | |
grid | boolean | true | Draw grid lines. | |
valueLabels | boolean | false | Write each value on its bar or point. | |
legend | boolean | false | Draw a legend of the series names. | |
colors | list of colour | at most 20 items | Colours for the series or slices, in order. | |
value | number | -1e+15 to 1e+15 | progress and number: the value. Required for those kinds. | |
max | number | over 0 | progress: the value of a full bar or ring. | |
progressStyle | bar, ring | "bar" | progress: bar or ring. | |
previous | number | -1e+15 to 1e+15 | number: the earlier value, for the trend arrow. | |
format | object | {"decimals":0,"prefix":"","suffix":"","compact":false} | How numbers are written: decimals (0 to 6), prefix and suffix (at most 8 characters, like $ or %), compact (1.2k). | |
binCount | integer | 1 to 200 | histogram: the number of bins. Default: Sturges' rule, rounded to a round width. | |
binWidth | number | over 0 | histogram and dotplot: the bin width. | |
dotSize | number | 6 | 1 to 100 | scatter and dotplot: dot size in px. |
dotShape | circle, square, diamond | "circle" | scatter and dotplot: circle, square or diamond. | |
trendLine | boolean | false | scatter: a least-squares trend line per series. | |
showMean | boolean | false | boxplot: a mark at the mean. | |
font | font family | "Inter" | The label font, a Google Fonts family with a regular (400) style. | |
fontSize | number | 14 | 4 to 200 | Label size in px. |
textColor | colour | "#334155" | Label colour. A hex colour (#rgb, #rgba, #rrggbb, #rrggbbaa) or transparent. | |
gridColor | colour | "#e2e8f0" | Grid line colour. A hex colour (#rgb, #rgba, #rrggbb, #rrggbbaa) or transparent. |
A chart series
| Field | Type | Default | Range | About |
|---|---|---|---|---|
name | string | at most 100 characters | The series name for the legend. | |
values | list of number | [] | at most 1,000 items | The numbers. A box plot, histogram and dot plot take raw values. |
points | list of [x, y] | at most 1,000 items | scatter: [x, y] pairs. | |
color | colour | This series' colour. A hex colour (#rgb, #rgba, #rrggbb, #rrggbbaa) or transparent. |
qr layer
| Field | Type | Default | Range | About |
|---|---|---|---|---|
value | string | "" | at most 2,000 characters | The text or URL in the code. Too long for the error correction level is a 400. |
ecc | L, M, Q, H | "M" | Error correction: L, M, Q or H. A logo needs H. | |
color | colour | "#000000" | The dark modules. A hex colour (#rgb, #rgba, #rrggbb, #rrggbbaa) or transparent. | |
background | colour | "#ffffff" | The light modules. A hex colour (#rgb, #rgba, #rrggbb, #rrggbbaa) or transparent. | |
margin | integer | 2 | 0 to 10 | The quiet zone around the code, in modules. |
logo | image source | at most 2,048 characters | An image in the middle: asset:<id> or an http(s) URL. Needs ecc H. |
barcode layer
| Field | Type | Default | Range | About |
|---|---|---|---|---|
format | code128, ean13 | "code128" | code128 or ean13. An EAN-13 needs a valid check digit. | |
value | string | "" | at most 80 characters | The value to encode. |
color | colour | "#000000" | The bars. A hex colour (#rgb, #rgba, #rrggbb, #rrggbbaa) or transparent. | |
background | colour | "#ffffff" | The space between bars. A hex colour (#rgb, #rgba, #rrggbb, #rrggbbaa) or transparent. | |
showText | boolean | true | Write the value under the bars. | |
font | font family | "Inter" | The font of the text, a Google Fonts family with a regular (400) style. |
group layer
| Field | Type | Default | Range | About |
|---|---|---|---|---|
clip | boolean | false | Cut the children to the group box, with its radius. | |
radius | number or list of 4 numbers | 0 | 0 to 100,000 | Corner radius for clip, in px: one number or four. |
layers required | list of layer | The layers inside the group, placed from the group's top-left corner. Groups go at most 8 deep. |
Errors
| Status | Code | When |
|---|---|---|
| 400 | invalid_scene | The scene breaks a rule. field names the place, like scene.pages[0].layers[1].weight, and the message says what is wrong. |
| 400 | reserved_for_video | The scene uses a field kept for video. |
| 400 | invalid_request | name or scene is missing, or name is over 100 characters. |
| 402 | plan_limit | The plan's template limit is reached. |
| 404 | not_found | No such template in this workspace. |
| 409 | conflict | Two publishes of the same template at the same moment. Try again. |
| 413 | too_large | The body is over 2 MB. |
Seen MintRender used for content that breaks our terms? Report it. Questions about the API: support@mintrender.com, with the request id.