API Overview
The Zandovi public API lets you generate personalized images from your saved templates directly from your own code — e-commerce platforms, email systems, print-on-demand workflows, and automations.
The API is render-focused: you design and save templates in the app, then call the API to produce images. By default each generate call returns the image bytes directly. Set delivery to link and the same call publishes the render and returns a temporary public URL instead — see Share Links.
Base URL
Section titled “Base URL”https://app.zandovi.com/api/v1All endpoints are HTTPS-only and versioned under /api/v1.
What you can do
Section titled “What you can do”| Capability | Endpoint | Notes |
|---|---|---|
| List your projects | GET /projects | Paginated |
| List templates in a project | GET /projects/{projectId}/templates | Paginated |
| Inspect a template’s variables | GET /templates/{templateId} | Use this to discover what to send |
| Generate an image | POST /templates/{templateId}/generate | Returns binary image data, or a public share link with delivery: "link" |
| Generate in bulk | POST /batch-jobs | One template + many rows → one async job; see Batch Rendering |
| Track batch jobs | GET /batch-jobs, GET /batch-jobs/{jobId} | List and poll job status |
| Inspect per-row outcomes | GET /batch-jobs/{jobId}/items | Paginated: what each submitted row produced, or why it failed |
| Fetch batch results | GET /batch-jobs/{jobId}/result | Download URL or ZIP stream; the archive is kept 30 days |
| Cancel / delete a batch job | POST /batch-jobs/{jobId}/cancel, DELETE /batch-jobs/{jobId} | Cancelling refunds unrendered rows |
| Be told when a batch finishes | callbackUrl on the submit body | Signed POST to your endpoint instead of polling; see Completion Callbacks |
| List your share links | GET /shares | Paginated, newest first |
| Revoke a share link | DELETE /shares/{shareId} | Deletes the published image |
Templates are authored visually in the app — the public API renders them; it doesn’t design them. To render many images from one template, submit a batch job rather than looping the generate endpoint: one request, one ZIP, and validation before you’re charged. The in-app batch tools drive the same engine from a CSV.
Authentication
Section titled “Authentication”Every request is authenticated with an API key sent in the X-Api-Key header:
X-Api-Key: your_api_keySee Authentication for how to create and manage keys.
Request format
Section titled “Request format”- Send
Content-Type: application/jsonfor request bodies. - All timestamps in responses are ISO 8601 in UTC:
2026-06-17T10:00:00Z. - Template and project IDs are UUIDs, e.g.
019463b8-1234-7890-abcd-ef1234567890.
Response format
Section titled “Response format”GETendpoints return JSON.POST /generatereturns the raw image bytes with the matchingContent-Type(image/png,image/jpeg,image/webp, orapplication/pdf) and aContent-Disposition: attachmentheader — write the response body straight to a file or stream it onward.POST /generatewithdelivery: "link"returnsapplication/jsoncarrying the public URL and its expiry instead. See Share Links.POST /batch-jobsis asynchronous — it returns202 Acceptedwith a job ID immediately; poll the job and fetch the ZIP when it completes. See Batch Rendering.
Errors
Section titled “Errors”Error responses use RFC 9457 application/problem+json:
{ "type": "about:blank", "title": "Variable validation failed", "status": 400, "code": "VALIDATION_ERROR", "detail": "Required variable 'discount_code' was not supplied.", "requestId": "req_01J9Z..."}See Errors, quotas & rate limits for the full status-code and error-code reference.
Status codes
Section titled “Status codes”| Code | Meaning |
|---|---|
200 | Success (image or JSON) |
202 | Batch job accepted — poll for the result, or wait for its callback |
400 | Validation error — missing or invalid variables / body |
401 | Missing or invalid API key |
403 | Share links not available on this plan, or the active-link cap is reached |
404 | Template, project, share link, or batch job not found / not accessible |
409 | Batch conflict — idempotency key reused, result not ready, or job still active |
410 | The batch result archive passed its 30-day retention window |
429 | Monthly quota or rate limit exceeded |
502 / 503 | Rendering service error / temporarily unavailable |
Quotas & rate limits
Section titled “Quotas & rate limits”Image generation consumes your organization’s monthly render quota. Every generate response carries X-Quota-Limit, X-Quota-Remaining, and X-Quota-Reset headers, and requests are additionally subject to a short-term rate limit. See Errors, quotas & rate limits.
Versioning
Section titled “Versioning”The API is versioned in the URL (/api/v1). Backwards-incompatible changes ship under a new version; we aim to keep a previous version available for at least 6 months after a new one is released.