Generate Template Variants
Generate multiple size variants of a template using AI
Updated
/v1/studio/templates/{templateId}/generate-variantscurl -X POST "https://api.orshot.com/v1/studio/templates/<TEMPLATE_ID>/generate-variants" \
-H "Authorization: Bearer <ORSHOT_API_KEY>" \
-H "Content-Type: application/json" \
-d '{
"variants": [],
"page_number": 1,
"output": "<OUTPUT>"
}'const res = await fetch("https://api.orshot.com/v1/studio/templates/<TEMPLATE_ID>/generate-variants", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer <ORSHOT_API_KEY>",
},
body: JSON.stringify({
"variants": [],
"page_number": 1,
"output": "<OUTPUT>"
}),
});
const data = await res.json();import requests
response = requests.post(
"https://api.orshot.com/v1/studio/templates/<TEMPLATE_ID>/generate-variants",
headers={"Authorization": "Bearer <ORSHOT_API_KEY>"},
json={
"variants": [],
"page_number": 1,
"output": "<OUTPUT>"
},
)
data = response.json()$ch = curl_init("https://api.orshot.com/v1/studio/templates/<TEMPLATE_ID>/generate-variants");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer <ORSHOT_API_KEY>",
"Content-Type: application/json",
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
"variants" => [],
"page_number" => 1,
"output" => "<OUTPUT>"
]));
$data = json_decode(curl_exec($ch), true);
curl_close($ch);require "net/http"
require "json"
uri = URI("https://api.orshot.com/v1/studio/templates/<TEMPLATE_ID>/generate-variants")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer <ORSHOT_API_KEY>"
req["Content-Type"] = "application/json"
req.body = {
"variants": [],
"page_number": 1,
"output": "<OUTPUT>"
}.to_json
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(res.body)Enterprise Only
This endpoint is available only to first party clients like the Orshot MCP server and workspaces on the Enterprise plan. Check out Enterprise pricing to get access.
Generate multiple size variants of an existing studio template using AI-powered layout adaptation. The AI intelligently repositions and resizes elements to fit new dimensions while maintaining visual hierarchy and design integrity.
By default, generated variants are added as new pages to the source template. You can also create them as separate templates using the output parameter.
AI Credits
Each variant generated consumes 1 AI credit from your plan. Credits are validated before generation and deducted after successful completion.
Endpoint#
https://api.orshot.com/v1/studio/templates/:templateId/generate-variantsRequest#
// Add variants as new pages to the same template
await fetch("https://api.orshot.com/v1/studio/templates/12345/generate-variants", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer <ORSHOT_API_KEY>",
},
body: JSON.stringify({
variants: [
{ width: 1080, height: 1080 },
{ width: 1080, height: 1920 }
],
output: "pages"
}),
});// Create new templates for each variant
await fetch("https://api.orshot.com/v1/studio/templates/12345/generate-variants", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer <ORSHOT_API_KEY>",
},
body: JSON.stringify({
variants: [
{ width: 1080, height: 1080 },
{ width: 1080, height: 1920 },
{ width: 1200, height: 628 }
],
output: "templates"
}),
});{
"success": true,
"source_template_id": "12345",
"source_page": 1,
"source_page_id": "a1b2c3d4-5e6f-7890-abcd-ef1234567890",
"output_mode": "pages",
"variants": [
{
"variant_index": 0,
"width": 1080,
"height": 1080,
"page_index": 1,
"page_id": "generated-page-uuid-1",
"page_name": "Variant 1080x1080"
},
{
"variant_index": 1,
"width": 1080,
"height": 1920,
"page_index": 2,
"page_id": "generated-page-uuid-2",
"page_name": "Variant 1080x1920"
}
]
}{
"success": true,
"source_template_id": "12345",
"source_page": 1,
"source_page_id": "a1b2c3d4-5e6f-7890-abcd-ef1234567890",
"output_mode": "templates",
"variants": [
{
"variant_index": 0,
"width": 1080,
"height": 1080,
"template_id": 12346,
"template_name": "(1080x1080) Summer Sale"
},
{
"variant_index": 1,
"width": 1080,
"height": 1920,
"template_id": 12347,
"template_name": "(1080x1920) Summer Sale"
},
{
"variant_index": 2,
"width": 1200,
"height": 628,
"template_id": 12348,
"template_name": "(1200x628) Summer Sale"
}
]
}{
"success": true,
"source_template_id": "12345",
"source_page": 1,
"source_page_id": "a1b2c3d4-5e6f-7890-abcd-ef1234567890",
"output_mode": "pages",
"variants": [
{
"variant_index": 0,
"width": 1080,
"height": 1080,
"page_index": 1,
"page_id": "generated-page-uuid-1",
"page_name": "Variant 1080x1080",
"thumbnail_url": "https://storage.orshot.com/cloud/w-50/renders/thumbnails/sq1.png"
},
{
"variant_index": 1,
"width": 1080,
"height": 1920,
"page_index": 2,
"page_id": "generated-page-uuid-2",
"page_name": "Variant 1080x1920",
"thumbnail_url": "https://storage.orshot.com/cloud/w-50/renders/thumbnails/st1.png"
}
]
}{
"success": true,
"source_template_id": "12345",
"source_page": 1,
"source_page_id": "a1b2c3d4-5e6f-7890-abcd-ef1234567890",
"output_mode": "templates",
"variants": [
{
"variant_index": 0,
"width": 1080,
"height": 1080,
"template_id": 12346,
"template_name": "(1080x1080) Summer Sale",
"thumbnails": {
"success": true,
"pages": [
{
"page": 1,
"page_id": "tpl-1-page-uuid",
"thumbnail_url": "https://storage.orshot.com/cloud/w-50/renders/thumbnails/sq2.png",
"error": null
}
]
}
},
{
"variant_index": 1,
"width": 1080,
"height": 1920,
"template_id": 12347,
"template_name": "(1080x1920) Summer Sale",
"thumbnails": {
"success": true,
"pages": [
{
"page": 1,
"page_id": "tpl-2-page-uuid",
"thumbnail_url": "https://storage.orshot.com/cloud/w-50/renders/thumbnails/st2.png",
"error": null
}
]
}
}
]
}Rate Limits#
| Limit | Value |
|---|---|
| Requests per minute | 30 |
| Max variants per request | 10 |
The limit is 30 requests per minute per API key, shared by every /v1/studio template endpoint, including template reads. Renders are not counted.
URL Parameters#
| Parameter | Type | Required | Description |
|---|---|---|---|
templateId | Integer | Yes | The ID of the source template to generate variants from |
Request Body Parameters#
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
variants | Array | Yes | - | Array of target dimensions for variants |
page_number | Integer | No | 1 | Which page of the template to use as source |
output | String | No | "pages" | Output mode: "pages" or "templates" |
Variant Object Structure#
Each variant in the variants array should include:
| Field | Type | Required | Description |
|---|---|---|---|
width | Integer | Yes | Target width in pixels (1-5000) |
height | Integer | Yes | Target height in pixels (1-5000) |
name | String | No | Custom name for the generated page or template. Without it, a page is named Variant <width>x<height> and a template (<width>x<height>) <source template name> |
Output Modes#
| Mode | Description |
|---|---|
pages | Adds each variant as a new page to the source template |
templates | Creates a new template for each variant in the same workspace |
Query Parameters#
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
includeThumbnails | Boolean | No | false | When true, thumbnails are rendered for each newly created variant and returned inline in the response. When false or absent, thumbnails are generated asynchronously. Shape of the inline thumbnail depends on output mode (see below). |
Response Fields#
Common Fields#
| Field | Type | Description |
|---|---|---|
success | Boolean | Whether the operation was successful |
source_template_id | String | ID of the source template |
source_page | Integer | Page number used as source |
source_page_id | String | Stable id of the source page. Use this to reliably reference the source page even after template pages are reordered |
output_mode | String | The output mode used |
variants | Array | Array of generated variant results |
Variant Result Fields (varies by output mode)#
| Field | Output Mode | Type | Description |
|---|---|---|---|
variant_index | All | Integer | Index of this variant in the request |
width | All | Integer | Width of the variant |
height | All | Integer | Height of the variant |
page_index | pages | Integer | 0-based index of the new page in the template. Its page number is page_index + 1 |
page_id | pages | String | Id of the new page |
page_name | pages | String | Name of the new page |
thumbnail_url | pages | String|null | Only present when ?includeThumbnails=true. Public URL of the thumbnail PNG for this variant's page. null if rendering this page failed |
thumbnail_error | pages | String | Present only when ?includeThumbnails=true and this variant's thumbnail failed to render. Contains the error message |
thumbnails | templates | Object | Only present when ?includeThumbnails=true. See Thumbnails Object Structure below |
template_id | templates | Integer | ID of the newly created template |
template_name | templates | String | Name of the newly created template |
error | All | String | Error message if this variant was generated but could not be saved |
If the AI could not produce a size, that size is missing from variants and is not billed. Compare variant_index with your request to find it.
Thumbnails Object Structure#
When ?includeThumbnails=true is passed with output: "templates", each new template variant includes a nested thumbnails object:
| Field | Type | Description |
|---|---|---|
success | Boolean | true if at least one page rendered successfully |
pages[].page | Integer | 1-based page number |
pages[].page_id | String | Stable id of the page |
pages[].thumbnail_url | String|null | Public URL of the thumbnail PNG. null if this page failed |
pages[].error | String|null | Error message if this page failed. null on success |
For output: "pages", each variant entry gets a flat thumbnail_url field instead (the variant itself represents a single page), with an optional thumbnail_error field if rendering failed.
When ?includeThumbnails is not passed, thumbnails are generated asynchronously after the response. For pages mode, they appear on the source template; for templates mode, on each newly created template.
How AI Variant Generation Works#
The AI reads the source page, and its thumbnail when it has one, then places each layer on the new canvas. It changes only position, size, font size, rotation, image fit and text fit. Text, images and colors stay the same.
- Fill the canvas: The main image and the headline are enlarged to fill the new size, with about 20px margins. Hero images take roughly 40 to 50% of the height.
- Backgrounds: Background layers are stretched to cover the whole canvas.
- Groups: A shape behind a text layer moves with that text. Texts that shared a left, center or right edge keep sharing it.
- Text: Text is never cut off. Long text wraps into a taller box.
- Overlap: Layers are kept apart. Overlap from the source is kept only when it does not grow.
Supported Transformations#
| From | To | Behavior |
|---|---|---|
| Landscape | Square | Stacks layers top to bottom: headline, then subtext or logo, then the hero image |
| Landscape | Portrait | Same as square: stacked top to bottom, hero image usually the largest layer |
| Any other | Any other | No fixed strategy. Layers are moved and resized to fill the new canvas |
Error Responses#
| Status Code | Error | Description |
|---|---|---|
| 400 | Validation failed | Invalid variants array or dimensions |
| 400 | Invalid page_number | Specified page doesn't exist in template |
| 401 | Unauthorized | The OAuth token is invalid or expired. Refresh it |
| 403 | Insufficient AI credits | Not enough AI credits, your plan has no AI credits, or your subscription is inactive or paused. The response includes credits_required and credits_available |
| 403 | Access Forbidden | Invalid API key, your plan does not include this endpoint, or a payment is overdue (see code) |
| 404 | Template not found | The template isn't in your workspace |
| 423 | stage_locked | With output: "pages": an approval flow locks the template. See Approvals |
| 429 | Rate limit exceeded | Too many requests (max 30/min) |
| 500 | Internal server error | AI generation or server error |
| 503 | No variants generated | The AI returned no usable variant. No credits are used. Try again, or simplify the source page |
Best Practices#
- Source Quality: Use a well-designed source template for best AI results
- Batch Sizes: Generate up to 10 variants per request for optimal performance
- Output Selection:
- Use
pagesto keep all variants in one template (carousels) - Use
templatesfor independent templates that render separately
- Use
- Page Selection: For multi-page templates, specify which page to use as source
- Dimensions: AI works best when aspect ratio changes aren't too extreme
Ready to automate?
Start rendering images, PDFs and videos from your templates in under 2 minutes. Free plan, no credit card.
Get your API key- Image, PDF and video generation via API
- Visual editor with AI and smart layouts
- Zapier, Make, MCP and 40+ integrations
- White-label embed for your own app
- 100 free credits a month, no credit card required