# Render a video

> The renderVideo endpoint renders a video template as an MP4 and returns its id and URL, or streams the progress of the render.

Canonical: https://bannerify.co/docs/api-reference/endpoint/render-video

## OpenAPI

```json post /v1/templates/renderVideo
{
  "openapi": "3.0.0",
  "info": {
    "title": "Bannerify API",
    "version": "0.0.0"
  },
  "servers": [
    {
      "url": "https://api.bannerify.co",
      "description": "Production"
    }
  ],
  "security": [
    {
      "token": []
    }
  ],
  "paths": {
    "/v1/templates/renderVideo": {
      "post": {
        "description": "Beta. Render a video template as an MP4, save the file, and return its id and URL. With `stream=true` the answer is a stream of server-sent events: `created` with the id of the video, `queued` while the video waits for a renderer, `progress` while its frames render, then `done` with the URL, or `error`. The video renders to its end also when the connection drops: read it again with `GET /v1/videos/{id}`. Each second of the video counts as one generation, and as two at 60 fps. A failed video counts nothing.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "`false` answers `202` with the id of the video at once, without waiting for the render. Read the video later with `GET /v1/videos/{id}`.",
              "example": "false"
            },
            "required": false,
            "description": "`false` answers `202` with the id of the video at once, without waiting for the render. Read the video later with `GET /v1/videos/{id}`.",
            "name": "wait",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "`true` streams the progress as server-sent events.",
              "example": "true"
            },
            "required": false,
            "description": "`true` streams the progress as server-sent events.",
            "name": "stream",
            "in": "query"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "apiKey": {
                    "type": "string",
                    "description": "Your API key. Create one on the API Keys page of the dashboard, and keep it on the server.",
                    "example": "YOUR_API_KEY"
                  },
                  "templateId": {
                    "type": "string",
                    "description": "The id of the template to render. In the dashboard, open the menu on a template card and choose Copy Template ID.",
                    "example": "tpl_xxx"
                  },
                  "modifications": {
                    "anyOf": [
                      {
                        "type": "array",
                        "items": {
                          "$ref": "#/components/schemas/Modification"
                        }
                      },
                      {
                        "type": "object",
                        "additionalProperties": {
                          "nullable": true
                        }
                      },
                      {
                        "type": "string"
                      },
                      {
                        "nullable": true
                      }
                    ],
                    "default": [],
                    "description": "The values to change in the template, as an array of modifications. Each modification names a layer and sets one or more fields, and a layer without a modification keeps the values from the template. An object keyed by layer name and a JSON string of either shape also work. See https://bannerify.co/docs/essentials/modifications.",
                    "example": [
                      {
                        "name": "headline",
                        "text": "Summer sale"
                      },
                      {
                        "name": "photo",
                        "src": "https://example.com/photo.png"
                      }
                    ]
                  }
                },
                "required": [
                  "apiKey",
                  "templateId"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The stored video, or the events of its render.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "The id of the video, for `GET /v1/videos/{id}`.",
                      "example": "vid_0b3c1c1e5d6f4c529e0a8f6a4c0f2a11"
                    },
                    "url": {
                      "type": "string",
                      "description": "The public URL of the MP4.",
                      "example": "https://images.bannerify.co/files/0b3c1c1e-5d6f-4c52-9e0a-8f6a4c0f2a11.mp4"
                    }
                  },
                  "required": [
                    "id",
                    "url"
                  ]
                }
              },
              "text/event-stream": {
                "schema": {
                  "type": "string",
                  "example": "event: created\ndata: {\"type\":\"created\",\"id\":\"vid_0b3c1c1e5d6f4c529e0a8f6a4c0f2a11\"}\n\nevent: done\ndata: {\"type\":\"done\",\"url\":\"https://images.bannerify.co/files/0b3c.mp4\"}\n\n"
                }
              }
            }
          },
          "202": {
            "description": "With `wait=false`: the video renders, and its id is ready.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "example": "vid_0b3c1c1e5d6f4c529e0a8f6a4c0f2a11"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "queued"
                      ]
                    }
                  },
                  "required": [
                    "id",
                    "status"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request cannot be processed. BAD_REQUEST means a field is invalid, the API key is unknown, or a signed URL has a wrong signature. FETCH_IMAGE_ERROR means Bannerify could not download an image from a src URL. A rate limit on the PDF and stored endpoints also uses status 400 with the code TOO_MANY_REQUESTS. Read error.code to tell them apart.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/ErrBadRequest"
                    },
                    {
                      "$ref": "#/components/schemas/ErrFetchImageError"
                    },
                    {
                      "$ref": "#/components/schemas/ErrTooManyRequests"
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "description": "The plan of your workspace does not include the feature. FORBIDDEN means s3Config came from a workspace on the Free or Automate plan.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrForbidden"
                }
              }
            }
          },
          "404": {
            "description": "The template does not exist.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrNotFound"
                }
              }
            }
          },
          "500": {
            "description": "The server could not finish the request. INTERNAL_SERVER_ERROR means an unexpected failure, such as a render error or a failed upload to your S3 bucket. USAGE_EXCEEDED means your workspace reached its daily or monthly generation limit, and RATE_LIMITED means the API key sent too many requests. Read error.code to tell them apart.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/ErrInternalServerError"
                    },
                    {
                      "$ref": "#/components/schemas/ErrUsageExceeded"
                    },
                    {
                      "$ref": "#/components/schemas/ErrRateLimited"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "ErrBadRequest": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "BAD_REQUEST"
                ],
                "description": "A machine readable error code.",
                "example": "BAD_REQUEST"
              },
              "docs": {
                "type": "string",
                "description": "A link to our documentation with more details about this error code",
                "example": "https://bannerify.co/docs/api-reference/errors/code/BAD_REQUEST"
              },
              "message": {
                "type": "string",
                "description": "A human readable explanation of what went wrong"
              },
              "requestId": {
                "type": "string",
                "description": "Please always include the requestId in your error report",
                "example": "req:1234"
              }
            },
            "required": [
              "code",
              "docs",
              "message",
              "requestId"
            ]
          }
        },
        "required": [
          "error"
        ]
      },
      "ErrFetchImageError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "FETCH_IMAGE_ERROR"
                ],
                "description": "A machine readable error code.",
                "example": "FETCH_IMAGE_ERROR"
              },
              "docs": {
                "type": "string",
                "description": "A link to our documentation with more details about this error code",
                "example": "https://bannerify.co/docs/api-reference/errors/code/FETCH_IMAGE_ERROR"
              },
              "message": {
                "type": "string",
                "description": "A human readable explanation of what went wrong"
              },
              "requestId": {
                "type": "string",
                "description": "Please always include the requestId in your error report",
                "example": "req:1234"
              }
            },
            "required": [
              "code",
              "docs",
              "message",
              "requestId"
            ]
          }
        },
        "required": [
          "error"
        ]
      },
      "ErrTooManyRequests": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "TOO_MANY_REQUESTS"
                ],
                "description": "A machine readable error code.",
                "example": "TOO_MANY_REQUESTS"
              },
              "docs": {
                "type": "string",
                "description": "A link to our documentation with more details about this error code",
                "example": "https://bannerify.co/docs/api-reference/errors/code/TOO_MANY_REQUESTS"
              },
              "message": {
                "type": "string",
                "description": "A human readable explanation of what went wrong"
              },
              "requestId": {
                "type": "string",
                "description": "Please always include the requestId in your error report",
                "example": "req:1234"
              }
            },
            "required": [
              "code",
              "docs",
              "message",
              "requestId"
            ]
          }
        },
        "required": [
          "error"
        ]
      },
      "ErrNotFound": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "NOT_FOUND"
                ],
                "description": "A machine readable error code.",
                "example": "NOT_FOUND"
              },
              "docs": {
                "type": "string",
                "description": "A link to our documentation with more details about this error code",
                "example": "https://bannerify.co/docs/api-reference/errors/code/NOT_FOUND"
              },
              "message": {
                "type": "string",
                "description": "A human readable explanation of what went wrong"
              },
              "requestId": {
                "type": "string",
                "description": "Please always include the requestId in your error report",
                "example": "req:1234"
              }
            },
            "required": [
              "code",
              "docs",
              "message",
              "requestId"
            ]
          }
        },
        "required": [
          "error"
        ]
      },
      "ErrInternalServerError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "INTERNAL_SERVER_ERROR"
                ],
                "description": "A machine readable error code.",
                "example": "INTERNAL_SERVER_ERROR"
              },
              "docs": {
                "type": "string",
                "description": "A link to our documentation with more details about this error code",
                "example": "https://bannerify.co/docs/api-reference/errors/code/INTERNAL_SERVER_ERROR"
              },
              "message": {
                "type": "string",
                "description": "A human readable explanation of what went wrong"
              },
              "requestId": {
                "type": "string",
                "description": "Please always include the requestId in your error report",
                "example": "req:1234"
              }
            },
            "required": [
              "code",
              "docs",
              "message",
              "requestId"
            ]
          }
        },
        "required": [
          "error"
        ]
      },
      "ErrUsageExceeded": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "USAGE_EXCEEDED"
                ],
                "description": "A machine readable error code.",
                "example": "USAGE_EXCEEDED"
              },
              "docs": {
                "type": "string",
                "description": "A link to our documentation with more details about this error code",
                "example": "https://bannerify.co/docs/api-reference/errors/code/USAGE_EXCEEDED"
              },
              "message": {
                "type": "string",
                "description": "A human readable explanation of what went wrong"
              },
              "requestId": {
                "type": "string",
                "description": "Please always include the requestId in your error report",
                "example": "req:1234"
              }
            },
            "required": [
              "code",
              "docs",
              "message",
              "requestId"
            ]
          }
        },
        "required": [
          "error"
        ]
      },
      "ErrRateLimited": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "RATE_LIMITED"
                ],
                "description": "A machine readable error code.",
                "example": "RATE_LIMITED"
              },
              "docs": {
                "type": "string",
                "description": "A link to our documentation with more details about this error code",
                "example": "https://bannerify.co/docs/api-reference/errors/code/RATE_LIMITED"
              },
              "message": {
                "type": "string",
                "description": "A human readable explanation of what went wrong"
              },
              "requestId": {
                "type": "string",
                "description": "Please always include the requestId in your error report",
                "example": "req:1234"
              }
            },
            "required": [
              "code",
              "docs",
              "message",
              "requestId"
            ]
          }
        },
        "required": [
          "error"
        ]
      },
      "Modification": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "The name of the layer to change. The match is exact and case-sensitive, and a name that no layer has is ignored.",
            "example": "headline"
          },
          "color": {
            "type": "string",
            "description": "The text color of a text layer, for example #ff5733. Other layers ignore it.",
            "example": "#FF0000"
          },
          "src": {
            "type": "string",
            "description": "The URL of the image for an image layer. It must be a public PNG, JPEG, WebP, or SVG file.",
            "example": "https://example.com/image.jpg"
          },
          "text": {
            "type": "string",
            "description": "The text of a text layer, the body of an alert layer, or the signer name of a signature layer.",
            "example": "Hello World"
          },
          "barcode": {
            "type": "string",
            "description": "The value of a barcode layer.",
            "example": "1234567890"
          },
          "qrcode": {
            "type": "string",
            "description": "The content of a QR code layer.",
            "example": "https://example.com"
          },
          "visible": {
            "type": "boolean",
            "description": "Show or hide the layer. It works on every layer type.",
            "example": true
          },
          "star": {
            "type": "number",
            "description": "The rating of a star layer. A value of 0 is ignored.",
            "example": 5
          },
          "rows": {
            "anyOf": [
              {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "label": {
                      "type": "string"
                    },
                    "value": {
                      "type": "number"
                    },
                    "color": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "label",
                    "value"
                  ]
                },
                "description": "Chart points, one series."
              },
              {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "name": {
                      "type": "string"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "label": {
                            "type": "string"
                          },
                          "value": {
                            "type": "number"
                          },
                          "color": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "label",
                          "value"
                        ]
                      }
                    },
                    "color": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "name",
                    "data"
                  ]
                },
                "description": "Chart series, several series."
              },
              {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "number"
                      },
                      {
                        "type": "boolean"
                      },
                      {
                        "nullable": true
                      }
                    ]
                  }
                },
                "description": "Table rows, keyed by column name."
              },
              {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "key": {
                      "type": "string"
                    },
                    "value": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "number"
                        }
                      ]
                    },
                    "valueColor": {
                      "type": "string"
                    },
                    "valueStyle": {
                      "type": "object",
                      "additionalProperties": {
                        "nullable": true
                      }
                    },
                    "keyStyle": {
                      "type": "object",
                      "additionalProperties": {
                        "nullable": true
                      }
                    }
                  },
                  "required": [
                    "key",
                    "value"
                  ]
                },
                "description": "Key value entries."
              }
            ],
            "description": "The rows of a data layer. A table takes row objects keyed by the column names, a chart takes { label, value } points or { name, data } series, and a key value layer takes { key, value } entries.",
            "example": [
              {
                "label": "Jan",
                "value": 22
              }
            ]
          },
          "columns": {
            "type": "array",
            "items": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "object",
                  "properties": {
                    "key": {
                      "type": "string"
                    },
                    "header": {
                      "type": "string"
                    },
                    "align": {
                      "type": "string",
                      "enum": [
                        "left",
                        "center",
                        "right"
                      ]
                    },
                    "width": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "number"
                        }
                      ]
                    }
                  },
                  "required": [
                    "key",
                    "header"
                  ]
                }
              ]
            },
            "description": "The columns of a table layer, as a column name or as a { key, header, align, width } object",
            "example": [
              "Item",
              "Qty",
              "Total"
            ]
          },
          "title": {
            "type": "string",
            "description": "The heading of an alert layer, or the job title of a signature layer",
            "example": "Payment terms"
          },
          "date": {
            "type": "string",
            "description": "The date of a signature layer",
            "example": "2026-01-31"
          },
          "values": {
            "type": "object",
            "additionalProperties": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "number"
                }
              ]
            },
            "description": "The fields of a component layer, by field key, such as { label, rating } for a rating pill. The properties panel of the layer lists its fields. A key that the component does not have is ignored.",
            "example": {
              "label": "Google:",
              "rating": 4.8
            }
          }
        },
        "required": [
          "name"
        ],
        "description": "A change to one layer of the template for one render. A field that does not fit the layer is ignored."
      },
      "ErrForbidden": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "FORBIDDEN"
                ],
                "description": "A machine readable error code.",
                "example": "FORBIDDEN"
              },
              "docs": {
                "type": "string",
                "description": "A link to our documentation with more details about this error code",
                "example": "https://bannerify.co/docs/api-reference/errors/code/FORBIDDEN"
              },
              "message": {
                "type": "string",
                "description": "A human readable explanation of what went wrong"
              },
              "requestId": {
                "type": "string",
                "description": "Please always include the requestId in your error report",
                "example": "req:1234"
              }
            },
            "required": [
              "code",
              "docs",
              "message",
              "requestId"
            ]
          }
        },
        "required": [
          "error"
        ]
      }
    }
  }
}
```

## Related

- [Previous: Create a stored PDF](https://bannerify.co/docs/api-reference/endpoint/create-stored-pdf)
- [Next: Retrieve a video](https://bannerify.co/docs/api-reference/endpoint/get-video)
- [Documentation index](https://bannerify.co/docs/llms.txt)
