Skip to content

Image API

Turn a template and a set of field values into a finished still. Image renders resolve synchronously — you get the CDN URL in the response, with nothing to poll.

How image rendering works#

An image render is a pure function of a template and the values you pass it. The template fixes the layout, the fonts and everything you did not expose as a field; the request fills in the rest. The same request produces the same pixels every time, which is what makes it safe to re-run a campaign months later.

Rendering happens in real headless Chrome, so web fonts, CSS grid, text wrapping, gradients andobject-fit all behave exactly as they do in a browser.

Call GET /api/v1/templates/:id first. It returns the field schema — every key, its type and whether it is required — which is what a valid values object has to match. It also returns canRender: a render only ever names a template your own workspace has published. A design from the public library is copied in first with POST /api/v1/templates/:id/duplicate, and you render the copy.

Formats and output#

FormatUse it forHonours quality
pngThe default. Lossless, and the only one people reach for when transparency matters.No
jpegPhotographs, where the file size difference is the whole point. No alpha channel.Yes
webpThe web. Smaller than both at the same quality, with alpha.Yes
avifSmaller still, at the cost of a slower encode. Alpha as well.Yes
pdfPrint. One page sized exactly to the canvas, backgrounds included.No

jpg is accepted as an alias for jpeg. WebP and AVIF are re-encoded from a lossless capture rather than asked of the browser, which is why output.quality genuinely applies to them.

output.scalemultiplies the template’s pixel dimensions, from 1 to 4 — a 1080×1080 template at scale: 2 renders 2160×2160. Your plan sets the real ceiling, and a render above it is refused rather than quietly downscaled. Each scale step is priced as its own render, because it is one.

output.transparent drops the canvas background so the output has a real alpha channel. It applies to png, webp and avif; JPEG and PDF have nowhere to put it and ignore the flag.

A render that succeeded but could not do everything asked of it comes back with a warnings array rather than an error — a background removal that could not run is the current example. The image is there and is correct in every other respect.

What the engine draws#

Layout happens in real headless Chrome, so web fonts, text wrapping, gradients, object-fit, blend modes, clip paths and shadows are the browser’s own implementations rather than approximations of them. The stylesheet that turns a layer into CSS is the same module the editor’s canvas imports, so the preview and the render cannot disagree about what a layer means.

The full layer reference — shapes, effects, photo adjustments, curved text, background removal — is in Templates and fields. Everything documented there is drawn by this endpoint.

Endpoints#

Every endpoint below runs live against this deployment. Paste a test-mode key into the runner and send a real request — test renders never spend credits, though each plan caps how many you get per month.

Render an image

POST/api/v1/renderAPI keyrenders:write
Renders a template to a still. Image renders resolve synchronously — the response carries the finished CDN URL rather than a job to poll. A template with a live-capture layer also returns `extracted`: whatever that layer read off the page it photographed, keyed as the template named it. A key whose selector matched nothing comes back `null`.

Cost 1 image credit per render, per output scale.

Body parameters

templateId
stringrequired
Id or slug of the template to render.
values
objectrequired
Field key → value, matching the template schema from GET /v1/templates/:id. Any {{PLACEHOLDER}} in the template also accepts a value under its own key, whether or not it is a declared field.
output.format
"png" | "jpeg" | "webp" | "avif" | "pdf"optional
Defaults to png. `jpg` is accepted as an alias for `jpeg`. WebP and AVIF are re-encoded from a lossless capture, so `quality` genuinely applies to them.
output.scale
numberoptional
1–4. Multiplies the template’s pixel dimensions. Your plan sets the ceiling.
output.quality
numberoptional
1–100. Applies to jpeg, webp and avif; ignored by png and pdf.
output.transparent
booleanoptional
Drop the canvas background so the output has a real alpha channel. png, webp and avif only — jpeg and pdf have nowhere to put it.
{
  "templateId": "diwali-sale-story",
  "values": {
    "headline": "Diwali Sale",
    "offer": "50% OFF",
    "product": "https://cdn.acme.com/lamp.jpg"
  },
  "output": {
    "format": "png",
    "scale": 2
  }
}

Try it

/api/v1/render
Show as cURL
curl -X POST "https://pixbix.app/api/v1/render" \
  -H "x-api-key: pk_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{ "templateId": "diwali-sale-story", "values": { "headline": "Diwali Sale", "offer": "50% OFF", "product": "https://cdn.acme.com/lamp.jpg" }, "output": { "format": "png", "scale": 2 } }'

Render a batch

POST/api/v1/render/batchAPI keyrenders:write
Runs up to 25 renders in one call and returns a row per render. Each row is an ordinary render request — a template and its values, or a raw edit — merged over an optional `defaults` object, so a batch of one template with different values per row need not repeat the template id. ONE ROW NEVER FAILS THE BATCH: rows report their own success or error and the response is 200 either way, so a bad value in row 12 does not throw away the eleven renders already produced. Image rows come back finished, with their URL; video rows come back queued, to be polled or waited for on a webhook exactly as a single render is. No row is ever refused for being busy: your plan’s concurrent-render allowance decides how many run at once, and the rest queue.

Cost Charged per row, at the same rate as a single render. A batch that runs out of credit part-way keeps what it paid for and reports INSUFFICIENT_CREDITS on the rest.

Body parameters

items
object[]required
The renders, 1–25 of them. Each takes the same fields as POST /v1/render: templateId, values, edit, output, callback. A row may also carry its own `idempotencyKey`, which is what makes re-running a partly failed batch safe.
defaults
objectoptional
Merged UNDER every row, so a row can override any of it. The usual use is one templateId and one output block for the whole batch.
callback
stringoptional
Webhook for every row that does not name its own. Video rows fire it when they finish encoding.
{
  "defaults": {
    "templateId": "diwali-sale-story",
    "output": {
      "format": "png",
      "scale": 2
    }
  },
  "items": [
    {
      "values": {
        "headline": "Diwali Sale",
        "offer": "50% OFF"
      },
      "idempotencyKey": "row-1"
    },
    {
      "values": {
        "headline": "Year End",
        "offer": "30% OFF"
      },
      "idempotencyKey": "row-2"
    }
  ]
}

Try it

/api/v1/render/batch
Show as cURL
curl -X POST "https://pixbix.app/api/v1/render/batch" \
  -H "x-api-key: pk_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{ "defaults": { "templateId": "diwali-sale-story", "output": { "format": "png", "scale": 2 } }, "items": [ { "values": { "headline": "Diwali Sale", "offer": "50% OFF" }, "idempotencyKey": "row-1" }, { "values": { "headline": "Year End", "offer": "30% OFF" }, "idempotencyKey": "row-2" } ] }'

Estimate a render

POST/api/v1/render/estimateAPI keyrenders:read
Prices a render without running it. Use this to show a cost before committing, or to check a payload validates.

Body parameters

templateId
stringrequired
Id or slug of the template to render.
values
objectrequired
Field key → value, matching the template schema from GET /v1/templates/:id. Any {{PLACEHOLDER}} in the template also accepts a value under its own key, whether or not it is a declared field.
{
  "templateId": "diwali-sale-story",
  "values": {
    "headline": "Diwali Sale",
    "offer": "50% OFF"
  },
  "output": {
    "format": "mp4",
    "resolution": "fhd"
  }
}

Try it

/api/v1/render/estimate
Show as cURL
curl -X POST "https://pixbix.app/api/v1/render/estimate" \
  -H "x-api-key: pk_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{ "templateId": "diwali-sale-story", "values": { "headline": "Diwali Sale", "offer": "50% OFF" }, "output": { "format": "mp4", "resolution": "fhd" } }'

List renders

GET/api/v1/renderAPI keyrenders:read
Most recent first. Covers both image and video renders.

Query parameters

page
numberoptional
Page number, from 1.
limit
numberoptional
Rows per page, 1–100. Defaults to 20.
sort
stringoptional
Column to order by: createdAt, finishedAt, status, kind, renderMs, creditCost. Defaults to `createdAt`.
order
"asc" | "desc"optional
Sort direction. Defaults to `desc` for dates and counts.
search
stringoptional
Case-insensitive match across the render id, the engine job id. Up to 128 characters.
status
stringoptional
queued, fetching, rendering, saving, done, failed or cancelled. Comma-separate several to match any of them.
kind
"image" | "video" | "audio"optional
Restrict to one engine.
templateId
stringoptional
Only renders from this template.
createdFrom
stringoptional
ISO date. Only renders queued on or after it.
createdTo
stringoptional
ISO date. Only renders queued on or before it.
Response
{
  "success": true,
  "data": [
    {
      "id": "rnd_8f2a1c",
      "status": "done",
      "kind": "image",
      "credits": 1
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 20,
    "total": 1,
    "totalPages": 1,
    "hasMore": false,
    "sort": "createdAt",
    "order": "desc"
  }
}

Try it

/api/v1/render?page=1&limit=20&sort=createdAt&order=desc&search=diwali&status=done&kind=image&templateId=diwali-sale-story&createdFrom=2026-08-01&createdTo=2026-08-31
Show as cURL
curl -X GET "https://pixbix.app/api/v1/render?page=1&limit=20&sort=createdAt&order=desc&search=diwali&status=done&kind=image&templateId=diwali-sale-story&createdFrom=2026-08-01&createdTo=2026-08-31" \
  -H "x-api-key: pk_live_your_key"

Get a render

GET/api/v1/render/:idAPI keyrenders:read
Fetch one render by id. This is the endpoint to poll when you are not using webhooks. A finished render may carry `warnings`: the output exists and follows the edit exactly, but something in the edit probably does not say what you meant. It carries `extracted` when the template photographed a live page and read values off it — the same values a `render.completed` webhook delivers, kept on the render so they are still there whenever you come back for them. `format` and `codec` describe what was DELIVERED, which is not always what was asked for: some codecs cannot be muxed into some containers, so a request for ProRes in MP4 comes back as MOV and a transparent MP4 comes back as WebM. A `warnings` entry says so when it happens. Read `format` rather than the format you requested when naming the file or choosing a player — a MOV carrying ProRes is an editing master and no browser will play it.

Path parameters

id
stringrequired
Render id.
Response
{
  "success": true,
  "data": {
    "id": "rnd_8f2a1c",
    "status": "done",
    "progress": 100,
    "url": "https://cdn.pixbix.app/render/org_4c1d/rnd_8f2a1c/render.png",
    "format": "png",
    "codec": null,
    "warnings": [],
    "extracted": {
      "headline": "Diwali Sale — 50% off everything",
      "price": "₹1,299"
    }
  }
}

Try it

/api/v1/render/rnd_8f2a1c
Show as cURL
curl -X GET "https://pixbix.app/api/v1/render/rnd_8f2a1c" \
  -H "x-api-key: pk_live_your_key"

Cancel a render

POST/api/v1/render/:id/cancelAPI keyrenders:write
Stops a queued or in-flight render. Credits for a cancelled render are refunded.

Path parameters

id
stringrequired
Render id.
Response
{
  "success": true,
  "data": {
    "id": "rnd_8f2a1c",
    "status": "cancelled"
  }
}

Cancelling is destructive — run it against a render id you own from your own client.

Generate from a template

POST/api/v1/generateAPI keyrenders:write
Fills a template's fields and returns a finished image. The template-driven counterpart to /v1/render: send field values by key rather than a full design. Accepts JSON, or multipart when a field takes an uploaded file — use the field key as the file's form name. Templates you can reach are your own plus anything published to the public library.

Cost 1 credit per generated image. Test keys render watermarked and cost nothing.

Body parameters

templateId
stringrequired
Template to render.
fields
objectoptional
Field values keyed by the template's field keys. May also be a JSON string. Keys matching a field can be sent at the top level instead.
format
stringoptional
png, jpeg, webp or pdf. Pass `binary` to receive image bytes rather than a hosted URL.
{
  "templateId": "tpl_7d21",
  "fields": {
    "headline": "Season sale",
    "price": "₹1,499"
  },
  "format": "png"
}

Try it

/api/v1/generate
Show as cURL
curl -X POST "https://pixbix.app/api/v1/generate" \
  -H "x-api-key: pk_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{ "templateId": "tpl_7d21", "fields": { "headline": "Season sale", "price": "₹1,499" }, "format": "png" }'

Every endpoint#

The rest of the public API, grouped by what it renders. Endpoints outside this page link to the reference that documents them.

Postman#

Both documents are generated from the same catalogue as this page, so an import is never out of date. In Postman choose Import → Link and paste either URL.

Collection

Every public v1 endpoint, foldered by API, plus webhook management — with example bodies and saved responses.

https://pixbix.app/postman/collection.jsonOpen JSON

Environment

baseUrl plus empty, secret-typed apiKey and authToken. Fill the credentials in Postman, not here.

https://pixbix.app/postman/environment.jsonOpen JSON