Skip to content
Create a key

Paste a key to use it in the examples on these pages. The key stays in this browser tab. These pages never send it anywhere.

Create a Vibe Editing project

create_vibe_edit_projectPOST/v1/projects/vibe-editBeta

Creates a Vibe Editing project from a video you uploaded: an edit of the whole video that you change with timeline operations.

Beta. This endpoint is supported and can gain new fields. If a change would break your code, we tell you before it takes effect and list it in the changelog.

About

Call it after complete_upload (POST /v1/uploads/{uploadId}/complete), with the id of the video to edit. The video is chosen here and only here: to edit another video, create another project. The language, the caption style and the shape are the choices the edit starts with; once it is prepared, change them on the timeline with apply_timeline_operations (POST /v1/projects/{projectId}/timeline/operations). Nothing is prepared and no credits are used until you call prepare_timeline (POST /v1/projects/{projectId}/timeline/prepare). Send an Idempotency-Key: a retry without one creates a second project.

Example use

A podcast producer uploads a full episode, creates a Vibe Editing project from it with the language and caption style of the show, and checks the price with estimate_analysis (POST /v1/projects/{projectId}/analyze/estimate) before the edit is prepared.

Endpoint

Code
POST https://api.gpt-video.com/v1/projects/vibe-edit
  • Scope clips:write.
  • Rate limit 60 requests a minute for each key and 120 for each account, shared by every write call. See rate limits.
  • Idempotency-Key is optional.

Parameters

Headers

NameTypeRequiredDescription
Idempotency-KeystringOptionalSend the same key on every retry of this request. From 1 to 255 visible characters, such as a UUID. See idempotency.

Body

NameTypeRequiredDescription
sourceAssetIdstringRequiredThe video to edit: the asset id that complete_upload (POST /v1/uploads/{uploadId}/complete) returned. It cannot be changed later. Matches ^ast_n?[0-9a-f]{20}$.
languagestringRequiredThe language spoken in the video: en, it, or auto to detect it. One of auto, it, en.
captionStylestringRequiredThe caption style the edit starts with. get_setting_options (GET /v1/reference/setting-options) lists every style with what it looks like. One of bold-karaoke, word-pop, boxed, outline.
aspectstringRequiredThe shape the edit starts with: source keeps the shape of the video, 9:16 is vertical, 1:1 square, 16:9 wide. One of source, 9:16, 1:1, 16:9.
vocabularystringOptionalNames, brands and jargon the transcription should spell right, separated by commas. At most 311 characters. At most 311 characters.
titlestringOptionalA name for the project, shown in the GPT-Video app. Leave it out to get a default name. From 1 to 120 characters. Matches \S.

Send only the fields listed here. Any other field is refused with UNKNOWN_PARAMETER.

Request

Create a Vibe Editing project.

Request example
# Create the key once. Send this same key again if you retry this request.
IDEMPOTENCY_KEY=$(uuidgen)
curl -X POST "https://api.gpt-video.com/v1/projects/vibe-edit" \
  -H "Authorization: Bearer $GPT_VIDEO_API_KEY" \
  -H "Idempotency-Key: $IDEMPOTENCY_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "sourceAssetId": "ast_8e21b0d94c6f4a17b358",
    "language": "en",
    "captionStyle": "word-pop",
    "aspect": "9:16",
    "title": "Product demo, edited"
  }'
// Create the key once. Send this same key again if you retry this request.
const idempotencyKey = crypto.randomUUID();
const res = await fetch("https://api.gpt-video.com/v1/projects/vibe-edit", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${process.env.GPT_VIDEO_API_KEY}`,
    "Idempotency-Key": idempotencyKey,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "sourceAssetId": "ast_8e21b0d94c6f4a17b358",
    "language": "en",
    "captionStyle": "word-pop",
    "aspect": "9:16",
    "title": "Product demo, edited"
  }),
});
const data = await res.json();
console.log(data);
import os
import uuid

import requests

# Create the key once. Send this same key again if you retry this request.
idempotency_key = str(uuid.uuid4())
r = requests.post(
    "https://api.gpt-video.com/v1/projects/vibe-edit",
    headers={
        "Authorization": f"Bearer {os.environ['GPT_VIDEO_API_KEY']}",
        "Idempotency-Key": idempotency_key,
    },
    json={
        "sourceAssetId": "ast_8e21b0d94c6f4a17b358",
        "language": "en",
        "captionStyle": "word-pop",
        "aspect": "9:16",
        "title": "Product demo, edited"
    },
)
data = r.json()
print(data)
{
  "method": "tools/call",
  "params": {
    "name": "create_vibe_edit_project",
    "arguments": {
      "sourceAssetId": "ast_8e21b0d94c6f4a17b358",
      "language": "en",
      "captionStyle": "word-pop",
      "aspect": "9:16",
      "title": "Product demo, edited"
    }
  }
}

Response

A successful call answers HTTP 201. Returns a Project object in project.

Fields to check

NameTypeDescription
project.idstringThe project id. It starts with prj_.
project.statusstringdraft has not been analyzed yet, processing is being analyzed, ready has clips, failed means the last analysis failed and errorMessage says why.

Response example

HTTP 201
{
  "project": {
    "id": "prj_6e2b9d14a7c3f0581e2d",
    "kind": "vibeedit",
    "title": "Product demo, edited",
    "status": "draft",
    "sourceAssetId": "ast_8e21b0d94c6f4a17b358",
    "compositionId": null,
    "settings": null,
    "missingSettings": [],
    "splitScreen": null,
    "streamer": null,
    "redditStory": null,
    "fakeText": null,
    "vibeEdit": {
      "sourceAssetId": "ast_8e21b0d94c6f4a17b358",
      "language": "en",
      "captionStyle": "word-pop",
      "aspect": "9:16",
      "vocabulary": null,
      "prepared": false
    },
    "errorMessage": null,
    "createdAt": "2026-09-01T11:00:00.000Z",
    "updatedAt": "2026-09-01T11:00:00.000Z"
  }
}
All response fields
NameTypeRequiredDescription
projectProject objectRequiredDescribed in Project object.
More examples

The video does not exist

POST /v1/projects/vibe-edit

Request body
{
  "sourceAssetId": "ast_0b1e5c9d3a7f40628e2d",
  "language": "en",
  "captionStyle": "word-pop",
  "aspect": "9:16"
}
HTTP 404
{
  "error": {
    "code": "NOT_FOUND",
    "message": "Asset ast_0b1e5c9d3a7f40628e2d not found",
    "hint": "Check the id. An id that belongs to another account is not found either.",
    "requestId": "req_4b7e1a9c3d0f52e86a1b7c04"
  }
}

Errors

CodeStatusWhenWhat to do
NOT_FOUND404The video does not existChange the request, then send it again.
CONFLICT409The asset is not a video, its file was deleted to free up storage, its size and length cannot be read, or it is longer than Vibe Editing accepts. The message says which one.Read the resource again, then decide. Do not send the same request again.

Every call can also answer these errors. VALIDATION_FAILED, UNKNOWN_PARAMETER, UNAUTHORIZED, SCOPE_MISSING, IDEMPOTENCY_IN_PROGRESS, PAYLOAD_TOO_LARGE, IDEMPOTENCY_KEY_REUSED, RATE_LIMITED, INTERNAL, UNAVAILABLE.

Cost

No credits are used. The preparation is charged when you call prepare_timeline (POST /v1/projects/{projectId}/timeline/prepare).

  • complete_upload (POST /v1/uploads/{uploadId}/complete) Complete an upload
  • prepare_timeline (POST /v1/projects/{projectId}/timeline/prepare) Prepare an edit
  • estimate_analysis (POST /v1/projects/{projectId}/analyze/estimate) Estimate the credits of an analysis or a build
  • get_project (GET /v1/projects/{projectId}) Get a project

Questions

Can I change the video of the project later?

No. The video of a Vibe Editing project is chosen when it is created and never changes. Create another project to edit another video, or add more videos to a prepared edit with add_timeline_clip (POST /v1/projects/{projectId}/timeline/clips).

Why is my video refused?

The video must be a video file you uploaded, with a size and a length that can be read, and short enough for the editor; the answer says which of these failed. A longer video can go through Auto Clip, which picks the best moments of it.

View as Markdown