Shotstack Create (AI Assets) API
Generate AI assets - text-to-speech, text-to-image, image-to-video, and text generation - through built-in (Shotstack) and third-party (ElevenLabs, Stability AI) providers, returning hosted assets for use in renders.
Generate AI assets - text-to-speech, text-to-image, image-to-video, and text generation - through built-in (Shotstack) and third-party (ElevenLabs, Stability AI) providers, returning hosted assets for use in renders.
openapi: 3.0.1
info:
title: Shotstack API
description: >-
Shotstack is a cloud video-editing platform that renders video, image, and
audio assets from a JSON edit specification. This document covers the Edit
API (render and templates), the Ingest API (source assets), the Serve API
(asset hosting and delivery), and the Create API (AI-generated assets). All
endpoints authenticate with an `x-api-key` header. Each API is available in
a `v1` (production) and `stage` (sandbox) environment.
termsOfService: https://shotstack.io/terms/
contact:
name: Shotstack Support
url: https://shotstack.io/contact/
version: '1.0'
servers:
- url: https://api.shotstack.io
description: Shotstack production and sandbox host (use /edit/v1 or /edit/stage, etc.)
security:
- apiKey: []
tags:
- name: Edit
description: Render videos, images, and audio from a JSON edit specification.
- name: Templates
description: Manage and render reusable edit templates with merge fields.
- name: Ingest
description: Upload, store, and transform source assets.
- name: Serve
description: Inspect, manage, and deliver hosted assets.
- name: Create
description: Generate AI assets such as text-to-speech and text-to-image.
paths:
/edit/v1/render:
post:
operationId: postRender
tags:
- Edit
summary: Queue a render
description: >-
Queue a video, image, or audio for rendering from a JSON edit
specification consisting of a timeline and an output. Returns a render
ID used to poll status.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Edit'
responses:
'201':
description: Render queued.
content:
application/json:
schema:
$ref: '#/components/schemas/QueuedResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
/edit/v1/render/{id}:
get:
operationId: getRender
tags:
- Edit
summary: Get render status
description: >-
Retrieve the status, progress, and output URL of a render by its ID.
Status values progress through queued, fetching, rendering, saving,
done, and failed.
parameters:
- name: id
in: path
required: true
description: The render ID returned when the render was queued.
schema:
type: string
format: uuid
- name: data
in: query
required: false
description: Include the original edit JSON in the response.
schema:
type: boolean
default: false
responses:
'200':
description: Render status.
content:
application/json:
schema:
$ref: '#/components/schemas/RenderResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
/edit/v1/probe/{url}:
get:
operationId: probeAsset
tags:
- Edit
summary: Probe a media asset
description: >-
Inspect the metadata of a media asset (duration, dimensions, codecs)
using FFprobe. The asset URL must be URL-encoded.
parameters:
- name: url
in: path
required: true
description: URL-encoded URL of the media asset to inspect.
schema:
type: string
responses:
'200':
description: Asset metadata.
content:
application/json:
schema:
$ref: '#/components/schemas/ProbeResponse'
'401':
$ref: '#/components/responses/Unauthorized'
/edit/v1/templates:
post:
operationId: createTemplate
tags:
- Templates
summary: Create a template
description: Save an edit as a reusable template with optional merge fields.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Template'
responses:
'201':
description: Template created.
content:
application/json:
schema:
$ref: '#/components/schemas/TemplateResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
get:
operationId: listTemplates
tags:
- Templates
summary: List templates
description: List all templates for the authenticated account.
responses:
'200':
description: A list of templates.
content:
application/json:
schema:
$ref: '#/components/schemas/TemplateListResponse'
'401':
$ref: '#/components/responses/Unauthorized'
/edit/v1/templates/{id}:
get:
operationId: getTemplate
tags:
- Templates
summary: Get a template
parameters:
- $ref: '#/components/parameters/TemplateId'
responses:
'200':
description: A template.
content:
application/json:
schema:
$ref: '#/components/schemas/TemplateResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
put:
operationId: updateTemplate
tags:
- Templates
summary: Update a template
parameters:
- $ref: '#/components/parameters/TemplateId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Template'
responses:
'200':
description: Template updated.
content:
application/json:
schema:
$ref: '#/components/schemas/TemplateResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
delete:
operationId: deleteTemplate
tags:
- Templates
summary: Delete a template
parameters:
- $ref: '#/components/parameters/TemplateId'
responses:
'200':
description: Template deleted.
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
/edit/v1/templates/render:
post:
operationId: renderTemplate
tags:
- Templates
summary: Render a template
description: >-
Render an asset from a saved template, supplying optional merge fields
to substitute variables in the template.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/TemplateRenderRequest'
responses:
'201':
description: Render queued.
content:
application/json:
schema:
$ref: '#/components/schemas/QueuedResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
/ingest/v1/sources:
post:
operationId: fetchSource
tags:
- Ingest
summary: Ingest a source from a URL
description: >-
Queue a source file (video, image, audio, or font) to be fetched from a
URL, stored, and optionally transformed into renditions or transcribed.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/SourceRequest'
responses:
'201':
description: Source queued.
content:
application/json:
schema:
$ref: '#/components/schemas/SourceResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
get:
operationId: listSources
tags:
- Ingest
summary: List sources
responses:
'200':
description: A list of ingested sources.
content:
application/json:
schema:
$ref: '#/components/schemas/SourceListResponse'
'401':
$ref: '#/components/responses/Unauthorized'
/ingest/v1/sources/{id}:
get:
operationId: getSource
tags:
- Ingest
summary: Get a source
parameters:
- $ref: '#/components/parameters/SourceId'
responses:
'200':
description: A source.
content:
application/json:
schema:
$ref: '#/components/schemas/SourceResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
delete:
operationId: deleteSource
tags:
- Ingest
summary: Delete a source
parameters:
- $ref: '#/components/parameters/SourceId'
responses:
'200':
description: Source deleted.
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
/ingest/v1/upload:
post:
operationId: requestUpload
tags:
- Ingest
summary: Request a direct upload
description: >-
Request a signed URL to upload a source file directly to Shotstack
storage.
responses:
'201':
description: Signed upload URL issued.
content:
application/json:
schema:
$ref: '#/components/schemas/UploadResponse'
'401':
$ref: '#/components/responses/Unauthorized'
/serve/v1/assets/{id}:
get:
operationId: getAsset
tags:
- Serve
summary: Get an asset
description: Retrieve the details and CDN URL of a hosted asset by asset ID.
parameters:
- $ref: '#/components/parameters/AssetId'
responses:
'200':
description: An asset.
content:
application/json:
schema:
$ref: '#/components/schemas/AssetResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
delete:
operationId: deleteAsset
tags:
- Serve
summary: Delete an asset
parameters:
- $ref: '#/components/parameters/AssetId'
responses:
'200':
description: Asset deleted.
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
/serve/v1/assets/render/{id}:
get:
operationId: getAssetsByRender
tags:
- Serve
summary: Get assets by render ID
description: >-
Retrieve all assets (video, thumbnail, poster) associated with a render
ID.
parameters:
- name: id
in: path
required: true
description: The render ID.
schema:
type: string
format: uuid
responses:
'200':
description: A list of assets for the render.
content:
application/json:
schema:
$ref: '#/components/schemas/AssetListResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
/serve/v1/assets:
post:
operationId: transferAsset
tags:
- Serve
summary: Transfer an asset
description: Transfer a file from a URL to one or more hosting destinations.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/TransferRequest'
responses:
'201':
description: Transfer queued.
content:
application/json:
schema:
$ref: '#/components/schemas/AssetResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
/create/v1/assets:
post:
operationId: generateAsset
tags:
- Create
summary: Generate an AI asset
description: >-
Generate an AI asset (text-to-speech, text-to-image, image-to-video, or
text generation) using a built-in or third-party provider. Returns an
asset ID to poll for the generated, hosted asset.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/GenerateAssetRequest'
responses:
'201':
description: Generation queued.
content:
application/json:
schema:
$ref: '#/components/schemas/GenerateAssetResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
/create/v1/assets/{id}:
get:
operationId: getGeneratedAsset
tags:
- Create
summary: Get a generated asset
description: Retrieve the status and URL of a generated AI asset by ID.
parameters:
- $ref: '#/components/parameters/AssetId'
responses:
'200':
description: A generated asset.
content:
application/json:
schema:
$ref: '#/components/schemas/GenerateAssetResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
components:
securitySchemes:
apiKey:
type: apiKey
in: header
name: x-api-key
description: Developer API key. The same key set is used by all Shotstack APIs.
parameters:
TemplateId:
name: id
in: path
required: true
description: The template ID.
schema:
type: string
format: uuid
SourceId:
name: id
in: path
required: true
description: The source ID.
schema:
type: string
format: uuid
AssetId:
name: id
in: path
required: true
description: The asset ID.
schema:
type: string
format: uuid
responses:
BadRequest:
description: The request was malformed or failed validation.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
Unauthorized:
description: Missing or invalid x-api-key.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
NotFound:
description: The requested resource was not found.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
schemas:
Edit:
type: object
required:
- timeline
- output
properties:
timeline:
$ref: '#/components/schemas/Timeline'
output:
$ref: '#/components/schemas/Output'
merge:
type: array
description: Find-and-replace merge fields applied before rendering.
items:
$ref: '#/components/schemas/MergeField'
callback:
type: string
format: uri
description: HTTPS webhook URL called when the render status changes.
Timeline:
type: object
required:
- tracks
properties:
soundtrack:
$ref: '#/components/schemas/Soundtrack'
background:
type: string
description: Hex color of the background canvas.
example: '#000000'
fonts:
type: array
items:
type: object
properties:
src:
type: string
format: uri
tracks:
type: array
description: Layers of clips composited from bottom to top.
items:
$ref: '#/components/schemas/Track'
Track:
type: object
required:
- clips
properties:
clips:
type: array
items:
$ref: '#/components/schemas/Clip'
Clip:
type: object
required:
- asset
- start
- length
properties:
asset:
$ref: '#/components/schemas/Asset'
start:
type: number
description: Start time on the timeline in seconds.
length:
oneOf:
- type: number
- type: string
description: Duration of the clip in seconds, or "auto"/"end".
fit:
type: string
enum: [crop, cover, contain, none]
scale:
type: number
position:
type: string
enum: [top, topRight, right, bottomRight, bottom, bottomLeft, left, topLeft, center]
opacity:
type: number
transition:
type: object
properties:
in:
type: string
out:
type: string
effect:
type: string
Asset:
type: object
description: >-
A clip asset. The "type" discriminates between video, image, audio,
title, html, luma, caption, and the AI generative asset types
(text-to-speech, text-to-image, image-to-video).
required:
- type
properties:
type:
type: string
enum:
- video
- image
- audio
- title
- html
- luma
- caption
- text-to-speech
- text-to-image
- image-to-video
src:
type: string
format: uri
description: Source URL for video, image, audio, and luma assets.
text:
type: string
description: Text content for title, caption, and AI text-based assets.
trim:
type: number
volume:
type: number
Soundtrack:
type: object
properties:
src:
type: string
format: uri
effect:
type: string
enum: [fadeIn, fadeOut, fadeInFadeOut]
volume:
type: number
Output:
type: object
required:
- format
properties:
format:
type: string
enum: [mp4, gif, jpg, png, bmp, mp3, webm]
resolution:
type: string
enum: [preview, mobile, sd, hd, '1080']
aspectRatio:
type: string
enum: ['16:9', '9:16', '1:1', '4:5', '4:3']
fps:
type: number
enum: [12, 15, 24, 25, 30, 60]
quality:
type: string
enum: [low, medium, high]
destinations:
type: array
description: Where to deliver the rendered output.
items:
type: object
properties:
provider:
type: string
enum: [shotstack, s3, googlecloudstorage, googledrive, mux, vimeo]
MergeField:
type: object
properties:
find:
type: string
replace:
type: string
QueuedResponse:
type: object
properties:
success:
type: boolean
message:
type: string
response:
type: object
properties:
message:
type: string
id:
type: string
format: uuid
RenderResponse:
type: object
properties:
success:
type: boolean
message:
type: string
response:
type: object
properties:
id:
type: string
format: uuid
owner:
type: string
status:
type: string
enum: [queued, fetching, rendering, saving, done, failed]
url:
type: string
format: uri
poster:
type: string
format: uri
thumbnail:
type: string
format: uri
duration:
type: number
renderTime:
type: number
created:
type: string
format: date-time
updated:
type: string
format: date-time
ProbeResponse:
type: object
properties:
success:
type: boolean
response:
type: object
properties:
metadata:
type: object
Template:
type: object
required:
- name
- template
properties:
name:
type: string
template:
$ref: '#/components/schemas/Edit'
TemplateResponse:
type: object
properties:
success:
type: boolean
message:
type: string
response:
type: object
properties:
id:
type: string
format: uuid
name:
type: string
template:
$ref: '#/components/schemas/Edit'
TemplateListResponse:
type: object
properties:
success:
type: boolean
response:
type: object
properties:
templates:
type: array
items:
type: object
properties:
id:
type: string
format: uuid
name:
type: string
TemplateRenderRequest:
type: object
required:
- id
properties:
id:
type: string
format: uuid
description: The template ID to render.
merge:
type: array
items:
$ref: '#/components/schemas/MergeField'
SourceRequest:
type: object
required:
- url
properties:
url:
type: string
format: uri
description: URL of the source file to fetch and store.
outputs:
type: object
description: Optional renditions and/or transcription to generate.
properties:
renditions:
type: array
items:
type: object
properties:
format:
type: string
resolution:
type: string
transcription:
type: object
properties:
format:
type: string
SourceResponse:
type: object
properties:
data:
type: object
properties:
type:
type: string
example: source
id:
type: string
format: uuid
attributes:
type: object
properties:
id:
type: string
format: uuid
owner:
type: string
source:
type: string
format: uri
status:
type: string
enum: [queued, importing, ready, failed, deleted]
created:
type: string
format: date-time
updated:
type: string
format: date-time
SourceListResponse:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/SourceResponse'
UploadResponse:
type: object
properties:
data:
type: object
properties:
type:
type: string
example: upload
id:
type: string
format: uuid
attributes:
type: object
properties:
id:
type: string
format: uuid
url:
type: string
format: uri
description: Signed URL to PUT the file to.
AssetResponse:
type: object
properties:
data:
type: object
properties:
type:
type: string
example: asset
id:
type: string
format: uuid
attributes:
type: object
properties:
id:
type: string
format: uuid
owner:
type: string
region:
type: string
renderId:
type: string
format: uuid
filename:
type: string
url:
type: string
format: uri
status:
type: string
enum: [queued, transferring, ready, failed, deleted]
created:
type: string
format: date-time
updated:
type: string
format: date-time
AssetListResponse:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/AssetResponse'
TransferRequest:
type: object
required:
- url
properties:
url:
type: string
format: uri
description: URL of the file to transfer.
destinations:
type: array
items:
type: object
properties:
provider:
type: string
enum: [shotstack, s3, googlecloudstorage, googledrive, mux, vimeo]
GenerateAssetRequest:
type: object
required:
- provider
- options
properties:
provider:
type: string
description: The generation provider.
enum: [shotstack, elevenlabs, stability-ai, openai]
options:
type: object
required:
- type
properties:
type:
type: string
enum: [text-to-speech, text-to-image, image-to-video, text-generation]
text:
type: string
description: Prompt or text input for the generation.
prompt:
type: string
voice:
type: string
language:
type: string
GenerateAssetResponse:
type: object
properties:
data:
type: object
properties:
type:
type: string
example: asset
id:
type: string
format: uuid
attributes:
type: object
properties:
id:
type: string
format: uuid
owner:
type: string
provider:
type: string
type:
type: string
status:
type: string
enum: [queued, processing, done, failed]
url:
type: string
format: uri
created:
type: string
format: date-time
updated:
type: string
format: date-time
Error:
type: object
properties:
success:
type: boolean
example: false
message:
type: string
response:
type: object
properties:
error:
type: string
code:
type: string