Key concepts
Response format
Every response on the API is wrapped in a consistent envelope.
Success
{
"success": true,
"data": { /* ... */ }
}Error
{
"success": false,
"statusCode": 403,
"code": "INSUFFICIENT_SCOPE",
"message": "This credential is missing the render:write scope",
"path": "/v1/embed/emb_123/templates/tpl_123/render",
"timestamp": "2026-09-08T12:00:00.000Z"
}INSUFFICIENT_SCOPE only happens to an embed session or MCP connection — an API key has no scope choice and always holds every scope.
A render response — the shape returned inside data — looks like:
Render response
{
"id": "ren_789",
"renderId": "rnd_456",
"templateId": "tpl_123",
"format": "png",
"url": "https://.../ren_789.png",
"byteSize": 482113,
"width": 1080,
"height": 1080,
"createdAt": "...",
"credits": { "charged": 1, "balanceAfter": 1879 },
"isEmpty": false
}| Param | Type | Notes |
|---|---|---|
| id | string | Id of this file (ren_…). |
| renderId | string | The render request this file belongs to (rnd_…) — what GET /v1/renders/:renderId, rerender and edit sessions take. |
| templateId | string | The template that was rendered. |
| format | "png" | "jpeg" | "pdf" | |
| url | string | Hosted URL of the rendered file. |
| byteSize | number | |
| width / height | number | Pixel dimensions of the rendered file. |
| createdAt | string (ISO 8601) | |
| credits.charged | number | 0 for a retry with the same idempotencyKey. An identical render without one is a new request and is charged. |
| credits.balanceAfter | number | Remaining credits on the plan. |
| isEmpty | boolean | True when the page had nothing to draw. It still renders, as a blank image, so files always match the pages. |
Requesting allPages with a raster format (png/jpeg) returns an array under pages, next to the request's renderId, instead of a single render object — one entry per page, in page order, each shaped like the response above.
Was this page helpful?