# Create Studio Template

> Create a single studio template programmatically via API

- **URL**: https://orshot.com/docs/api-reference/enterprise-template-create

---

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](https://orshot.com/docs/definitions/template-anatomy).

## Endpoint```markdown tab="Endpoint"
https://api.orshot.com/v1/studio/templates/create
```## Query 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

<Tabs items=>
<Tab value="Basic Request">```js
// 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
  }),
});
```</Tab>
<Tab value="With Pages Data">```js
// 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",
            x: 100,
            y: 200,
            width: 880,
            height: 100,
            content: "Your Headline Here",
            parameterId: "headline",
            parameterizable: true
          },
          {
            id: "image-element",
            type: "image",
            x: 100,
            y: 350,
            width: 880,
            height: 500,
            src: "https://example.com/placeholder.png",
            parameterId: "product_image",
            parameterizable: true
          }
        ],
        modifications: []
      }
    ]
  }),
});
```</Tab>
<Tab value="Response">```json
{
  "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"
  }
}
```</Tab>
<Tab value="Response (?includeThumbnails=true)">```json
{
  "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
        }
      ]
    }
  }
}
```</Tab>
</Tabs>

## 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 `` |
| `elements`      | Array  | Array of element objects (text, image, shapes, etc.) |
| `modifications` | Array  | Array of parameterizable modifications               |
| `thumbnail_url` | String | URL to page thumbnail                                |

## 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 |
| `template.created_at`    | String  | ISO timestamp of creation                                     |
| `template.thumbnails`    | Object  | Only present when `?includeThumbnails=true`. See [Thumbnails Object Structure](#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`, `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:```json
{
  "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_data` is not provided, a blank page with the specified dimensions is automatically created
- Elements with `parameterizable: true` and a `parameterId` will be automatically extracted as modifications
- The `modifications` array in the response shows which dynamic parameters are available for rendering
- When `embed_user_id` is 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).