Learn how to generate dynamic images using our API
Complete OpenAPI specification with all endpoints
View the auto-generated OpenAPI documentation for detailed endpoint specifications, request/response schemas, and authentication details.
The fastest way to a working template: open Templates → New Template → Browse Starter Templates and click one.
It's cloned into your account and opens in the editor — tweak it or use it as-is.
Copy your new Template ID from the editor URL or the templates list.
Then create an API key (step 2) and render it in seconds with POST /api/generate (step 3), passing your Template ID plus any layer overrides.
Want a public, no-auth image URL instead? A cloned template is private by default, so
first enable App → URL Access (allow all domains or whitelist yours),
then use the public /api/render URL (step 4).
Navigate to Templates → New Template
Choose a preset (e.g., OG Image 1200×630px)
Add layers with semantic names: title, subtitle, logo
Save the template and note your Template ID
Go to App → API Keys → Create New Key to generate your authentication token
Use layer overrides to dynamically customize your template:
const response = await fetch('https://yourdomain.com/api/generate', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
templateId: 'your-template-id',
layers: {
title: { text: 'My Blog Post Title' },
subtitle: {
text: 'Published on Jan 15',
fontSize: 24,
color: '#666666'
},
logo: {
image_url: 'https://example.com/logo.png',
width: 120,
height: 120
}
},
format: 'png', // 'png' (default), 'jpeg', or 'webp'
quality: 80 // 1-100 for jpeg/webp; ignored for png
})
});
const { success, imageUrl, cached, warnings } = await response.json();
// warnings (optional) lists any image that failed to load or an
// unresolved asset reference — the render still returns 200.
// Use imageUrl in your application The public /api/render endpoint always returns PNG; use /api/generate with format for JPEG or WebP output.
Each override targets a layer by its name and must match the shape for that
layer's type. Any subset of fields works — override just fontSize without text, or just objectFit without image_url. The full typed
schemas (TextLayerOverrides, ImageLayerOverrides, ShapeLayerOverrides) are in the API Reference.
Text layers text, fontSize, fontWeight, fontStyle, fontFamily, color,
textAlign, verticalAlign, lineHeight, letterSpacing,
textTransform, textDecoration, backgroundColor,
borderRadius, width, height, rotation
Image layers image_url, objectFit, objectPosition, borderRadius,
border, opacity, width, height, rotation
Shape layers fill, opacity, borderWidth, borderColor, borderStyle,
borderRadius, width, height, rotation Strict validation: a malformed override — a bare value instead of an
object ({ "title": "Hello" } instead of { "title": { "text": "Hello" } }),
an unknown field, or a wrong type — is rejected with a 400 that names the
offending layer and field. Text content is set with text (not content), image sources with image_url (not src).
Warnings: an override that names a layer that doesn't exist in the
template, or carries fields the layer's type can't use, renders fine but is reported in
the response's warnings array (or the X-Render-Warnings header on /render) as override_ignored.
Upload an image, then reference it in any image_url override (or a template
layer's src) with its asset:<id> reference.
The renderer resolves it from your account server-side, so you never need a public URL. You
can also pass a base64 data:image/* URI directly. Prefer a UI? Manage your
uploads and copy references under App → Assets.
# 1. Upload a file (multipart). 'name' is optional.
curl -X POST https://yourdomain.com/api/uploads \
-H 'Authorization: Bearer YOUR_API_KEY' \
-F '[email protected]' \
-F 'name=hero shot'
# → 201 { "id": "...", "name": "hero shot", "reference": "asset:...", ... }
# 2. List your uploads to find their ids / references later
curl https://yourdomain.com/api/uploads \
-H 'Authorization: Bearer YOUR_API_KEY'
# → { "uploads": [{ "id": "...", "name": "hero shot", "reference": "asset:..." }], "total": 1 }
# 3. Reference it when generating (works in image_url overrides and layer src)
{
"templateId": "your-template-id",
"layers": {
"photo": { "image_url": "asset:PASTE_UPLOAD_ID" }
}
}Prefer a typed client over raw fetch? The official SDK wraps every endpoint and
returns a { data, error } result — no
manual URL building or response parsing.
npm install @renderfast/client import { createClient, postApiGenerate } from '@renderfast/client';
const client = createClient({
baseUrl: 'https://yourdomain.com',
headers: {
Authorization: 'Bearer ' + process.env.RENDERFAST_API_KEY
}
});
const { data, error } = await postApiGenerate({
client,
body: {
templateId: 'your-template-id',
layers: {
title: { text: 'My Blog Post Title' },
subtitle: { text: 'Published on Jan 15', fontSize: 24, color: '#666666' }
}
}
});
if (error) throw error;
console.log(data.imageUrl); // { success, imageUrl, cached, generationTimeMs } The same generated functions cover the rest of the API — getApiTemplates, postApiTemplatesByIdClone, getApiUploads, and more. Each takes { client, body?, path?, query? } and returns { data, error }.
For public templates, generate images directly via URL with JSON-encoded layer data:
# Simple text override
/api/render?templateId=uuid&layers={"title":{"text":"Hello World"}}
# Multiple layer overrides
/api/render?templateId=uuid&layers={"title":{"text":"Blog Title"},"subtitle":{"text":"By John Doe"},"logo":{"image_url":"https://example.com/avatar.jpg"}}
# Use in HTML
<meta property="og:image" content="https://yourdomain.com/api/render?templateId=..." /> Note: The public endpoint doesn't require authentication and doesn't count toward rate limits. Perfect for social media OG images!
Update existing templates via API for programmatic template management, bulk updates, or CI/CD integration:
const response = await fetch('https://yourdomain.com/api/templates/your-template-id', {
method: 'PUT',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'Updated Template Name',
description: 'Updated description',
jsonData: {
canvas: { width: 1200, height: 630, background: '#ffffff' },
layers: [
// Your updated layer definitions
],
variables: []
}
})
});
const updatedTemplate = await response.json(); Updatable fields: name, description, jsonData, previewUrl
Override text content and styling:
{
"title": {
"text": "New content",
"fontSize": 48,
"fontWeight": "bold",
"color": "#000000",
"textAlign": "center",
"lineHeight": 1.2,
"letterSpacing": -1,
"textTransform": "uppercase"
}
}Override image source and display properties:
{
"avatar": {
"image_url": "https://example.com/avatar.jpg",
"width": 120,
"height": 120,
"objectFit": "cover",
"borderRadius": 60,
"opacity": 1
}
}Rate limits are based on your subscription plan and reset monthly:
Note: Cached responses don't count toward your limit. The public /api/render endpoint also doesn't count
toward rate limits.
Questions about the API or template creation? Contact our support team