MintRender
All docs pages

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

  1. Draft. Every template has one draft. The editor saves it as you work. PUT /v1/templates/{id}/draft replaces it. A draft never changes what renders and links show.

  2. Publish. POST /v1/templates/{id}/publish copies the draft into version 1, 2, 3 and so on. The newest version becomes the published version.

  3. 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" }]}
FieldAbout
idtpl_ and 20 letters and digits.
name1 to 100 characters.
sizesmain and the extra size names, from the draft.
paramsThe 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_versionThe number of the newest version. 0 before the first publish.
published_versionThe version renders use, or null before the first publish.
thumbnailA 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, updatedISO 8601 UTC times.
draftThe draft scene, with every default filled in.
versionsEvery 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 id is unique in the whole scene. On one page, all layers with the same param have 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) or transparent.
  • 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, keyframes and the layer types video and audio are kept for video and refused now (400 reserved_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

FieldTypeDefaultRangeAbout
version required1The format version. Always 1.
width requiredinteger1 to 10,000The width of the main size, in px.
height requiredinteger1 to 10,000The height of the main size, in px.
backgroundobjectThe background of every page. No background is transparent in PNG, WebP and SVG.
fontslist of font spec[]at most 20 itemsFont styles to load before drawing, like Inter or Inter:400,700i (i is italic). Every font a layer names is loaded anyway.
sizeslist of object[]at most 19 itemsExtra sizes besides main, each with its own layer changes.
pages requiredlist of object1 to 100 itemsThe pages. Images draw the first page. A PDF has every page.

background

FieldTypeDefaultRangeAbout
colorcolourThe page colour. A hex colour (#rgb, #rgba, #rrggbb, #rrggbbaa) or transparent.
gradientgradientA linear or radial gradient over the page.
imageimage sourceat most 2,048 charactersAn image over the colour and gradient: asset:<id>, an http(s) URL, or empty.
fitcover, contain, fill"cover"How the image fills the page: cover fills and crops, contain shows all of it, fill stretches it.

A linear gradient

FieldTypeDefaultRangeAbout
type required"linear"linear.
anglenumber0-360 to 360The direction in degrees: 0 is left to right, 90 is top to bottom.
stops requiredlist of object2 to 16 itemsThe colours along the line.

A radial gradient

FieldTypeDefaultRangeAbout
type required"radial"radial.
cxnumber0.50 to 1The centre, left to right, as a fraction of the box.
cynumber0.50 to 1The centre, top to bottom, as a fraction of the box.
rnumber0.50 to 2The radius as a fraction of the box.
stops requiredlist of object2 to 16 itemsThe colours from the centre out.

A gradient stop

FieldTypeDefaultRangeAbout
offset requirednumber0 to 1Where the colour is, from 0 (start) to 1 (end).
color requiredcolourA hex colour (#rgb, #rgba, #rrggbb, #rrggbbaa) or transparent.

A page

FieldTypeDefaultRangeAbout
backgroundobjectReplaces the scene background on this page.
layers requiredlist of layerat most 2,000 itemsThe layers in drawing order: the first is at the back, the last on top.

An extra size

FieldTypeDefaultRangeAbout
name requiredstringThe size name used in sizes and signed links. Lowercase letters, digits, _ and -, and not main.
width requiredinteger1 to 10,000The width in px.
height requiredinteger1 to 10,000The height in px.
layersobject of id → changes{}Layer id → the fields this size changes for that layer.

A layer change in a size

FieldTypeDefaultRangeAbout
xnumber-100,000 to 100,000Left edge in px for this size.
ynumber-100,000 to 100,000Top edge in px for this size.
wnumber0 to 100,000Box width in px for this size.
hnumber0 to 100,000Box height in px for this size.
rotationnumber-360 to 360Rotation in degrees for this size.
visiblebooleanShow or hide the layer in this size.
sizenumber1 to 1,000Text size in px for this size (text layers).

Fields of every layer

FieldTypeDefaultRangeAbout
id requiredstringUnique in the whole scene. Letters, digits, _ and -. Sizes and data never change it.
namestringat most 100 charactersA label for the editor's layer list. It does not change the output.
xnumber0-100,000 to 100,000Left edge of the box in px. In a group, from the group's top-left corner.
ynumber0-100,000 to 100,000Top edge of the box in px. In a group, from the group's top-left corner.
w requirednumber0 to 100,000Box width in px.
h requirednumber0 to 100,000Box height in px.
rotationnumber0-360 to 360Degrees clockwise, about the box centre.
opacitynumber10 to 10 is invisible, 1 is solid.
visiblebooleantruefalse hides the layer. In data, true or false sets this.
lockedbooleanfalseEditor only: the layer cannot be selected on the canvas.
shadowobjectA drop shadow behind the layer.
blurnumber00 to 250A Gaussian blur of the whole layer, in px.
blendnormal, multiply, screen, overlay, darken, lighten"normal"How the layer mixes with the layers below it.
paramstringThe 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 requiredtext, image, shape, chart, qr, barcode, groupThe layer type.

shadow

FieldTypeDefaultRangeAbout
xnumber0-1,000 to 1,000Offset to the right in px.
ynumber4-1,000 to 1,000Offset down in px.
blurnumber80 to 500Blur in px, like CSS box-shadow.
colorcolour"#00000040"A hex colour (#rgb, #rgba, #rrggbb, #rrggbbaa) or transparent. The default is black at 25%.

text layer

FieldTypeDefaultRangeAbout
textstring""at most 10,000 charactersThe text. A new line (\n) starts a new line.
fontfont family"Inter"A Google Fonts family name, like Inter or Noto Sans Arabic.
fallbackFontslist of font family[]at most 4 itemsFamilies tried in order for characters the font does not have, before the Noto fonts.
weightinteger400100 to 900, in steps of 100, a style the family hasThe weight. The family must have it (with italic, if italic is set).
italicbooleanfalseItalic. In a family without italic, the text is slanted by 12 degrees.
sizenumber321 to 1,000The font size in px.
minSizenumber1 to 1,000The smallest size for fit shrink. Default: a quarter of size, at least 4. Not bigger than size.
maxSizenumber1 to 1,000The largest size for fit grow. Default: the box height, at most 1,000. Not smaller than size.
fitnone, 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.
lineHeightnumber1.20.5 to 5Line height as a multiple of the size.
letterSpacingnumber0-100 to 1,000Extra space after each letter, in px. Below 0 brings letters closer.
colorcolour"#000000"The text colour. A hex colour (#rgb, #rgba, #rrggbb, #rrggbbaa) or transparent.
alignleft, center, right"left"Horizontal place of each line in the box.
valigntop, middle, bottom"top"Vertical place of the text block in the box.
maxLinesinteger1 to 1,000The most lines to draw. Text that does not fit ends with … on the last line.
uppercasebooleanfalseDraw the text in capitals. The data keeps its case.
markupbooleanfalseRead **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

FieldTypeDefaultRangeAbout
srcimage source""at most 2,048 charactersasset:<id> (an upload), an http(s) URL (PNG, JPEG, GIF or WebP), or empty for no image.
fitcover, contain, fill"cover"cover fills the box and crops, contain shows the whole image, fill stretches it.
focalobject{"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.
radiusnumber or list of 4 numbers00 to 100,000Corner radius in px: one number, or four for top-left, top-right, bottom-right, bottom-left.
filtersobjectgrayscale (0 to 1), brightness and contrast (1 is no change), blur in px.

shape layer

FieldTypeDefaultRangeAbout
shaperect, ellipse, line, polygon"rect"rect, ellipse, line (needs stroke and exactly 2 points) or polygon (3 or more points).
fillcolour or gradientA colour or a gradient. No fill draws no inside.
strokeobjectThe outline: color (required), width in px (default 1), dash (lengths in px, at most 8).
radiusnumber or list of 4 numbers00 to 100,000Corner radius of a rect in px: one number, or four for top-left, top-right, bottom-right, bottom-left.
pointslist of [x, y]at most 500 itemsLine 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

FieldTypeDefaultRangeAbout
chart requiredobjectThe chart: its kind, data and look. The table below lists its fields.

chart

FieldTypeDefaultRangeAbout
kind requiredbar, line, area, pie, doughnut, sparkline, progress, number, scatter, histogram, boxplot, dotplotbar, line, area, pie, doughnut, sparkline, progress (bar or ring), number (a big value with a trend arrow), scatter, histogram, boxplot or dotplot.
serieslist of object[]at most 20 itemsThe data series. Bar, line and area charts draw each one. Pie and doughnut use the first.
labelslist of string[]at most 1,000 itemsCategory labels, one per value.
orientationvertical, horizontal"vertical"vertical or horizontal bars and box plots.
stackedbooleanfalseStack bar or area series.
axisbooleantrueDraw the axes.
gridbooleantrueDraw grid lines.
valueLabelsbooleanfalseWrite each value on its bar or point.
legendbooleanfalseDraw a legend of the series names.
colorslist of colourat most 20 itemsColours for the series or slices, in order.
valuenumber-1e+15 to 1e+15progress and number: the value. Required for those kinds.
maxnumberover 0progress: the value of a full bar or ring.
progressStylebar, ring"bar"progress: bar or ring.
previousnumber-1e+15 to 1e+15number: the earlier value, for the trend arrow.
formatobject{"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).
binCountinteger1 to 200histogram: the number of bins. Default: Sturges' rule, rounded to a round width.
binWidthnumberover 0histogram and dotplot: the bin width.
dotSizenumber61 to 100scatter and dotplot: dot size in px.
dotShapecircle, square, diamond"circle"scatter and dotplot: circle, square or diamond.
trendLinebooleanfalsescatter: a least-squares trend line per series.
showMeanbooleanfalseboxplot: a mark at the mean.
fontfont family"Inter"The label font, a Google Fonts family with a regular (400) style.
fontSizenumber144 to 200Label size in px.
textColorcolour"#334155"Label colour. A hex colour (#rgb, #rgba, #rrggbb, #rrggbbaa) or transparent.
gridColorcolour"#e2e8f0"Grid line colour. A hex colour (#rgb, #rgba, #rrggbb, #rrggbbaa) or transparent.

A chart series

FieldTypeDefaultRangeAbout
namestringat most 100 charactersThe series name for the legend.
valueslist of number[]at most 1,000 itemsThe numbers. A box plot, histogram and dot plot take raw values.
pointslist of [x, y]at most 1,000 itemsscatter: [x, y] pairs.
colorcolourThis series' colour. A hex colour (#rgb, #rgba, #rrggbb, #rrggbbaa) or transparent.

qr layer

FieldTypeDefaultRangeAbout
valuestring""at most 2,000 charactersThe text or URL in the code. Too long for the error correction level is a 400.
eccL, M, Q, H"M"Error correction: L, M, Q or H. A logo needs H.
colorcolour"#000000"The dark modules. A hex colour (#rgb, #rgba, #rrggbb, #rrggbbaa) or transparent.
backgroundcolour"#ffffff"The light modules. A hex colour (#rgb, #rgba, #rrggbb, #rrggbbaa) or transparent.
margininteger20 to 10The quiet zone around the code, in modules.
logoimage sourceat most 2,048 charactersAn image in the middle: asset:<id> or an http(s) URL. Needs ecc H.

barcode layer

FieldTypeDefaultRangeAbout
formatcode128, ean13"code128"code128 or ean13. An EAN-13 needs a valid check digit.
valuestring""at most 80 charactersThe value to encode.
colorcolour"#000000"The bars. A hex colour (#rgb, #rgba, #rrggbb, #rrggbbaa) or transparent.
backgroundcolour"#ffffff"The space between bars. A hex colour (#rgb, #rgba, #rrggbb, #rrggbbaa) or transparent.
showTextbooleantrueWrite the value under the bars.
fontfont family"Inter"The font of the text, a Google Fonts family with a regular (400) style.

group layer

FieldTypeDefaultRangeAbout
clipbooleanfalseCut the children to the group box, with its radius.
radiusnumber or list of 4 numbers00 to 100,000Corner radius for clip, in px: one number or four.
layers requiredlist of layerThe layers inside the group, placed from the group's top-left corner. Groups go at most 8 deep.

Errors

StatusCodeWhen
400invalid_sceneThe scene breaks a rule. field names the place, like scene.pages[0].layers[1].weight, and the message says what is wrong.
400reserved_for_videoThe scene uses a field kept for video.
400invalid_requestname or scene is missing, or name is over 100 characters.
402plan_limitThe plan's template limit is reached.
404not_foundNo such template in this workspace.
409conflictTwo publishes of the same template at the same moment. Try again.
413too_largeThe 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.