# Render from Studio Template

> Learn how you can make a POST request to render from a custom template on Orshot

- **URL**: https://orshot.com/docs/api-reference/render-from-studio-template

---

## What are Studio Templates?

Templates that you've designed in [Orshot Studio](https://orshot.com/docs/orshot-studio/introduction) are Studio Templates.
These templates are custom designs that you can customize and paramterize

You can render content from a custom template that you've designed using [Orshot Studio](https://orshot.com/features/orshot-studio) by making `POST` request to Orshot API```markdown tab="Endpoint"
https://api.orshot.com/v1/studio/render
```## POST Request```js
await fetch("https://api.orshot.com/v1/studio/render", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    Authorization: "Bearer <ORSHOT_API_KEY>",
  },
  body: JSON.stringify({
    templateId: <TEMPLATE_ID>,
    modifications: {
      canvasBackgroundColor: "#eff2fa", // Supports CSS Color Values(HEX, RGBA, linear-gradient)
      canvasBackgroundImage: "https://acme.com/public/web-background.png",
      title: "Custom Title",
      imageUrl: "Custom Image URL",
    },
    response : {
      type: "base64",
      format: "png",
      scale: 1, // control scale of the image/pdf, scale = 1(set size), 2 = double the size
      includePages: [1, 3], // only for multi-page templates
      fileName: "" // specify custom file name(without extension) for output file
    },
    pdfOptions : { // applicable only if response.format is "pdf"
      margin: "20px",
      rangeFrom: 1, // show only from page 1(set to "null" to show all pages)
      rangeTo: 2, // to page 2(set to "null" to show all pages)
      colorMode: "rgb", // set color mode for PDFs (supports "rgb" and "cmyk")
      dpi: 300, // set DPI for the PDF
    },
    videoOptions: { // applicable only if response.format is "mp4", "webm", or "gif"
      fps: 30,
      quality: 80,
      trimStart: 0,
      trimEnd: 20,
      muted: true,
      subtitleSource: "https://acme.com/public/subtitles.srt",
      subtitleFontSize: "30px",
      subtitleColor: "#ffffff",
      subtitleBackground: "rgba(0,0,0,0.5)",
      subtitleFontFamily: "Inter, sans-serif",
      subtitleBottom: "50px",
      combinePages: true, // optional, only for multi-page mp4/webm
      pageTransition: "fade", // optional
      pageTransitionDuration: 0.5, // optional, 0.1 to 2 seconds
    },
    publish: { // optional — publish render to connected social accounts
      accounts: [1, 2], // social account IDs from your workspace
      content: "Check out our latest design!", // caption for the post
    },
  }),
});
```### Response Structure

<Tabs items=>

<Tab value="Single Page Templates">```js
{
  "data": {
    "content": "data:image/png;base64,iVBORw0.....",
    "format": "png",
    "type": "base64",
    "responseTime": 325.22
  },
  // only if publish object was included in the request
  "publish": [
    { "platform": "twitter", "username": "acmehq", "status": "published" },
    { "platform": "instagram", "username": "acmeinsta", "status": "published" }
  ]
}
```</Tab>
<Tab value="Carousel Templates">```js
{
  "data": [
    {
      "page": 1,
      "pageId": "a1b2c3d4-5e6f-7890-abcd-ef1234567890",
      "content": "https://storage.orshot.com/cloud/w-11/renders/images/FMEI22AVte8.png"
    },
    {
      "page": 2,
      "pageId": "b2c3d4e5-6f78-9012-bcde-f23456789012",
      "content": "https://storage.orshot.com/cloud/w-11/renders/images/4J6NvUi0UJW.png"
    },
    {
      "page": 3,
      "pageId": "c3d4e5f6-7890-1234-cdef-345678901234",
      "content": "https://storage.orshot.com/cloud/w-11/renders/images/Xsmpnp3aVIu.png"
    }
  ],
  "format": "png",
  "type": "url",
  "responseTime": 3166.01,
  "totalPages": 3,
  "renderedPages": 3,
  // only if publish object was included in the request
  "publish": [
    { "platform": "linkedin", "username": "acmehq", "status": "published" }
  ]
}
```</Tab>
<Tab value="Flow Templates">
When a template has flow text that overflows across pages, the response includes metadata about the flow:```js
{
  "data": [
    {
      "page": 1,
      "pageId": "a1b2c3d4-5e6f-7890-abcd-ef1234567890",
      "content": "https://storage.orshot.com/cloud/w-11/renders/images/page_1.png"
    },
    {
      "page": 2,
      "content": "https://storage.orshot.com/cloud/w-11/renders/images/page_2.png",
      "sourcePageId": "a1b2c3d4-5e6f-7890-abcd-ef1234567890",
      "sourcePageNumber": 1,
      "flowPage": 1
    },
    {
      "page": 3,
      "content": "https://storage.orshot.com/cloud/w-11/renders/images/page_3.png",
      "sourcePageId": "a1b2c3d4-5e6f-7890-abcd-ef1234567890",
      "sourcePageNumber": 1,
      "flowPage": 2
    }
  ],
  "format": "png",
  "type": "url",
  "responseTime": 4200.15,
  "totalPages": 3,
  "renderedPages": 3,
  "flowTotalPages": 2
}
```Flow-specific fields on each overflow page:
- `sourcePageId` — the page ID of the source template page
- `sourcePageNumber` — which template page the overflow came from
- `flowPage` — overflow page number (1 = first overflow, 2 = second, etc.)

Top-level field:
- `flowTotalPages` — total number of overflow pages generated

See [Flowing Content](https://orshot.com/docs/orshot-studio/flowing-content) for setup instructions.
</Tab>
</Tabs>

## Single Page Templates

- Templates with only one page
- Response can be accessed at the value at `data.content`, it's in `string` format
- (base64 format + binary type) response combination isn't supported

## Multi Page Templates

- Templates with more than one pages
- Response can be accessed at `data.content`, it's in `array` format with content
- Each array entry includes `page` (1-based page number) and `pageId` (stable UUID of the page). Prefer `pageId` when your workflow needs to reference a specific page — page numbers shift when pages are reordered, while `pageId` is stable for the lifetime of the page
- For multi-page video renders (`mp4`/`webm`), set `videoOptions.combinePages: true` to return one combined video instead of per-page video files

## Parameters

- `templateId`: Each Studio template has a unique templateId(integer) which you can see on Template's page or payground
- `modifications`: Object structure of the dynamic modidifcations that you've set in the template. Additionally, you can also use style parameters to dynamically set styles for your layers, [learn more](https://orshot.com/docs/orshot-studio/style-parameters)
- [`response.format`](https://orshot.com/docs/definitions/response-format) - Supports `png`, `webp`, `jpg`, `avif`, `pdf`, `mp4`, `webm`, `gif`
- [`response.type`](https://orshot.com/docs/definitions/response-type)
- `response.fileName`: works only when the response type is either `url` or `binary`, can be used to specify custom file name for the output files. In carousel templates, the file name will be suffixed by `-page-1`, `-page-2` etc. Also if `response/format` is set to `url`, the custom file name will be suffixed with `-[UNIQUE_HASH]` to make sure it's a unique file
- `pdfOptions`: Optional object for PDF renders (`response.format: "pdf"`)
  - `pdfOptions.margin`: Global margin around PDF content (example: `"20px"`)
  - `pdfOptions.rangeFrom`: Start page for PDF range selection
  - `pdfOptions.rangeTo`: End page for PDF range selection
  - `pdfOptions.colorMode`: Color mode (`"rgb"` or `"cmyk"`)
  - `pdfOptions.dpi`: Output DPI (commonly `72`, `150`, `300`)
  - `pdfOptions.marginTop`: Optional top margin override
  - `pdfOptions.marginBottom`: Optional bottom margin override
  - `pdfOptions.marginLeft`: Optional left margin override
  - `pdfOptions.marginRight`: Optional right margin override
  - See [PDF Options](https://orshot.com/docs/pdf-generation/pdf-options) for behavior details and print recommendations
- `videoOptions`: Optional object for video renders (`mp4`, `webm`, `gif`)
  - `videoOptions.fps`: Output FPS (`1-30`)
  - `videoOptions.quality`: Video quality (`1-100`)
  - `videoOptions.trimStart`: Global trim start in seconds (works with `trimEnd`)
  - `videoOptions.trimEnd`: Global trim end in seconds (works with `trimStart`)
  - `videoOptions.duration`: Fallback output duration in seconds when trim range is not provided
  - `videoOptions.muted`: Global audio control (`true` = mute all output audio, `false` = include available element audio)
  - `videoOptions.subtitleSource`: Subtitle input source
    - `string`: single subtitle/audio/video/SRT URL for single-page templates
    - `array`: page-mapped sources for multi-page templates, e.g. `[]`
  - `videoOptions.subtitleFontSize`: Subtitle font size (CSS size string, e.g. `"30px"`)
  - `videoOptions.subtitleColor`: Subtitle text color
  - `videoOptions.subtitleBackground`: Subtitle background color
  - `videoOptions.subtitleFontFamily`: Subtitle font family
  - `videoOptions.subtitleBottom`: Subtitle bottom offset (CSS size string)
  - `videoOptions.combinePages`: Combine multi-page videos into one output video (supported only for multi-page `mp4` and `webm`)
  - `videoOptions.pageTransition`: Optional transition when `combinePages` is enabled
    - Supported values: `fade`, `fadeblack`, `fadewhite`, `dissolve`, `wipeleft`, `wiperight`, `wipeup`, `wipedown`, `slideleft`, `slideright`, `slideup`, `slidedown`, `circleopen`, `circleclose`, `pixelize`
    - Use `"none"` or omit for hard cuts
  - `videoOptions.pageTransitionDuration`: Transition duration in seconds (`0.1` to `2`)
  - See [Video Options](https://orshot.com/docs/video-generation/video-options) for behavior details and examples
- [`publish`](https://orshot.com/docs/publish/publish-from-api): Optional object to publish the render directly to connected social accounts
  - `publish.accounts`: Array of social account IDs from your workspace
  - `publish.content`: Caption/text for the social post
  - `publish.isDraft`: Set to `true` to save as draft instead of publishing
  - `publish.schedule.scheduledFor`: ISO date string to schedule the post for later
  - `publish.timezone`: Timezone string (e.g. `"America/New_York"`) for scheduling
  - `publish.platformOptions`: Per-account options keyed by account ID (e.g. LinkedIn `firstComment`, Pinterest `title`/`link`). See [Publish from API](https://orshot.com/docs/publish/publish-from-api#platform-options)

## Video Generation

For templates with video elements, you can render them as video files by setting `response.format` to `mp4`, `webm`, or `gif`.```js
await fetch("https://api.orshot.com/v1/studio/render", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    Authorization: "Bearer <ORSHOT_API_KEY>",
  },
  body: JSON.stringify({
    templateId: <TEMPLATE_ID>,
    modifications: {
      "videoElement": "https://example.com/custom-video.mp4", // Dynamic video URL
      "videoElement.trimStart": 0, // Start time in seconds
      "videoElement.trimEnd": 10, // End time in seconds
      "videoElement.muted": false, // Include audio
      "videoElement.loop": true, // Loop the video
    },
    videoOptions: { // global video option
      trimStart: 0, // in seconds
      trimEnd: 20, // in seconds
      muted: true,
      combinePages: true, // optional, only for multi-page mp4/webm
      pageTransition: "fade", // optional transition between pages
      pageTransitionDuration: 0.5, // optional, seconds (0.1 to 2)
    },
    response: {
      type: "url",
      format: "mp4", // or "webm", "gif"
    },
  }),
});
```### Video Parameters

For video elements with a parameter ID set, you can pass dynamic video properties:

- `` - Custom video URL
- `.trimStart` - Start time in seconds
- `.trimEnd` - End time in seconds
- `.muted` - `true` or `false` for audio
- `.loop` - `true` or `false` for looping

### Global `videoOptions`

All supported `videoOptions` fields are listed above in the [Parameters](#parameters) section.

### Combining Multi-Page Videos

By default, multi-page video renders return one output per page.
To get one final combined video, pass `videoOptions.combinePages: true`.```js
await fetch("https://api.orshot.com/v1/studio/render", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    Authorization: "Bearer <ORSHOT_API_KEY>",
  },
  body: JSON.stringify({
    templateId: <TEMPLATE_ID>,
    response: {
      type: "url",
      format: "webm",
      includePages: [1, 2, 3],
    },
    videoOptions: {
      combinePages: true,
      pageTransition: "fade", // optional
      pageTransitionDuration: 0.5, // optional
    },
  }),
});
```