openapi: 3.2.0 info: title: VideoGen Projects API version: 1.0.0 description: Programmatically generate images, videos, voiceovers, sound effects, and avatar clips. servers: - url: https://api.videogen.io description: Production security: - bearerAuth: [] tags: - name: Projects description: Read project metadata and status. paths: /v1/projects: get: tags: - Projects operationId: listProjects x-fern-audiences: - rest summary: List projects description: Returns projects, most recently updated first. By default only API-created projects are included; pass `includeUiProjects=true` to also include dashboard-created projects. Use `selfOnly=true` to restrict results to the calling API key's user; otherwise all matching projects for the team are returned. Cursor-paginated; see the Pagination guide. parameters: - $ref: '#/components/parameters/PaginationLimit' - $ref: '#/components/parameters/PaginationCursor' - $ref: '#/components/parameters/SelfOnlyQuery' - $ref: '#/components/parameters/IncludeUiProjectsQuery' responses: '200': description: Paginated list of projects. content: application/json: schema: $ref: '#/components/schemas/ListProjectsResponse' default: description: Error content: application/json: schema: $ref: '#/components/schemas/ApiError' /v1/projects/{projectId}: get: tags: - Projects operationId: getProject x-fern-audiences: - rest summary: Get project metadata description: Returns a simplified view of a project including its title, aspect ratio, status, and URL. parameters: - $ref: '#/components/parameters/ProjectIdPath' responses: '200': description: Project metadata. content: application/json: schema: $ref: '#/components/schemas/ProjectResponse' default: description: Error content: application/json: schema: $ref: '#/components/schemas/ApiError' /v1/projects/{projectId}/export: post: tags: - Projects operationId: exportProject x-fern-audiences: - rest summary: Export a project as MP4 description: Starts an export of a project to MP4. Returns immediately with an export id; the file becomes available when the export task completes. Exporting requires a paid plan in the app, but the API lets you export for free with a VideoGen watermark and a short 'Made with VideoGen' end screen appended to the video. A Pro plan lets you remove both by setting `watermarkMode` and `endScreenMode` to `NONE`. parameters: - $ref: '#/components/parameters/ProjectIdPath' requestBody: required: false content: application/json: schema: $ref: '#/components/schemas/ExportProjectRequest' responses: '202': description: Export accepted. content: application/json: schema: $ref: '#/components/schemas/ExportProjectResponse' default: description: Error content: application/json: schema: $ref: '#/components/schemas/ApiError' /v1/projects/{projectId}/exports: get: tags: - Projects operationId: listProjectExports x-fern-audiences: - rest summary: List project exports description: Returns a project's exports, newest first, as fully hydrated `ProjectExport` objects (status, signed download/thumbnail URLs, and the embedded `file`). Signed URLs are re-signed when within an hour of expiring, so they are always valid long enough to use. Cursor-paginated; see the Pagination guide. parameters: - $ref: '#/components/parameters/ProjectIdPath' - $ref: '#/components/parameters/PaginationLimit' - $ref: '#/components/parameters/PaginationCursor' responses: '200': description: Project exports. content: application/json: schema: $ref: '#/components/schemas/ListProjectExportsResponse' default: description: Error content: application/json: schema: $ref: '#/components/schemas/ApiError' /v1/projects/{projectId}/exports/{exportId}: get: tags: - Projects operationId: getProjectExport x-fern-audiences: - rest summary: Get project export description: Returns the current status of a project export started via `POST /v1/projects/{projectId}/export`, and — once `status` is `succeeded` — the signed download/thumbnail URLs and the hydrated export `file`. Poll this endpoint until `status` is `succeeded`, `failed`, or `cancelled`. The signed URLs are private and valid for 7 days; this endpoint automatically re-signs them when they are within an hour of expiring, so a caller always receives a URL valid long enough to use. Every endpoint that returns hydrated files auto-rehydrates this way — only the file endpoints (`GET /v1/files/{fileId}` and `POST /v1/files/{fileId}/hydrate`) are the explicit, on-demand hydration paths. Use `exportFileId` with `POST /v1/files/{fileId}/hydrate` if you need to re-sign the export file directly later. parameters: - $ref: '#/components/parameters/ProjectIdPath' - $ref: '#/components/parameters/ExportIdPath' responses: '200': description: Export status. content: application/json: schema: $ref: '#/components/schemas/ProjectExport' default: description: Error content: application/json: schema: $ref: '#/components/schemas/ApiError' /v1/projects/{projectId}/timeline-interchange: post: tags: - Projects operationId: createTimelineInterchange x-fern-audiences: - rest summary: Create a timeline interchange description: 'Starts a timeline interchange job that converts a project into an editor interchange document (Final Cut Pro FCPXML, Adobe Premiere Pro XML, OpenTimelineIO, or an SRT caption sidecar). Returns immediately with an interchange job id; the file becomes available when the job completes. Unlike `POST /v1/projects/{projectId}/export` (which renders a flattened MP4), this preserves the project as an editable timeline of separate clips, tracks, and captions so you can keep editing it in a desktop video editor. Choose `mediaDelivery` to control how the document references media: `REMOTE_URLS` produces a single document that links to signed media URLs, while `BUNDLE` produces a zip containing the document plus every referenced media file for durable offline relinking.' parameters: - $ref: '#/components/parameters/ProjectIdPath' requestBody: required: false content: application/json: schema: $ref: '#/components/schemas/CreateTimelineInterchangeRequest' responses: '202': description: Timeline interchange accepted. content: application/json: schema: $ref: '#/components/schemas/CreateTimelineInterchangeResponse' default: description: Error content: application/json: schema: $ref: '#/components/schemas/ApiError' /v1/timeline-interchange/{interchangeJobId}: get: tags: - Projects operationId: getTimelineInterchange x-fern-audiences: - rest summary: Get timeline interchange job description: Returns the current status of a timeline interchange job started via `POST /v1/projects/{projectId}/timeline-interchange`, and, once `status` is `succeeded`, the signed download URL and the hydrated interchange `file`. Poll this endpoint until `status` is `succeeded`, `failed`, or `cancelled`. The signed URL is private and valid for 7 days; this endpoint automatically re-signs it when it is within an hour of expiring. Use `interchangeFileId` with `POST /v1/files/{fileId}/hydrate` if you need to re-sign the file directly later. parameters: - $ref: '#/components/parameters/InterchangeJobIdPath' responses: '200': description: Timeline interchange status. content: application/json: schema: $ref: '#/components/schemas/TimelineInterchange' default: description: Error content: application/json: schema: $ref: '#/components/schemas/ApiError' /v1/projects/{projectId}/remix: post: tags: - Projects operationId: remixProject x-fern-audiences: - rest summary: Apply remix actions to a project description: Applies an ordered list of edits (background music, logo overlay, caption visibility/style) to a project. Each action runs asynchronously as its own remix action; the response returns one remix action id per action in order. Set `saveAsNewProject` to apply the edits to a copy and leave the original untouched. Poll `GET /v1/projects/{projectId}/remix-actions` for status. parameters: - $ref: '#/components/parameters/ProjectIdPath' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/RemixProjectRequest' responses: '202': description: Remix actions accepted. content: application/json: schema: $ref: '#/components/schemas/RemixProjectResponse' default: description: Error content: application/json: schema: $ref: '#/components/schemas/ApiError' /v1/projects/{projectId}/remix-actions: get: tags: - Projects operationId: listProjectRemixActions x-fern-audiences: - rest summary: List remix actions for a project description: Returns remix actions applied to a project (via `POST /v1/projects/{projectId}/remix` or as a post-workflow step), most recent first, with each action's status and progress. Cursor-paginated; see the Pagination guide. parameters: - $ref: '#/components/parameters/ProjectIdPath' - $ref: '#/components/parameters/PaginationLimit' - $ref: '#/components/parameters/PaginationCursor' responses: '200': description: Remix actions for the project. content: application/json: schema: $ref: '#/components/schemas/ListRemixActionsResponse' default: description: Error content: application/json: schema: $ref: '#/components/schemas/ApiError' components: schemas: RemixActionCleanUpTranscript: type: object required: - type description: Tighten every transcript in the project by removing silent pauses and/or filler words. Useful for polishing narration captured from raw recordings. properties: type: type: string enum: - CLEAN_UP_TRANSCRIPT removeFillers: type: - boolean - 'null' description: Remove filler words ("um", "uh", …). Defaults to `true`. removePauses: type: - boolean - 'null' description: Remove silent pauses longer than `minPauseSeconds`. Defaults to `true`. fillerWords: type: - array - 'null' items: type: string description: Override the filler-word list to remove. Omit or pass `null` to use the built-in defaults. minPauseSeconds: type: - number - 'null' minimum: 0 description: Shortest pause (in seconds) to remove; pauses below this stay. Omit or pass `null` to use the default threshold. ExportProjectRequest: type: object properties: quality: $ref: '#/components/schemas/ExportProjectQuality' watermarkMode: $ref: '#/components/schemas/WatermarkMode' endScreenMode: $ref: '#/components/schemas/EndScreenMode' deliveryDestinations: type: array description: Destinations to deliver the finished export to when it completes, in addition to any delivery destinations already saved for the team. Each destination references a connected integration. items: $ref: '#/components/schemas/ExportDeliveryDestination' RemixActionRun: type: object required: - remixActionId - type - status - projectId - projectUrl - progressPercentage - attemptIndex - error properties: remixActionId: type: string description: Opaque remix action id (e.g. `vg_rmix_...`). type: $ref: '#/components/schemas/RemixActionType' status: $ref: '#/components/schemas/JobStatus' projectId: type: string description: Id of the project this remix action edits (e.g. `vg_proj_...`). projectUrl: type: string format: uri description: 'Deep link to open this project in the VideoGen web editor. Not required for an API-only integration: store `projectId` and use the Projects API (export, remix, metadata). Use `projectUrl` when a person should open the project in the app to review or edit it manually. The project is visible only to members of your team and any project collaborators, the same access model as a project created in the dashboard.' progressPercentage: type: number minimum: 0 maximum: 100 description: Completion progress for the current attempt (0-100). Always `100` when `status` is `succeeded`. attemptIndex: type: integer minimum: 0 description: Zero-based index of the current or most recent execution attempt. error: description: Error details. Always present as a field; `null` unless `status` is `failed`. anyOf: - $ref: '#/components/schemas/ApiError' - type: 'null' RemixActionUpscaleAssets: type: object required: - type description: 'Sharpen every eligible asset in the project up to 4K, replacing each in place. Runs asynchronously: one upscaled asset is generated per eligible asset. If the project has no eligible assets, the action is skipped and completes successfully without changing anything.' properties: type: type: string enum: - UPSCALE_ASSETS includeVideos: type: - boolean - 'null' description: Also upscale video assets (billed per output second). Defaults to `true`. includeStockContent: type: - boolean - 'null' description: Also upscale stock (library) assets, not just uploaded or generated ones. Defaults to `true`. RemixActionEnableCaptions: type: object required: - type description: Show captions on every captionable section. Optionally override the project caption style. properties: type: type: string enum: - ENABLE_CAPTIONS captionStyle: description: Caption styling to apply. Omit or pass `null` to show captions with the current style. Any provided field overrides that field; omitted fields keep their current value. anyOf: - $ref: '#/components/schemas/WorkflowCaptionStyle' - type: 'null' AspectRatio: type: object required: - width - height description: Aspect ratio as a width:height pair (e.g. 16 and 9 for 16:9). Not pixel dimensions. properties: width: type: integer minimum: 1 height: type: integer minimum: 1 WatermarkMode: type: string enum: - NONE - VIDEO_GEN - AUTO default: AUTO description: Controls whether the VideoGen watermark is applied to the output. `AUTO` applies the watermark unless you have a Pro plan. `VIDEO_GEN` always applies it. `NONE` removes the watermark (requires Pro; returns an error if you don't have it). FileInfo: type: object description: Metadata for a generated file. Obtain ids from tool results or `GET /v1/files`. required: - fileId - scope properties: fileId: type: string description: File id (e.g. `vg_file_...`). type: description: File type. Null when the file is still being processed and the type has not yet been determined. anyOf: - $ref: '#/components/schemas/FileType' - type: 'null' scope: type: string enum: - GLOBAL - PROJECT - EXPORT - TEMPORARY - ENTITY description: 'File scope. - `GLOBAL`: user-uploaded or standalone generated files that persist indefinitely. - `PROJECT`: project-specific files (e.g. text-to-speech clips in a generated project). - `EXPORT`: project exports. - `TEMPORARY`: short-lived files guaranteed to be available for 24 hours, after which they may be archived at any time. Not analyzed (no description, transcript, or embedding). - `ENTITY`: files attached to a reusable entity (e.g. a voice sample for an actor), shared across your team. ' displayName: type: string description: Display name for the file. description: type: - string - 'null' durationSeconds: type: - number - 'null' description: Duration in seconds for video and audio files. Null for images. transcript: description: Timed transcript for video and audio files, when available, as a `Transcript` object with timed `words`. Null for images or when no transcript has been generated. For plain transcript text, use `transcriptText`. anyOf: - $ref: '#/components/schemas/Transcript' - type: 'null' transcriptText: type: - string - 'null' description: Plain transcript text for video and audio files, when available. Null for images or when no transcript has been generated. downloadUrl: type: - string - 'null' format: uri description: Private signed URL for the highest-quality downloadable rendition, provided at the top level for convenience. Valid for 7 days from when it was signed. `null` when the rendition is still processing or the URL has not been signed yet. See `downloadUrlExpiresAt` for the exact expiry and `downloadSource` for the full rendition metadata; call `POST /v1/files/{fileId}/hydrate` to refresh it. downloadUrlExpiresAt: type: - integer - 'null' description: Seconds since epoch (Unix timestamp) when `downloadUrl` expires. `null` when `downloadUrl` is null. thumbnailUrl: type: - string - 'null' format: uri description: Private signed URL for the thumbnail rendition, provided at the top level for convenience. Valid for 7 days from when it was signed. `null` for file types that have no thumbnail (e.g. audio) or when it has not been signed yet. See `thumbnailSource` for the full rendition metadata. thumbnailUrlExpiresAt: type: - integer - 'null' description: Seconds since epoch (Unix timestamp) when `thumbnailUrl` expires. `null` when `thumbnailUrl` is null. thumbnailSource: description: Thumbnail image source. Populated after hydration. anyOf: - $ref: '#/components/schemas/FileSource' - type: 'null' previewSource: description: Preview rendition source (720p for video, resized for images). Populated after hydration. anyOf: - $ref: '#/components/schemas/FileSource' - type: 'null' downloadSource: description: Highest-quality downloadable rendition. Populated after hydration. anyOf: - $ref: '#/components/schemas/FileSource' - type: 'null' hlsSource: description: Private HLS streaming source. Populated for video and audio files once streaming renditions are ready. Uses a signed token; treat like other signed sources. anyOf: - $ref: '#/components/schemas/FileSource' - type: 'null' isPublicPreviewEnabled: type: boolean description: Whether public preview is enabled for this file. When true, `staticPublicPreviewSource` is populated for all file types. For video and audio, `publicHlsUrl` and `publicPlaybackId` are also populated once embed streaming is ready. staticPublicPreviewSource: description: Permanent public URL for the file's highest-quality rendition. Populated when `isPublicPreviewEnabled` is true. Does not expire (`expiresAt` is null). Use for direct links to images, downloads, or any file type. For embedded video or audio players, prefer `publicPlaybackId`. anyOf: - $ref: '#/components/schemas/FileSource' - type: 'null' publicHlsUrl: type: - string - 'null' description: Public HLS streaming URL for video and audio. Only present when `isPublicPreviewEnabled` is true and embed streaming is ready. Prefer `publicPlaybackId` with `@videogen/player` for embeds. publicPlaybackId: type: - string - 'null' description: Encoded public playback id (e.g. `vg_play_...`) for video and audio embeds. Pass this to `@videogen/player` or `@videogen/player-react`. Only present when `isPublicPreviewEnabled` is true and embed streaming is ready. For a permanent direct file URL (any type), use `staticPublicPreviewSource` instead. sourceToolType: type: string description: Tool type that generated this file (e.g. `GENERATE_IMAGE`, `TEXT_TO_SPEECH`). Only present when the file was created by a tool execution. sourceToolExecutionId: type: string description: Execution id of the tool call that generated this file (e.g. `vg_tool_...`). Only present when the file was created by a tool execution. fileAnalysisMetadata: description: Background analysis state for the file (used to populate `description`, `transcript`, `durationSeconds`, and the search embedding). Omitted when the file was returned via a path that does not check analysis progress (e.g. tool-result inline files and webhook payloads). $ref: '#/components/schemas/FileAnalysisMetadata' RemixProjectRequest: type: object required: - remixActions properties: remixActions: type: array items: $ref: '#/components/schemas/RemixAction' description: Ordered list of edits to apply. Each runs asynchronously as its own remix action. Must contain at least one action. saveAsNewProject: type: boolean description: When true, the project is duplicated first and the edits are applied to the copy, leaving the original untouched. The response's `projectId` is the copy. Defaults to false (edits the project in place). RemixActionDisableCaptions: type: object required: - type description: Hide captions on every captionable section. properties: type: type: string enum: - DISABLE_CAPTIONS ExportProjectResponse: type: object required: - exportId properties: exportId: type: string description: Opaque export id (e.g. `vg_expo_...`). Poll `GET /v1/projects/{projectId}/exports/{exportId}` or subscribe to webhooks for completion. TimelineInterchange: type: object required: - interchangeJobId - projectId - format - mediaDelivery - status - progressPercentage - attemptIndex - downloadUrl - downloadUrlExpiresAt - interchangeFileId - file - error properties: interchangeJobId: type: string description: Opaque timeline interchange job id (e.g. `vg_inte_...`) matching the original request. projectId: type: string description: Id of the source project (e.g. `vg_proj_...`). format: $ref: '#/components/schemas/TimelineInterchangeFormat' mediaDelivery: $ref: '#/components/schemas/TimelineInterchangeMediaDelivery' status: $ref: '#/components/schemas/JobStatus' progressPercentage: type: number minimum: 0 maximum: 100 description: Completion progress for the current attempt (0-100). Always `100` when `status` is `succeeded`. attemptIndex: type: integer minimum: 0 description: Zero-based index of the current or most recent job attempt. downloadUrl: type: - string - 'null' format: uri description: Private signed download URL for the interchange document (or the media bundle zip when `mediaDelivery` is `BUNDLE`), valid for 7 days from when it was signed. Always present as a field; `null` until `status` is `succeeded`. This endpoint automatically re-signs the URL when it is within an hour of expiring. To fetch a fresh URL directly from the underlying file at any time, use `interchangeFileId` with the hydrate-file endpoint. downloadUrlExpiresAt: type: - integer - 'null' description: Seconds since epoch (Unix timestamp) when `downloadUrl` expires. `null` while `downloadUrl` is null. interchangeFileId: type: - string - 'null' description: File id (e.g. `vg_file_...`) of the interchange document or bundle zip. Always present as a field; `null` until `status` is `succeeded`. Pass it to `POST /v1/files/{fileId}/hydrate` to fetch fresh signed URLs directly from the file at any time. file: description: Hydrated interchange file metadata with a signed download URL. Always present as a field; `null` until `status` is `succeeded`. Its signed URL follows the same 24-hour validity and automatic re-signing as `downloadUrl`. anyOf: - $ref: '#/components/schemas/FileInfo' - type: 'null' error: description: Error details. Always present as a field; `null` unless `status` is `failed`. anyOf: - $ref: '#/components/schemas/ApiError' - type: 'null' ExportProjectQuality: type: string description: Vertical resolution tier for the rendered MP4. enum: - STANDARD - HIGH - FULL_HIGH - ULTRA_HIGH EndScreenMode: type: string enum: - NONE - VIDEO_GEN - AUTO default: AUTO description: Controls whether a short 'Made with VideoGen' end screen is appended to the output. `AUTO` appends it unless you have a Pro plan. `VIDEO_GEN` always appends it. `NONE` removes it (requires Pro; returns an error if you don't have it). RemixTransitionStyle: type: string description: A transition applied at a boundary. `DYNAMIC` auto-varies the style across boundaries; `NONE` removes transitions; the rest apply that fixed style everywhere. enum: - DYNAMIC - NONE - FADE - RISE - PAN - POP - WIPE FileSource: type: object description: A rendition source for a file (e.g. thumbnail, preview, download). Contains a signed URL and metadata. required: - status properties: status: type: string enum: - pending - ready - failed - skipped description: '`pending`: asset is still processing or has not been hydrated yet. `ready`: signed URL is available. `failed`: rendition generation failed. `skipped`: rendition does not apply to this file type (e.g. thumbnail for audio).' url: type: - string - 'null' description: Signed URL. Present when status is `ready` and file has been recently hydrated. If missing, call the hydrate endpoint. expiresAt: type: - integer - 'null' description: Seconds since epoch (Unix timestamp) when the signed URL expires. width: type: - integer - 'null' description: Rendition width in pixels, when known. height: type: - integer - 'null' description: Rendition height in pixels, when known. fileBytes: type: - integer - 'null' description: File size in bytes, when known. RemixActionGenerateMusic: type: object required: - type - prompt description: Generate a background music track from a text prompt and set it as the project's background music, replacing any existing track. Runs asynchronously. properties: type: type: string enum: - GENERATE_MUSIC prompt: type: string description: Describe the music to generate (e.g. "upbeat corporate background music with a driving beat"). RemixActionAddTransitions: type: object required: - type description: 'Stamp transitions across the project. Not per-boundary: each field you set is applied uniformly to every boundary in that scope, replacing any transition already there. Set the transition between sections, between base-layer assets, or both; omit or pass `null` for a scope to leave its transitions untouched.' properties: type: type: string enum: - ADD_TRANSITIONS sectionTransition: description: Transition applied at every boundary between sections, replacing any existing section transitions. Omit or pass `null` to leave section transitions untouched. anyOf: - $ref: '#/components/schemas/RemixTransitionStyle' - type: 'null' assetTransition: description: Transition applied at every boundary between base-layer assets within sections, replacing any existing asset transitions. Omit or pass `null` to leave asset transitions untouched. anyOf: - $ref: '#/components/schemas/RemixTransitionStyle' - type: 'null' RemixActionType: type: string description: The kind of edit a remix action applies. enum: - SET_BACKGROUND_MUSIC - SET_LOGO - ENABLE_CAPTIONS - DISABLE_CAPTIONS - ADD_TRANSITIONS - ADD_ZOOM - RESIZE_PROJECT - CLEAN_UP_TRANSCRIPT - CONVERT_IMAGES_TO_VIDEOS - REGENERATE_IMAGES - UPSCALE_ASSETS - CHANGE_NARRATOR - SHUFFLE_STOCK_VISUALS - GENERATE_MUSIC - TRANSLATE_PROJECT CreateTimelineInterchangeRequest: type: object properties: format: $ref: '#/components/schemas/TimelineInterchangeFormat' mediaDelivery: $ref: '#/components/schemas/TimelineInterchangeMediaDelivery' RemixActionChangeNarrator: type: object required: - type - voiceId description: 'Re-narrate every AI-voiceover asset in the project with a new voice and optional actor avatar, replacing each narration in place. Runs asynchronously: text-to-speech is re-fired per asset with the original narration text. If the project has no AI-narrated assets, the action is skipped and completes successfully without changing anything.' properties: type: type: string enum: - CHANGE_NARRATOR voiceId: type: string description: Catalog `displayName` (e.g. `Matilda`) or voice id from `GET /v1/resources/tts-voices` (e.g. `vg_voic_...`) to re-narrate with. actorEntityId: type: - string - 'null' description: Recommended. Optional id of a built-in stock actor or an ACTOR entity (e.g. `vg_enti_...`) with an image reference. When set, narration is delivered by that actor avatar. Omit or pass `null` for voiceover without an avatar. avatarQuality: $ref: '#/components/schemas/ModelQuality' description: Avatar generation quality tier. Applies when `actorEntityId` is provided. Optional; when omitted, your account's Default AI quality for avatars is used. voiceSpeed: type: - number - 'null' minimum: 0.5 maximum: 2 description: Speech rate multiplier, between 0.5 (half speed) and 2 (double speed). Omit or pass `null` to keep each asset's current speed. RemixActionAddZoom: type: object required: - type description: Apply a Ken Burns zoom to every eligible still image in the project, including uploaded images. Replaces any existing still-image effect on those assets. If the project has no eligible stills, the action is skipped and completes successfully without changing anything. properties: type: type: string enum: - ADD_ZOOM ApiError: type: object description: 'Standard error body returned with every non-2xx response (the `default` response of every operation). The HTTP status code conveys the error class; this body carries the details: - `400` invalid request, `401` missing or invalid API key, `403` not permitted (e.g. plan or add-on required, see `requirement`), `404` not found, `409` conflict, `429` rate limited or out of credits, `5xx` server error. Common `code` values include `invalid_request`, `invalid_api_key`, `not_authorized`, `not_found`, `insufficient_credits`, and `rate_limited`. Always branch on `code` (and `requirement.type` when present) rather than parsing `message`. ' required: - message properties: message: type: string description: Human-readable error description. For display and logging only; do not branch on its exact text. code: type: - string - 'null' description: Machine-readable error code in snake_case (e.g. `invalid_api_key`, `insufficient_credits`). `null` when no specific code applies. requirement: description: What is needed to resolve the error. Present when the error can be fixed by fulfilling a specific requirement (e.g. purchasing an add-on); `null` otherwise. anyOf: - $ref: '#/components/schemas/ErrorRequirement' - type: 'null' internalErrorCode: type: - string - 'null' description: Opaque internal error code for debugging. Include this when contacting support. `null` when not applicable. RemixActionTranslateProject: type: object required: - type - languageCode description: 'Translate the whole project into another language: every piece of text (title, section names, on-screen text overlays, transcripts, and narration scripts) is translated, and — unless disabled — each AI voiceover is re-narrated in the new language. Runs asynchronously. Requires a Pro subscription. Retrieve the list of supported language codes from `GET /v1/resources/languages`.' properties: type: type: string enum: - TRANSLATE_PROJECT languageCode: type: string description: Target language code to translate the project into (e.g. `es`, `fr`, `ja`). Must be one of the codes returned by `GET /v1/resources/languages`. changeVoice: type: - boolean - 'null' description: Swap each AI voiceover to a voice that natively matches the target language. Recommended, since keeping the original voice usually produces a foreign accent. Defaults to `true`. translateImageText: type: - boolean - 'null' description: Also re-generate every eligible image so that text baked into the image is translated too (image-to-image). Billed per generated image. Defaults to `false`. ErrorRequirement: type: object description: What is needed to resolve an error, when it can be fixed by fulfilling a specific requirement (e.g. purchasing an add-on or upgrading the plan). required: - type properties: type: type: string description: Machine-readable requirement type in snake_case (e.g. `purchase_add_on`, `upgrade_plan`). details: type: object additionalProperties: type: string description: Key-value pairs with requirement-specific context (e.g. the add-on id to purchase). RemixProjectResponse: type: object description: Returned when remix actions are accepted. Poll `GET /v1/projects/{projectId}/remix-actions` for status. required: - projectId - projectUrl - remixActionIds properties: projectId: type: string description: Id of the edited project (e.g. `vg_proj_...`; the duplicate when `saveAsNewProject` was true). projectUrl: type: string format: uri description: 'Deep link to open this project in the VideoGen web editor. Not required for an API-only integration: store `projectId` and use the Projects API (export, remix, metadata). Use `projectUrl` when a person should open the project in the app to review or edit it manually. The project is visible only to members of your team and any project collaborators, the same access model as a project created in the dashboard.' remixActionIds: type: array items: type: string description: Opaque remix action ids (e.g. `vg_rmix_...`), one per requested action in order. TimelineInterchangeFormat: type: string description: Editor interchange document format. `FCPXML` is Final Cut Pro (also imported by DaVinci Resolve and others). `PREMIERE_XML` is the Final Cut 7 `xmeml` XML that Adobe Premiere Pro imports natively. `OTIO` is OpenTimelineIO, the vendor-neutral format. `SRT` is a SubRip caption sidecar. enum: - FCPXML - PREMIERE_XML - OTIO - SRT RemixActionShuffleStockVisuals: type: object required: - type description: 'Replace every stock (library) visual in the project with a fresh alternative from the same search, replacing each in place. Runs asynchronously: each stock asset''s original search is re-run, excluding the currently-shown result. If the project has no shuffleable stock visuals, the action is skipped and completes successfully without changing anything.' properties: type: type: string enum: - SHUFFLE_STOCK_VISUALS ExportDeliveryDestination: type: object required: - integrationConnectionId - type properties: integrationConnectionId: type: string description: Id of the connected integration that will receive this export. type: type: string description: Where to deliver the export within the connected integration. enum: - SLACK_CHANNEL - GOOGLE_DRIVE_FOLDER slackChannelId: type: - string - 'null' description: Target channel id. Required when `type` is `SLACK_CHANNEL`. googleDriveFolderId: type: - string - 'null' description: Target folder id. Required when `type` is `GOOGLE_DRIVE_FOLDER`. TranscriptWord: type: object required: - startSeconds - endSeconds - word description: A single timed word of a transcript. properties: startSeconds: type: number minimum: 0 description: Start time of the word in seconds from the beginning of the audio. endSeconds: type: number description: End time of the word in seconds from the beginning of the audio. Must be greater than `startSeconds`. word: type: string description: The spoken word, used verbatim for narration timing and captions. ProjectExport: type: object required: - exportId - projectId - status - progressPercentage - attemptIndex - downloadUrl - downloadUrlExpiresAt - thumbnailUrl - thumbnailUrlExpiresAt - exportFileId - file - error properties: exportId: type: string description: Opaque export id (e.g. `vg_expo_...`) matching the original request. projectId: type: string description: Id of the exported project (e.g. `vg_proj_...`). status: $ref: '#/components/schemas/JobStatus' progressPercentage: type: number minimum: 0 maximum: 100 description: Completion progress for the current attempt (0-100). Always `100` when `status` is `succeeded`. attemptIndex: type: integer minimum: 0 description: Zero-based index of the current or most recent export attempt. downloadUrl: type: - string - 'null' format: uri description: Private signed MP4 download URL, valid for 7 days from when it was signed. Always present as a field; `null` until `status` is `succeeded`. This endpoint automatically re-signs the URL when it is within an hour of expiring, so a fresh call to get the export always returns a URL valid long enough to use. See `downloadUrlExpiresAt` for the exact expiry. To fetch a fresh URL directly from the underlying file at any time, use `exportFileId` with the hydrate-file endpoint. downloadUrlExpiresAt: type: - integer - 'null' description: Seconds since epoch (Unix timestamp) when `downloadUrl` expires. `null` while `downloadUrl` is null. thumbnailUrl: type: - string - 'null' format: uri description: Private signed thumbnail URL, valid for 7 days from when it was signed. Always present as a field; `null` until `status` is `succeeded` (and when no thumbnail is available). Re-signed automatically on the same terms as `downloadUrl`. thumbnailUrlExpiresAt: type: - integer - 'null' description: Seconds since epoch (Unix timestamp) when `thumbnailUrl` expires. `null` while `thumbnailUrl` is null. exportFileId: type: - string - 'null' description: File id (e.g. `vg_file_...`) of the exported MP4. Always present as a field; `null` until `status` is `succeeded`. Pass it to `POST /v1/files/{fileId}/hydrate` to fetch fresh signed URLs directly from the file at any time, which is useful once the 24-hour URLs above have expired. file: description: Hydrated export file metadata with signed download URLs. Always present as a field; `null` until `status` is `succeeded`. Its signed URLs follow the same 24-hour validity and automatic re-signing as `downloadUrl`. anyOf: - $ref: '#/components/schemas/FileInfo' - type: 'null' error: description: Error details. Always present as a field; `null` unless `status` is `failed`. anyOf: - $ref: '#/components/schemas/ApiError' - type: 'null' Transcript: type: object required: - words description: A transcript of an audio file, as timed words in order. properties: languageCode: type: - string - 'null' description: Optional BCP-47 language code of the spoken audio (e.g. `en`, `es`). Used to tag the transcript's language; omit if unknown. words: type: array items: $ref: '#/components/schemas/TranscriptWord' description: The transcript words, sorted by `startSeconds` and non-overlapping. Must contain at least one word. RemixActionSetLogo: type: object required: - type description: Set, replace, or remove the logo overlay. properties: type: type: string enum: - SET_LOGO fileId: type: - string - 'null' description: File id of an uploaded image to overlay as a logo (e.g. `vg_file_...`). Upload it first via `POST /v1/files/upload`. Pass `null` to remove the existing logo. position: type: - string - 'null' enum: - TOP_LEFT - TOP_CENTER - TOP_RIGHT - BOTTOM_LEFT - BOTTOM_CENTER - BOTTOM_RIGHT - null description: Position the logo is anchored to. Omit or pass `null` to keep the current position. sizePercent: type: - number - 'null' description: Logo width as a percentage of the video width. Omit or pass `null` to keep the current size. RemixActionConvertImagesToVideos: type: object required: - type description: 'Animate every eligible still image in the project into a short AI video clip (image-to-video), replacing each image in place. Eligible images are non-SVG image assets backed by an uploaded or stock file. Runs asynchronously: one clip is generated per image. If the project has no eligible images, the action is skipped and completes successfully without changing anything (for example, a project whose timeline is already all video clips).' properties: type: type: string enum: - CONVERT_IMAGES_TO_VIDEOS motionPrompt: type: - string - 'null' description: Describe the motion to apply to every image (e.g. "slow cinematic push-in"). Omit or pass `null` for automatic motion. muteOutputVideos: type: - boolean - 'null' description: Mute the generated clips and suppress generated background music. Recommended when the clips sit behind a voiceover. Defaults to `true`. quality: $ref: '#/components/schemas/ModelQuality' description: Video generation quality tier for the image-to-video conversions (`LOW`, `STANDARD`, `HIGH`, or `MAX`). Optional; when omitted, your account's Default AI quality for video is used (change it at https://app.videogen.io/settings/account). CreateTimelineInterchangeResponse: type: object required: - interchangeJobId properties: interchangeJobId: type: string description: Opaque timeline interchange job id (e.g. `vg_inte_...`). Poll `GET /v1/timeline-interchange/{interchangeJobId}` for completion. ProjectResponse: type: object description: Simplified project metadata. required: - projectId - assistantId - title - aspectRatio - status - createdAt - updatedAt - projectUrl properties: projectId: type: string description: Opaque project id (e.g. `vg_proj_...`). assistantId: type: - string - 'null' description: Opaque id of this project's assistant conversation (e.g. `vg_asst_...`). Use with the Assistant API to send follow-up messages or list the assistant's prior messages for this project. `null` for older projects created before assistant chats were attached at creation time. title: type: string aspectRatio: $ref: '#/components/schemas/AspectRatio' status: type: string description: High-level project status. enum: - generating - ready createdAt: type: integer description: Seconds since epoch (Unix timestamp) when the project was created. updatedAt: type: integer description: Seconds since epoch (Unix timestamp) when the project was last updated. projectUrl: type: string format: uri description: 'Deep link to open this project in the VideoGen web editor. Not required for an API-only integration: store `projectId` and use the Projects API (export, remix, metadata). Use `projectUrl` when a person should open the project in the app to review or edit it manually. The project is visible only to members of your team and any project collaborators, the same access model as a project created in the dashboard.' ListProjectExportsResponse: type: object required: - exports - hasMore - nextCursor properties: exports: type: array items: $ref: '#/components/schemas/ProjectExport' description: Fully hydrated exports for this project, newest first. Each includes status, signed download/thumbnail URLs, and the embedded `file`. hasMore: type: boolean description: When true, there are more exports available. Pass `nextCursor` as the `cursor` query param to fetch the next page. nextCursor: type: - string - 'null' description: Opaque cursor to fetch the next page. `null` when `hasMore` is false. ListRemixActionsResponse: type: object required: - remixActions - hasMore - nextCursor properties: remixActions: type: array items: $ref: '#/components/schemas/RemixActionRun' description: Remix actions for the project, most recent first. hasMore: type: boolean description: When true, there are more remix actions available. Pass `nextCursor` as the `cursor` query param to fetch the next page. nextCursor: type: - string - 'null' description: Opaque cursor to fetch the next page. `null` when `hasMore` is false. WorkflowRgbColor: type: object required: - red - green - blue description: An RGB color. Each channel is an integer from 0 to 255. properties: red: type: integer minimum: 0 maximum: 255 green: type: integer minimum: 0 maximum: 255 blue: type: integer minimum: 0 maximum: 255 RemixActionSetBackgroundMusic: type: object required: - type description: Set, replace, or remove the project's background music track. properties: type: type: string enum: - SET_BACKGROUND_MUSIC fileId: type: - string - 'null' description: File id of an uploaded audio file to use as background music (e.g. `vg_file_...`). Upload it first via `POST /v1/files/upload`. Pass `null` to remove the existing background music. volume: type: - number - 'null' minimum: 0 maximum: 1 description: Music volume from 0 (silent) to 1 (full). Omit or pass `null` to keep the current volume. TimelineInterchangeMediaDelivery: type: string description: How the interchange document references media. `REMOTE_URLS` produces a single document that links to signed media URLs. `BUNDLE` produces a zip containing the document plus every referenced media file, referenced by relative path, for durable offline relinking. enum: - REMOTE_URLS - BUNDLE WorkflowCaptionBackgroundStyle: type: object required: - type - backgroundColor description: Background drawn behind caption text. properties: type: type: string enum: - RECT - WRAPPED - WORD_BY_WORD description: RECT draws one rectangle behind the whole line; WRAPPED hugs the text; WORD_BY_WORD draws a box per word. backgroundColor: $ref: '#/components/schemas/WorkflowRgbColor' borderRadiusProportion: type: number minimum: 0 maximum: 1 description: Corner rounding as a proportion of the background height, between 0 (square corners) and 1 (fully rounded). opacityProportion: type: number minimum: 0 maximum: 1 description: Background opacity from 0 (transparent) to 1 (opaque). FileAnalysisMetadata: type: object description: 'Background analysis state for a file. Background analysis populates `description`, `transcript`, `durationSeconds`, and the search embedding after a file is uploaded or generated; this object lets you render a progress indicator while it runs (and skip rendering once it''s done). ' required: - analysisLoadingState - analysisProgressPercentage properties: analysisLoadingState: type: string enum: - UNATTEMPTED - LOADING - FULFILLED - REJECTED description: 'Coarse-grained analysis state. - `UNATTEMPTED`: analysis has not started yet. - `LOADING`: analysis is in progress. - `FULFILLED`: analysis completed successfully. `description`, `transcript`, and `durationSeconds` are now populated where applicable for the file''s type. - `REJECTED`: analysis failed permanently and will not be retried. ' analysisProgressPercentage: type: number description: Progress in `[0, 100]`. Always `100` when `analysisLoadingState` is `FULFILLED`. Otherwise the most recent in-flight progress reported by the analysis task (or `0` if no progress has been reported yet). analysisAttemptIndex: type: integer description: Zero-based index of the current analysis task attempt. Only present while analysis is still loading (`UNATTEMPTED` or `LOADING`); omitted once analysis reaches a terminal state. ModelQuality: type: string enum: - LOW - STANDARD - HIGH - MAX description: 'AI generation quality tier, shared across every generative feature (image, video, text, and so on). `LOW` is fastest and cheapest, `STANDARD` balances quality and cost, `HIGH` is higher quality, and `MAX` is the highest quality. When a request omits the quality field, VideoGen falls back to your account''s **Default AI quality** for that feature, which you can change at [Account settings](https://app.videogen.io/settings/account). Not every feature supports every tier; unsupported tiers are rejected with an error (see each field''s description). ' JobStatus: type: string description: Lifecycle status shared by every asynchronous job (tool executions, workflow runs, remix actions, project exports, and timeline interchange jobs). `pending` and `running` are in-progress; `succeeded`, `failed`, and `cancelled` are terminal. enum: - pending - running - succeeded - failed - cancelled WorkflowCaptionStyle: type: object description: Caption styling. Any omitted field falls back to the VideoGen default caption style. Provide an empty object (`{}`) to keep the default style but ensure captions are shown. Pass `null` for the whole `captionStyle` field to hide captions entirely. properties: fontName: type: string description: Font family name. fontSize: type: number minimum: 1 description: Font size in pixels at 1080p. Must be greater than 0. fontWeight: type: integer enum: - 100 - 200 - 300 - 400 - 500 - 600 - 700 - 800 - 900 description: Numeric font weight (400 = regular, 700 = bold). textColor: $ref: '#/components/schemas/WorkflowRgbColor' textJustification: type: string enum: - LEFT - CENTER - RIGHT verticalAlignment: type: string enum: - TOP - MIDDLE - BOTTOM description: Vertical position of the caption block in the frame. strokeColor: description: Outline color around glyphs, or null for no outline. anyOf: - $ref: '#/components/schemas/WorkflowRgbColor' - type: 'null' strokeWeight: type: number minimum: 0 description: Outline thickness in pixels. 0 disables the outline. backgroundStyle: description: Background drawn behind the text, or null for no background. anyOf: - $ref: '#/components/schemas/WorkflowCaptionBackgroundStyle' - type: 'null' spokenTextColor: description: Color applied to the currently spoken word for karaoke-style highlighting, or null to keep the base text color. anyOf: - $ref: '#/components/schemas/WorkflowRgbColor' - type: 'null' spokenTextStrokeColor: description: Outline color applied to the currently spoken word, or null. anyOf: - $ref: '#/components/schemas/WorkflowRgbColor' - type: 'null' persistSpokenTextColor: type: boolean description: When true, a word keeps the spoken-text color after it has been spoken instead of reverting. RemixActionRegenerateImages: type: object required: - type - stylePrompt description: 'Restyle every eligible still image in the project to a new look (image-to-image), replacing each image in place. Eligible images are non-SVG image assets backed by an uploaded or generated file. Runs asynchronously: one restyled image is generated per eligible image. If the project has no eligible images, the action is skipped and completes successfully without changing anything.' properties: type: type: string enum: - REGENERATE_IMAGES stylePrompt: type: string description: 'A full, strict paragraph for the look of every image (medium, texture, palette, then composition). Do not pass a short label such as `watercolor painting`. Image models pack the frame with text, charts, diagrams, and extra objects unless the style forbids that. Keep the picture simple: one uncluttered subject in the middle half of the frame, empty margins, and no on-image text or diagrams unless you asked for one specific word or number.' quality: $ref: '#/components/schemas/ModelQuality' description: Image generation quality tier for the restyled images. Optional; when omitted, your account's Default AI quality for images is used (change it at https://app.videogen.io/settings/account). RemixAction: description: A single edit applied to a project. Each array entry is exactly one of the action types below, chosen by its `type` field; the variants are mutually-exclusive options, not fields you must all provide. Include only the actions you want. oneOf: - $ref: '#/components/schemas/RemixActionSetBackgroundMusic' - $ref: '#/components/schemas/RemixActionSetLogo' - $ref: '#/components/schemas/RemixActionEnableCaptions' - $ref: '#/components/schemas/RemixActionDisableCaptions' - $ref: '#/components/schemas/RemixActionAddTransitions' - $ref: '#/components/schemas/RemixActionAddZoom' - $ref: '#/components/schemas/RemixActionResizeProject' - $ref: '#/components/schemas/RemixActionCleanUpTranscript' - $ref: '#/components/schemas/RemixActionConvertImagesToVideos' - $ref: '#/components/schemas/RemixActionRegenerateImages' - $ref: '#/components/schemas/RemixActionUpscaleAssets' - $ref: '#/components/schemas/RemixActionChangeNarrator' - $ref: '#/components/schemas/RemixActionShuffleStockVisuals' - $ref: '#/components/schemas/RemixActionGenerateMusic' - $ref: '#/components/schemas/RemixActionTranslateProject' discriminator: propertyName: type mapping: SET_BACKGROUND_MUSIC: '#/components/schemas/RemixActionSetBackgroundMusic' SET_LOGO: '#/components/schemas/RemixActionSetLogo' ENABLE_CAPTIONS: '#/components/schemas/RemixActionEnableCaptions' DISABLE_CAPTIONS: '#/components/schemas/RemixActionDisableCaptions' ADD_TRANSITIONS: '#/components/schemas/RemixActionAddTransitions' ADD_ZOOM: '#/components/schemas/RemixActionAddZoom' RESIZE_PROJECT: '#/components/schemas/RemixActionResizeProject' CLEAN_UP_TRANSCRIPT: '#/components/schemas/RemixActionCleanUpTranscript' CONVERT_IMAGES_TO_VIDEOS: '#/components/schemas/RemixActionConvertImagesToVideos' REGENERATE_IMAGES: '#/components/schemas/RemixActionRegenerateImages' UPSCALE_ASSETS: '#/components/schemas/RemixActionUpscaleAssets' CHANGE_NARRATOR: '#/components/schemas/RemixActionChangeNarrator' SHUFFLE_STOCK_VISUALS: '#/components/schemas/RemixActionShuffleStockVisuals' GENERATE_MUSIC: '#/components/schemas/RemixActionGenerateMusic' TRANSLATE_PROJECT: '#/components/schemas/RemixActionTranslateProject' RemixActionResizeProject: type: object required: - type - aspectRatio description: Change the project's output aspect ratio (e.g. to a vertical 9:16 social format). The video is re-flowed to the new ratio. properties: type: type: string enum: - RESIZE_PROJECT aspectRatio: $ref: '#/components/schemas/AspectRatio' FileType: type: string enum: - IMAGE - VIDEO - AUDIO - PDF - SLIDESHOW - TEXT - LOTTIE description: File type. `TEXT` covers plain-text and editor-interchange documents; `LOTTIE` is a JSON animation. ListProjectsResponse: type: object description: Paginated list of projects, most recently updated first. By default only API-created projects are included; pass `includeUiProjects=true` on the request to also include dashboard-created projects. required: - projects - hasMore - nextCursor properties: projects: type: array items: $ref: '#/components/schemas/ProjectResponse' hasMore: type: boolean description: When true, there are more projects available. Pass `nextCursor` as the `cursor` query param to fetch the next page. nextCursor: type: - string - 'null' description: Opaque cursor to fetch the next page. `null` when `hasMore` is false. parameters: ProjectIdPath: name: projectId in: path required: true schema: type: string description: The project id (e.g. `vg_proj_...`). PaginationCursor: name: cursor in: query required: false schema: type: string description: Opaque pagination cursor returned as `nextCursor` by the previous page. Omit on the first request. Cursors are tied to the endpoint that produced them and must be passed unmodified. See [Pagination](/pagination). InterchangeJobIdPath: name: interchangeJobId in: path required: true schema: type: string description: The timeline interchange job id (e.g. `vg_inte_...`) returned by `POST /v1/projects/{projectId}/timeline-interchange`. ExportIdPath: name: exportId in: path required: true schema: type: string description: The export id (e.g. `vg_expo_...`) returned by `POST /v1/projects/{projectId}/export`. IncludeUiProjectsQuery: name: includeUiProjects in: query required: false schema: type: boolean default: false description: When true, includes dashboard-created projects in addition to API-created projects. When false (default), returns only API-created projects. PaginationLimit: name: limit in: query required: false schema: type: integer minimum: 1 maximum: 200 default: 50 description: Maximum number of items to return in the page. Defaults to 50; capped at 200. See [Pagination](/pagination). SelfOnlyQuery: name: selfOnly in: query required: false schema: type: boolean default: false description: When true, returns only items created by the API key's owner. When false (default), returns all items accessible to the team. securitySchemes: bearerAuth: type: http scheme: bearer bearerFormat: opaque description: API key from [app.videogen.io/api](https://app.videogen.io/api). The full key is only shown once when you create it.