Skip to content

POST /render/batch

Renders multiple images in a single API call. Each item is an independent render request. Returns a ZIP archive containing all generated images.

POST https://og-engine.com/render/batch

Authentication: Required (Authorization: Bearer oge_sk_...) Plan: Pro and Scale only

{
"items": [
{
"format": "og",
"title": "Introduction to Bun",
"description": "A fast all-in-one JavaScript runtime.",
"tag": "Tutorial"
},
{
"format": "twitter",
"template": "social-card",
"title": "OG Engine 1.0 Released",
"style": { "accent": "#f59e0b" }
}
]
}
FieldTypeRequiredConstraintsDescription
itemsarrayYes1–100 itemsArray of render request objects

Each item in items is a full render request body. See POST /render for the complete field reference. Items can have different formats, templates, and styles.

Maximum items per request: 100

Terminal window
curl -X POST https://og-engine.com/render/batch \
-H "Authorization: Bearer oge_sk_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"items": [
{ "format": "og", "title": "Post One", "tag": "Tutorial" },
{ "format": "og", "title": "Post Two", "style": { "accent": "#e91e63" } },
{ "format": "twitter", "template": "social-card", "title": "Announcement" }
]
}' \
--output images.zip

On success, the response body is a ZIP archive. HTTP status: 200.

images.zip
├── 0.png ← first item (index 0)
├── 1.png ← second item (index 1)
├── 2.png ← third item (index 2)
└── errors.json ← present only if any items failed

Images are named {index}.png (or {index}.webp if the item specified WebP output). The index matches the item’s position in the items array, starting at 0.

HeaderExampleDescription
Content-Typeapplication/zipAlways ZIP for batch responses
X-Total-Render-Time-Ms18.34Total server-side render time for all items
X-Batch-Count3Number of successfully rendered images
X-Batch-Errors0Number of items that failed to render

If some items fail (for example, an invalid font on item 2), the other items still render successfully. The ZIP is returned with the successful images, and errors.json documents the failures:

[
{
"index": 2,
"error": "invalid_font",
"message": "Font 'Roboto' is not available.",
"details": { "field": "style.font", "provided": "Roboto" }
}
]

errors.json is only present when at least one item failed. Always check for its presence before assuming all images were generated.

If all items fail, the API returns a 400 JSON error response instead of a ZIP.

Each successfully rendered item in the batch consumes one render from your monthly quota. A batch of 50 items uses 50 renders. Failed items do not consume quota.

The X-RateLimit-Remaining header in the response reflects the quota after the batch completes.

StatusCodeCause
400invalid_requestitems is missing, empty, or not an array
400invalid_requestitems contains more than 100 entries
401unauthorizedMissing or invalid API key
402plan_requiredBatch endpoint not available on Free or Starter plan
429rate_limitedNot enough quota remaining to complete the batch
500server_errorInternal error
import { OGEngine } from '@atypical-consulting/og-engine-sdk'
const og = new OGEngine(process.env.OG_ENGINE_KEY!)
const zipBuffer = await og.batch([
{ format: 'og', title: 'First Post', tag: 'Blog' },
{ format: 'og', title: 'Second Post', tag: 'Blog' },
{ format: 'og', title: 'Third Post', tag: 'Blog' },
])
// Save or process the ZIP
await Bun.write('images.zip', zipBuffer)