Create Studio Template
Create a single studio template programmatically via API
Updated
/v1/studio/templates/createcurl -X POST "https://api.orshot.com/v1/studio/templates/create" \
-H "Authorization: Bearer <ORSHOT_API_KEY>" \
-H "Content-Type: application/json" \
-d '{
"name": "<NAME>",
"canvas_width": 1,
"canvas_height": 1,
"description": "<DESCRIPTION>"
}'const res = await fetch("https://api.orshot.com/v1/studio/templates/create", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer <ORSHOT_API_KEY>",
},
body: JSON.stringify({
"name": "<NAME>",
"canvas_width": 1,
"canvas_height": 1,
"description": "<DESCRIPTION>"
}),
});
const data = await res.json();import requests
response = requests.post(
"https://api.orshot.com/v1/studio/templates/create",
headers={"Authorization": "Bearer <ORSHOT_API_KEY>"},
json={
"name": "<NAME>",
"canvas_width": 1,
"canvas_height": 1,
"description": "<DESCRIPTION>"
},
)
data = response.json()$ch = curl_init("https://api.orshot.com/v1/studio/templates/create");
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([
"name" => "<NAME>",
"canvas_width" => 1,
"canvas_height" => 1,
"description" => "<DESCRIPTION>"
]));
$data = json_decode(curl_exec($ch), true);
curl_close($ch);require "net/http"
require "json"
uri = URI("https://api.orshot.com/v1/studio/templates/create")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer <ORSHOT_API_KEY>"
req["Content-Type"] = "application/json"
req.body = {
"name": "<NAME>",
"canvas_width": 1,
"canvas_height": 1,
"description": "<DESCRIPTION>"
}.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. Checkout the Enterprise Pricing to get access.
Create a new studio template in your workspace programmatically. This endpoint allows you to define the template structure, dimensions, and optionally include pre-built pages with elements.
For detailed information about the template data structure, see Anatomy of a Template.
Endpoint#
https://api.orshot.com/v1/studio/templates/createQuery Parameters#
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
includeThumbnails | Boolean | No | false | When true, the endpoint renders a thumbnail for every page and waits for all uploads before responding. When false or absent, thumbnails are generated asynchronously after the response is sent. |
Request#
// Create a blank template with specified dimensions
await fetch("https://api.orshot.com/v1/studio/templates/create", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer <ORSHOT_API_KEY>",
},
body: JSON.stringify({
name: "Product Banner",
description: "E-commerce product showcase banner",
canvas_width: 1200,
canvas_height: 628,
embed_user_id: "your-external-user-id" // Optional
}),
});// Create a template with pre-built page structure
await fetch("https://api.orshot.com/v1/studio/templates/create", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer <ORSHOT_API_KEY>",
},
body: JSON.stringify({
name: "Social Media Post",
description: "Instagram post template",
canvas_width: 1080,
canvas_height: 1080,
pages_data: [
{
id: "page-1-uuid",
name: "Page 1",
canvas: {
width: 1080,
height: 1080,
backgroundColor: "#ffffff"
},
elements: [
{
id: "headline-element",
type: "text",
position: { x: 100, y: 200 },
dimensions: { width: 880, height: 100 },
content: "Your Headline Here",
parameterId: "headline",
parameterizable: true
},
{
id: "image-element",
type: "image",
position: { x: 100, y: 350 },
dimensions: { width: 880, height: 500 },
content: "https://example.com/placeholder.png",
parameterId: "product_image",
parameterizable: true
}
],
modifications: []
}
]
}),
});{
"success": true,
"template": {
"id": 12345,
"name": "Product Banner",
"canvas_width": 1200,
"canvas_height": 628,
"tags": [],
"pages_count": 1,
"modifications": [
{
"key": "headline",
"id": "headline",
"type": "text",
"description": "Headline — Text content",
"help_text": "Headline — Text content",
"element_name": "Headline",
"example": "Your Headline Here",
"page_number": 1,
"page_id": "page-1-uuid"
},
{
"key": "product_image",
"id": "product_image",
"type": "imageUrl",
"description": "Product Image — Image URL",
"help_text": "Product Image — Image URL",
"element_name": "Product Image",
"example": "https://example.com/placeholder.png",
"page_number": 1,
"page_id": "page-1-uuid"
}
],
"created_at": "2026-01-29T10:30:00.000Z"
}
}{
"success": true,
"template": {
"id": 12345,
"name": "Product Banner",
"canvas_width": 1200,
"canvas_height": 628,
"tags": [],
"pages_count": 1,
"modifications": [
{
"key": "headline",
"id": "headline",
"type": "text",
"description": "Headline — Text content",
"help_text": "Headline — Text content",
"element_name": "Headline",
"example": "Your Headline Here",
"page_number": 1,
"page_id": "page-1-uuid"
}
],
"created_at": "2026-01-29T10:30:00.000Z",
"thumbnails": {
"success": true,
"pages": [
{
"page": 1,
"page_id": "page-1-uuid",
"thumbnail_url": "https://storage.orshot.com/cloud/w-50/renders/thumbnails/abc123.png",
"error": null
}
]
}
}
}Rate Limits#
| Limit | Value |
|---|---|
| Requests per minute | 30 |
Request Body Parameters#
| Parameter | Type | Required | Description |
|---|---|---|---|
name | String | Yes | Name of the template (max 255 characters) |
description | String | No | Description of the template |
canvas_width | Integer | Yes | Width of the canvas in pixels (1-5000) |
canvas_height | Integer | Yes | Height of the canvas in pixels (1-5000) |
pages_data | Array | No | Array of page objects with elements. If not provided, a blank page is created |
tags | Array | No | Array of tag strings to categorize the template (e.g. ["social", "marketing"]) |
thumbnail_url | String | No | URL to a thumbnail image for the template |
embed_user_id | String | No | Assign the template to an embed user. Accepts either an external user ID (which will be resolved using your workspace's embed configuration) or an Orshot internal ID (prefixed with eui_). |
Pages Data Structure#
Each page in the pages_data array should follow this structure:
| Field | Type | Description |
|---|---|---|
id | String | Unique identifier for the page (UUID recommended) |
name | String | Name of the page (e.g., "Page 1") |
canvas | Object | Canvas settings { width, height, backgroundColor } |
elements | Array | Array of text, image, shape, video, waveform, and other elements |
motion | Object | Optional page-level motion: film look and camera moves |
Elements may carry transitions (animations) and motion (cinematic behaviors) for video output. Motion params are validated on write: structural problems fail with a 400 listing each issue; unknown or misspelled params are accepted and reported in the response warnings array with a did-you-mean suggestion.
| modifications | Array | Array of parameterizable modifications |
| thumbnail_url | String | URL to page thumbnail |
| audioTracks | Array | Existing audio, generated narration, and ambient tracks |
| subtitle | Object | Burned-in subtitle configuration |
| videoDuration | Number | Saved video duration for this page in seconds |
Use audioTracks[].tts for generated narration and audioTracks[].sfx for ambient audio. Add tts.parameterId when the spoken script should be dynamic. See Template Anatomy for the complete page, audio, subtitle, and waveform schemas.
Response Fields#
| Field | Type | Description |
|---|---|---|
success | Boolean | Whether the operation was successful |
template.id | Integer | Unique identifier for the created template |
template.name | String | Name of the template |
template.canvas_width | Integer | Canvas width in pixels |
template.canvas_height | Integer | Canvas height in pixels |
template.tags | Array | Tags assigned to the template |
template.pages_count | Integer | Number of pages in the template |
template.modifications | Array | List of parameterizable modifications extracted from elements |
warnings | Array | Non-blocking authoring warnings (e.g. an unknown motion param with a suggested fix). Present only when there is something to fix |
template.created_at | String | ISO timestamp of creation |
template.thumbnails | Object | Only present when ?includeThumbnails=true. See Thumbnails Object Structure below |
Modification Object Structure#
Each modification in template.modifications contains:
| Field | Type | Description |
|---|---|---|
key | String | Unique key for the modification. For multi-page templates this is prefixed, e.g. page1@headline |
id | String | Same as key |
type | String | Type of modification (text, voiceText, imageUrl, videoUrl, backgroundColor, fill, color, stroke) |
description | String | Human-readable description, e.g. "Headline — Text content" or "Image URL" when no element name is set |
help_text | String | Same as description |
element_name | String | Layer name of the element in the editor (only present when the element has a name) |
example | String | Default/example value for the field |
page_number | Integer | 1-based page number this modification belongs to |
page_id | String | Stable UUID of the page this modification belongs to — use this to reliably map modifications to pages after reorder |
Error Responses#
| Status Code | Error | Description |
|---|---|---|
| 400 | Validation failed | Invalid request body parameters |
| 403 | Access Forbidden | Invalid or missing API key |
| 429 | Rate limit exceeded | Too many requests (max 30/min) |
| 500 | Internal server error | Server-side error |
Thumbnails Object Structure#
When you pass ?includeThumbnails=true, the endpoint renders a PNG thumbnail for each page using the same scale convention as the Studio editor (capped at 1200×1200, never upscaled). The returned template.thumbnails object has this shape:
{
"success": true,
"pages": [
{ "page": 1, "page_id": "...", "thumbnail_url": "https://...", "error": null },
{ "page": 2, "page_id": "...", "thumbnail_url": "https://...", "error": null }
]
}| 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 UUID of the page |
pages[].thumbnail_url | String|null | Public URL of the uploaded thumbnail PNG. null if this specific page failed |
pages[].error | String|null | Error message if this page failed. null on success |
Asynchronous thumbnails#
When ?includeThumbnails=true is not set (the default), the endpoint responds immediately and generates thumbnails in the background. The thumbnails will appear on the template (via pages_data[].thumbnail_url and pages_meta[].thumbnail_url) shortly after creation — typically within a few seconds per page. Use GET /v1/studio/templates/:templateId to fetch the current state.
Pass ?includeThumbnails=true only when your workflow needs the thumbnail URLs in the same response (e.g., you're about to render or display the template immediately). Sync mode adds ~1–2 seconds per page to the response time.
Notes#
- If
pages_datais not provided, a blank page with the specified dimensions is automatically created - Elements with
parameterizable: trueand aparameterIdwill be automatically extracted as modifications - The
modificationsarray in the response shows which dynamic parameters are available for rendering - When
embed_user_idis provided, the template will be associated with the specified embed user. If you pass your own external user ID, it will be resolved to an internal Orshot ID using the embed configuration linked to your workspace. You can also pass an Orshot internal ID directly (format:eui_followed by 16 alphanumeric characters).
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 50+ integrations
- White-label embed for your own app
- 30 free credits — no credit card required