Skip to content

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.

Most calls render: 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. The API can also author templates from your own code or an AI agent: validate a design, render a preview, then save it — see Authoring Templates.

https://app.zandovi.com/api/v1

All endpoints are HTTPS-only and versioned under /api/v1.

CapabilityEndpointNotes
Check your account & plan limitsGET /accountOrganization, quota, scopes, and the plan’s limits
List your projectsGET /projectsPaginated
List templates in a projectGET /projects/{projectId}/templatesPaginated
Inspect a template’s variablesGET /templates/{templateId}Use this to discover what to send
Generate an imagePOST /templates/{templateId}/generateReturns binary image data, or a public share link with delivery: "link"
Generate in bulkPOST /batch-jobsOne template + many rows → one async job; see Batch Rendering
Track batch jobsGET /batch-jobs, GET /batch-jobs/{jobId}List and poll job status
Inspect per-row outcomesGET /batch-jobs/{jobId}/itemsPaginated: what each submitted row produced, or why it failed
Fetch batch resultsGET /batch-jobs/{jobId}/resultDownload URL or ZIP stream; the archive is kept 30 days
Cancel / delete a batch jobPOST /batch-jobs/{jobId}/cancel, DELETE /batch-jobs/{jobId}Cancelling refunds unrendered rows
Be told when a batch finishescallbackUrl on the submit bodySigned POST to your endpoint instead of polling; see Completion Callbacks
List your share linksGET /sharesPaginated, newest first
Revoke a share linkDELETE /shares/{shareId}Deletes the published image
Manage your image libraryGET, POST /images, GET, DELETE /images/{id}, GET /images/{id}/previewUpload by file or URL and reference as zandovi://images/{id}; free. See Image Library
Read the design formatGET /design-reference and sub-routesField tables, fonts, icons, presets, examples; free. See Design Reference
Validate a designPOST /designs/validateFree; every violation with a path, code and hint. See Authoring Templates
Preview a designPOST /designs/renderOne render; returns the image and the render receipt a write needs
Create a templatePOST /templatesPrivate template in one of your projects, from a previewed design
Read a template’s designGET /templates/{templateId}?include=canvasThe stored canvasData, to edit and patch back
Update / delete a templatePATCH, DELETE /templates/{templateId}Templates your account created, in the app or through the API; Idempotency-Key honoured
Browse a template’s versionsGET /templates/{templateId}/versions, GET .../versions/{version}The last 10 saved designs, with thumbnails; free. See Version history
Restore a versionPOST /templates/{templateId}/versions/{version}/restoreSaves the old design as a new version; free, no render
Create a projectPOST /projectsPrivate project to hold templates

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. Templates can be designed in the app or written as JSON and saved through the authoring endpoints; the MCP server lets an AI assistant do the latter for you.

Requests authenticate with an API key sent in the X-Api-Key header, or an OAuth 2.1 access token sent as an Authorization: Bearer header:

X-Api-Key: your_api_key
Authorization: Bearer your_access_token

Send exactly one of the two: a request carrying both is rejected. See Authentication for how to create an API key and how the OAuth flow works.

  • Send Content-Type: application/json for 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.
  • GET endpoints return JSON.
  • POST /generate returns the raw image bytes with the matching Content-Type (image/png, image/jpeg, image/webp, or application/pdf) and a Content-Disposition: attachment header — write the response body straight to a file or stream it onward.
  • POST /generate with delivery: "link" returns application/json carrying the public URL and its expiry instead. See Share Links.
  • POST /batch-jobs is asynchronous — it returns 202 Accepted with a job ID immediately; poll the job and fetch the ZIP when it completes. See Batch Rendering.
  • POST /designs/render returns JSON with the preview image as base64 and a renderReceipt; POST /templates and POST /projects return 201 Created with a Location header. See Authoring Templates.

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": "3f2b8c1e-7d4a-4b9e-9c2f-5a6d8e1b0c47"
}

See Errors, quotas & rate limits for the full status-code and error-code reference.

CodeMeaning
200Success (image or JSON)
202Batch job accepted — poll for the result, or wait for its callback
400Validation error: missing or invalid variables / body, an unknown request property, a plan limit on projects or templates, or both X-Api-Key and Authorization: Bearer sent on the same request
401Missing, invalid, or revoked credential (API key or bearer token)
402The output would exceed your plan’s maxOutputPixels (OUTPUT_SIZE_LIMIT_EXCEEDED; details has outputPixels, maxOutputPixels, plan). Nothing is charged. Lower scale/outputDpi or upgrade
403Share links not available on this plan, the active-link cap is reached, the credential lacks a required scope, or the template or project belongs to another account
404Template, project, share link, or batch job not found / not accessible
409Batch conflict — idempotency key reused, result not ready, or job still active; an authoring write whose Idempotency-Key is still being processed
410The batch result archive passed its 30-day retention window
422A design failed validation, is too large to preview, lacks a valid render receipt, would break the template’s variables, or an Idempotency-Key was reused with a different body — see Authoring Templates; an image supplied for an image variable couldn’t be loaded (IMAGE_VARIABLE_UNREACHABLE)
429Monthly quota or rate limit exceeded
502 / 503Rendering service error / temporarily unavailable

Image generation, including design previews, consumes your organization’s monthly render quota; validation, every template or project write and version restores are free. 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.

GET /account returns the organization, account and quota behind the presenting credential (API key or bearer token), its effective scopes, plus a limits object with the caps that apply to the current plan:

FieldTypeDescription
maxOutputPixelsnumberLargest image size the plan may render, in total pixels (width × height) — see Generating images
shareRetentionDaysnumber | nullDays a public share link is kept before it expires; null when the plan doesn’t permit public sharing — see Share Links
maxActiveSharesnumber | nullMaximum number of active public share links the organization may hold at once; null when the plan has no limit
maxBatchRowsPerJobnumberMaximum rows accepted in a single batch job

Check these before you call the API — for example, to keep a scale/outputDpi combination under maxOutputPixels, or an expiresInDays under shareRetentionDays — instead of discovering the limit from a rejected request.

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.