Skip to content

API Quickstart

This guide takes you from zero to a saved, rendered image. You’ll create a key, find a template, discover its variables, and generate a personalized image.

  • A Zandovi account with at least one saved template that contains a variable (e.g. a coupon with {{first_name}} and {{discount_code}}). See Creating a Variable if you don’t have one yet.
  • An API key — create one in Settings → API Keys (see Authentication).

Set your key as an environment variable so it stays out of your code:

Terminal window
export ZANDOVI_API_KEY="your_api_key"

Template IDs are UUIDs. The quickest way to get one is from the Designer URL when the template is open (…/templates/019463b8-…). You can also list them via the API:

Terminal window
# List your projects
curl https://app.zandovi.com/api/v1/projects \
-H "X-Api-Key: $ZANDOVI_API_KEY"
# List templates in a project
curl https://app.zandovi.com/api/v1/projects/019463b8-abcd-7890-1234-ef1234567890/templates \
-H "X-Api-Key: $ZANDOVI_API_KEY"

Before generating, ask the template what variables it accepts. This tells you the exact variable names, their types, and which are required:

Terminal window
curl https://app.zandovi.com/api/v1/templates/$TEMPLATE_ID \
-H "X-Api-Key: $ZANDOVI_API_KEY"

The response includes a variables array — use each name as a key in the next step. See Templates & schema discovery for the full response shape.

Send the variable values and write the binary response to a file.

Terminal window
curl -X POST https://app.zandovi.com/api/v1/templates/$TEMPLATE_ID/generate \
-H "X-Api-Key: $ZANDOVI_API_KEY" \
-H "Content-Type: application/json" \
-o coupon.png \
-d '{
"variables": {
"first_name": "Sarah",
"discount_code": "VIP30"
},
"format": "png",
"options": { "scale": 2 }
}'
const res = await fetch(
`https://app.zandovi.com/api/v1/templates/${process.env.TEMPLATE_ID}/generate`,
{
method: "POST",
headers: {
"X-Api-Key": process.env.ZANDOVI_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
variables: { first_name: "Sarah", discount_code: "VIP30" },
format: "png",
options: { scale: 2 },
}),
}
);
if (!res.ok) throw new Error(`Render failed: ${res.status} ${await res.text()}`);
const buffer = Buffer.from(await res.arrayBuffer());
await require("node:fs/promises").writeFile("coupon.png", buffer);
import os, requests
template_id = os.environ["TEMPLATE_ID"]
res = requests.post(
f"https://app.zandovi.com/api/v1/templates/{template_id}/generate",
headers={"X-Api-Key": os.environ["ZANDOVI_API_KEY"]},
json={
"variables": {"first_name": "Sarah", "discount_code": "VIP30"},
"format": "png",
"options": {"scale": 2},
},
)
res.raise_for_status()
with open("coupon.png", "wb") as f:
f.write(res.content)

The response body is the image — there is no hosted URL to fetch afterwards. Save it, attach it to an email, or stream it to your storage.

Every generation response includes quota headers:

X-Quota-Limit: 10000
X-Quota-Remaining: 9999
X-Quota-Reset: 2026-07-01T00:00:00Z

If you exceed your monthly quota you’ll get a 429 — see Errors, quotas & rate limits.