Images and assets
An image in a template comes from an uploaded asset (asset:img_…) or from a URL that we fetch. Upload images that many renders use, like logos. Use URLs for images that change per render, like product photos.
Upload a file
Send multipart/form-data with the file in the field file and an optional name (at most 200 characters; default: the file name).
curl
curl -X POST "https://mintrender.com/v1/assets" \ -H "Authorization: Bearer $MINTRENDER_KEY" \ -F "file=@logo.png" \ -F "name=Logo"JavaScript
import { readFile } from "node:fs/promises"; const form = new FormData();form.append("file", new Blob([await readFile("logo.png")]), "logo.png");form.append("name", "Logo");const res = await fetch("https://mintrender.com/v1/assets", { method: "POST", headers: { Authorization: `Bearer ${process.env.MINTRENDER_KEY}` }, body: form,});const asset = await res.json();if (!res.ok) throw new Error(`${asset.error.code}: ${asset.error.message}`);console.log(asset.src); // asset:img_…Python
import os import requests with open("logo.png", "rb") as f: res = requests.post( "https://mintrender.com/v1/assets", headers={"Authorization": f"Bearer {os.environ['MINTRENDER_KEY']}"}, files={"file": ("logo.png", f)}, data={"name": "Logo"}, timeout=120, )asset = res.json()if not res.ok: raise RuntimeError(f"{asset['error']['code']}: {asset['error']['message']}")print(asset["src"]) # asset:img_…Upload from a URL
Send JSON with url. We fetch it once and store the bytes. The default name is the last part of the URL's path.
curl
curl -X POST "https://mintrender.com/v1/assets" \ -H "Authorization: Bearer $MINTRENDER_KEY" \ -H "Content-Type: application/json" \ -d '{"url":"https://example.com/logo.png","name":"Logo"}'JavaScript
const res = await fetch("https://mintrender.com/v1/assets", { method: "POST", headers: { Authorization: `Bearer ${process.env.MINTRENDER_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ url: "https://example.com/logo.png", name: "Logo", }),});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/assets", headers={"Authorization": f"Bearer {os.environ['MINTRENDER_KEY']}"}, json={ "url": "https://example.com/logo.png", "name": "Logo", }, 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 asset object
{ "id": "img_9Lk2mQ8xP0aB4nC7vR2s", "kind": "image", "name": "Logo", "mime": "image/png", "bytes": 18211, "sha256": "3f8a…", "width": 640, "height": 240, "src": "asset:img_9Lk2mQ8xP0aB4nC7vR2s", "source_url": null, "created": "2026-11-01T09:30:00.000Z"}| Field | About |
|---|---|
id | img_… for an image, csv_… for a CSV. |
kind | image or csv. |
mime | The type read from the bytes: image/png, image/jpeg, image/gif, image/webp, image/svg+xml or text/csv. |
bytes, sha256 | The stored file's size and hash. |
width, height | Pixels of an image. null for a CSV. |
src | Use this as an image value in data or as src in a scene. |
source_url | The URL it was fetched from, or null for a file upload. |
Use a CSV's id as csv_asset in a batch.
Types and sizes
| Type | Limit | Notes |
|---|---|---|
| PNG, JPEG, GIF, WebP | 20 MB, 16 megapixels | We read the type from the bytes. The file name does not matter. |
| SVG | 20 MB | Cleaned on upload: scripts, foreignObject, event attributes and every outside reference are removed. It needs a width and height, or a viewBox. It is drawn as an image. |
| CSV | 5 MB | UTF-8 text with no NUL bytes. |
An image over 16 megapixels is refused with image_too_large. The editor makes such images smaller in your browser before it uploads them. Font files cannot be uploaded: fonts come from Google Fonts.
Image URLs in data
| Asset (asset:img_…) | URL in data | |
|---|---|---|
| Types | PNG, JPEG, GIF, WebP, SVG | PNG, JPEG, GIF, WebP |
| Size | 20 MB, 16 megapixels | 20 MB, 16 megapixels |
| When we read it | Stored once, at upload | Fetched when a render needs it. Signed links reuse a fetch for an hour. |
| Same file again | Yes, while the template and data stay the same | Yes, when the URL gives the same bytes |
We fetch URLs with these rules: http or https on port 80 or 443, no user name or password, a public host (no localhost, .local, .internal and similar, and no private or reserved IP address), an answer within 10 seconds, at most 3 redirects, each checked again. Our requests send User-Agent: MintRender/1.0 (+https://mintrender.com).
List, download and delete
List assets, newest first, at most 500. Filter with kind=image or kind=csv.
curl
curl "https://mintrender.com/v1/assets?kind=image" \ -H "Authorization: Bearer $MINTRENDER_KEY"JavaScript
const res = await fetch("https://mintrender.com/v1/assets?kind=image", { 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/assets?kind=image", 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)Download a stored file with GET /v1/assets/{id}/file and your key. Delete an asset:
curl
curl -X DELETE "https://mintrender.com/v1/assets/img_9Lk2mQ8xP0aB4nC7vR2s" \ -H "Authorization: Bearer $MINTRENDER_KEY"JavaScript
const res = await fetch("https://mintrender.com/v1/assets/img_9Lk2mQ8xP0aB4nC7vR2s", { 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/assets/img_9Lk2mQ8xP0aB4nC7vR2s", 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)A delete is refused with 409 in_use while a version of a template that is not deleted uses the asset. The message names the template and version. Before a delete, GET /v1/assets/{id}/uses lists up to 100 templates whose draft or versions use it:
curl
curl "https://mintrender.com/v1/assets/img_9Lk2mQ8xP0aB4nC7vR2s/uses" \ -H "Authorization: Bearer $MINTRENDER_KEY"JavaScript
const res = await fetch("https://mintrender.com/v1/assets/img_9Lk2mQ8xP0aB4nC7vR2s/uses", { 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/assets/img_9Lk2mQ8xP0aB4nC7vR2s/uses", 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){ "templates": [ { "id": "tpl_3k2jQ8xLm0P4nB7vR2sT", "name": "Blog OG image", "draft": true, "versions": true } ]}Errors
| Status | Code | When |
|---|---|---|
| 400 | invalid_request | No file field, or JSON without url. |
| 400 | unsupported_type | Not a PNG, JPEG, GIF, WebP, SVG or UTF-8 CSV. |
| 400 | invalid_svg | The SVG cannot be read or has no size. |
| 400 | image_too_large | The image is over 16 megapixels. |
| 400 | url_refused | We do not fetch this URL. The message says why. |
| 400 | url_failed | The URL answered with a status that is not 2xx. |
| 402 | plan_limit | The workspace's uploads would pass 500 MB on Free or 10 GB on a paid plan. |
| 404 | not_found | No such asset. |
| 409 | in_use | A version of a template that is not deleted uses the asset. |
| 413 | too_large | An image over 20 MB or a CSV over 5 MB. |
| 451 | frozen | The workspace is frozen. |
Seen MintRender used for content that breaks our terms? Report it. Questions about the API: support@mintrender.com, with the request id.