Skip to content

POST /render

Renders a single image from a structured JSON payload. Returns the binary image bytes directly — not a URL to an image.

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

Authentication: Required (Authorization: Bearer oge_sk_...)

FieldTypeRequiredDefaultConstraints
formatstringYesog, twitter, square, linkedin, story
templatestringNo"default"default, social-card, blog-hero, email-banner, product-card, event, testimonial, github-repo, news-article, pricing, profile-card, announcement, or custom:<name> (Scale plan)
titlestringYesMax 200 characters
descriptionstringNoMax 500 characters
authorstringNoMax 100 characters
tagstringNoMax 50 characters
variablesobjectNo{}Arbitrary key-value pairs (Record<string, string>) for template interpolation
imagesobjectNo{}Named image URLs fetched server-side (Record<string, url>) for use in template image layers
style.accentstringNo"#38ef7d"Valid hex color (#rrggbb or #rgb)
style.fontstringNo"Outfit"One of the 8 supported fonts
style.titleSizenumberNo4828–72
style.descSizenumberNo2214–32
style.layoutstringNo"left"left, center, bottom
style.gradientstringNo"void"void, deep-sea, ember, forest, plum, slate
style.overlayOpacitynumberNo0.650.2–0.9 (used with background image)
style.autoFitbooleanNofalseAuto-adjust font sizes to prevent overflow
output.formatstringNo"png"png, webp (Starter+), pdf
output.qualitynumberNo901–100 (WebP only)
Terminal window
curl -X POST https://og-engine.com/render \
-H "Authorization: Bearer oge_sk_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"format": "og",
"template": "default",
"title": "Server-Side Text Layout Without a Browser",
"description": "Pure JS text measurement replaces Puppeteer. ~22ms renders ([benchmarked](/benchmarks/)), zero browser dependencies.",
"author": "Pretext Engine",
"tag": "Open Source",
"style": {
"accent": "#38ef7d",
"font": "Outfit",
"titleSize": 48,
"descSize": 22,
"layout": "left",
"gradient": "void"
},
"output": {
"format": "png"
}
}' \
--output card.png

Use variables to pass arbitrary template interpolation data. Templates can reference these values to personalise content dynamically:

Terminal window
curl -X POST https://og-engine.com/render \
-H "Authorization: Bearer oge_sk_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"format": "og",
"template": "profile-card",
"title": "{{name}}",
"description": "{{bio}}",
"variables": {
"name": "Jane Smith",
"bio": "Staff Engineer at Acme Corp",
"handle": "@janesmith",
"followers": "4,200"
},
"output": { "format": "png" }
}' \
--output profile.png

Use images to pass server-fetched images by name. Custom templates can reference them via source on image layers:

Terminal window
curl -X POST https://og-engine.com/render \
-H "Authorization: Bearer oge_sk_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"format": "og",
"template": "custom:product-showcase",
"title": "Wireless Noise-Cancelling Headphones",
"description": "Premium sound. All day comfort.",
"images": {
"hero": "https://example.com/product-hero.jpg",
"logo": "https://example.com/brand-logo.png"
},
"output": { "format": "png" }
}' \
--output product.png

Named images are fetched server-side at render time. Each URL must be publicly accessible and return a valid JPEG, PNG, or WebP image under 5MB.

To supply a background image, use multipart/form-data. The JSON payload goes in a field named config, the image in image:

Terminal window
curl -X POST https://og-engine.com/render \
-H "Authorization: Bearer oge_sk_YOUR_KEY" \
-F 'config={
"format": "og",
"template": "blog-hero",
"title": "Building in the Open",
"style": { "overlayOpacity": 0.65 }
}' \
-F 'image=@cover.jpg' \
--output card.png

Accepted image formats: JPEG, PNG, WebP. Maximum size: 5MB.

On success, the response body is the raw binary image. The HTTP status is 200.

HeaderExampleDescription
Content-Typeimage/pngMIME type (image/png, image/webp, or application/pdf)
X-Cachemisshit if served from image cache, miss otherwise
X-Render-Time-Ms2.34Server-side render time in milliseconds
X-Title-Lines2Number of lines the title was wrapped to
X-Desc-Lines3Number of lines the description was wrapped to
X-Layout-Overflowfalsetrue if any text was truncated with ellipsis
X-RateLimit-Limit500Monthly render quota
X-RateLimit-Remaining483Renders remaining this month
X-RateLimit-Reset1735689600Unix timestamp (seconds) of next quota reset

If your title or description is too long to fit within the max lines for the chosen format, OG Engine truncates the last visible line and appends . The response header X-Layout-Overflow: true signals this occurred.

To prevent truncation, use /validate before rendering to check fit, and adjust font size or shorten the text accordingly.

StatusCodeCause
400missing_fieldformat or title not provided
400invalid_formatformat is not one of the allowed values
400invalid_fontstyle.font is not a supported font
400invalid_fileBackground image is too large or corrupt
401unauthorizedMissing or invalid API key
402plan_requiredWebP output requested on Free plan
429rate_limitedMonthly quota exceeded
500server_errorInternal error
0.0ms|1300× vs Puppeteer
Accent
Font
Layout
Gradient
48
22