Share Links
By default the generate endpoint returns raw image bytes. Setting delivery to
link publishes the render instead and returns a JSON body carrying a public URL and its expiry.
Useful when the image has to be fetched by something that wants a URL — an <img> tag in a
transactional email, a Slack message, a webhook payload, or an automation platform that handles JSON
more comfortably than binary.
Requesting a link
Section titled “Requesting a link”Add delivery to the generate request body:
| Field | Type | Default | Description |
|---|---|---|---|
delivery | string | binary | binary returns raw image/PDF bytes. link publishes the render and returns a JSON share link. |
Omitting delivery keeps the existing behaviour exactly — existing integrations need no changes.
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" \ -d '{ "variables": { "first_name": "Sarah", "discount_code": "VIP30" }, "format": "png", "delivery": "link" }'{ "id": "019a4c31-8e2f-7b10-9c44-1d5e77b0a913", "url": "https://img.zandovi.com/s/8f3c2ad9e1b74c05.png", "templateId": "019463b8-1234-7890-abcd-ef1234567890", "templateName": "Autumn voucher", "mimeType": "image/png", "fileSize": 41982, "source": "API", "createdAt": "2026-08-24T09:00:00Z", "expiresAt": "2026-09-23T09:00:00Z"}The X-Request-Id, X-Template-Id, and X-Timestamp response headers are returned as usual.
Share link fields
Section titled “Share link fields”| Field | Type | Description |
|---|---|---|
id | UUID | Identifier for the link — pass it to the revoke endpoint |
url | string | The public URL. Serve it directly; it needs no auth |
templateId | UUID | null | Template the render came from |
templateName | string | null | Template name captured at share time — survives the template being deleted later |
mimeType | string | image/png, image/jpeg, image/webp, or application/pdf |
fileSize | integer | Size of the published object, in bytes |
source | string | API for links created with a key, DESIGNER for links created in the app |
createdAt | string | ISO 8601 UTC |
expiresAt | string | ISO 8601 UTC — after this the object is deleted and the URL stops resolving |
Store expiresAt alongside whatever references the URL. When it lapses there is nothing to renew —
generate the image again and share the new result.
Listing links
Section titled “Listing links”GET /api/v1/shares| Query parameter | Default | Description |
|---|---|---|
page | 0 | Zero-based page index |
size | 20 | Items per page |
Returns the links created with this API key’s account, newest first. Ordering is stable across pages.
curl https://app.zandovi.com/api/v1/shares?page=0&size=20 \ -H "X-Api-Key: $ZANDOVI_API_KEY"{ "data": [ /* share link objects, as above */ ], "pagination": { "page": 0, "size": 20, "totalElements": 143, "totalPages": 8 }}There is no history view. An expired link stays listed only until the next cleanup pass removes it.
Revoking a link
Section titled “Revoking a link”DELETE /api/v1/shares/{shareId}Deletes the published object and its record, so the URL stops resolving. Responds 204 No Content.
curl -X DELETE https://app.zandovi.com/api/v1/shares/$SHARE_ID \ -H "X-Api-Key: $ZANDOVI_API_KEY"Revocation is permanent — there is no undo, and the link cannot be restored. Published images are cached at the edge for up to five minutes; revoking purges that cache, but a copy may still be served briefly.
Scoping
Section titled “Scoping”An API key can only see and revoke the links its own account created. Any other link in the
organization responds 404, the same as a link that doesn’t exist.
This differs from the app, where a workspace Owner or Admin can manage every link in the organization. Revoking or deleting an API key does not revoke the links created with it.
Errors
Section titled “Errors”| Status | code | Cause |
|---|---|---|
403 | SHARING_NOT_AVAILABLE_ON_PLAN | The organization’s plan does not include share links |
403 | SHARE_LINK_LIMIT_REACHED | The organization is at its cap of active links — revoke one or upgrade |
404 | SHARE_NOT_FOUND | No such link, or it belongs to another account |
502 | SHARE_UPLOAD_FAILED | The render succeeded but could not be published — nothing was created, safe to retry |
502 | SHARE_REVOKE_FAILED | The object could not be deleted — the link may still resolve, retry |
503 | SHARING_UNAVAILABLE | Share storage is temporarily unavailable |
A SHARE_UPLOAD_FAILED leaves nothing behind, so retrying is safe — but it re-renders and consumes
another render. If you need the bytes regardless, retry with delivery: "binary".
See Errors, quotas & rate limits for the response body format and general retry guidance.
Limits
Section titled “Limits”Retention (how long a link lives) and the cap on simultaneously active links both vary by plan. Current values are on the Zandovi pricing page and the Plans page in the app.
The active-link cap is checked when a link is created. If a plan change leaves you above the cap, existing links keep working — you just can’t create new ones until you’re back under it.
When not to use share links
Section titled “When not to use share links”Share links are temporary hosting. They’re the wrong tool when the image has to persist:
- Anything referenced from a long-lived page — OG images in a page’s
<head>, product imagery, avatars. Usedelivery: "binary"and store the bytes yourself. - Anything that must be private. There is no per-viewer access control.
- Anything needing custom cache or CORS headers. The published objects use fixed headers.