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 project

create_projectPOST/v1/projectsBeta

Creates an Auto Clip project on a video you uploaded, with the settings you choose.

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 it returned. The source video is chosen here and only here: to analyze another video, create another project. You can set the settings now or later with update_project (PATCH /v1/projects/{projectId}); every setting listed in missingSettings must be chosen before analyze_project (POST /v1/projects/{projectId}/analyze). Nothing is analyzed and no credits are used until you call analyze_project. Send an Idempotency-Key: a retry without one creates a second project.

Example use

A podcast team uploads each new episode, creates a project on it with the language and the number of clips it wants, and checks the price with estimate_analysis (POST /v1/projects/{projectId}/analyze/estimate) before it calls analyze_project (POST /v1/projects/{projectId}/analyze).

Endpoint

Code
POST https://api.gpt-video.com/v1/projects
  • 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 analyze: the asset id that complete_upload (POST /v1/uploads/{uploadId}/complete) returned. It cannot be changed later. Matches ^ast_n?[0-9a-f]{20}$.
titlestringOptionalA name for the project. Leave it out to get a default name. From 1 to 120 characters. Matches \S.
settingsobjectOptionalAuto Clip settings. A field you leave out is left as it is, and every one can be set later with update_project (PATCH /v1/projects/{projectId}).
settings.languagestringOptionalThe language spoken in the video: en, it, or auto to detect it. One of auto, it, en.
settings.clipCountintegerOptionalHow many clips the analysis proposes. From 1 to 100. From 1 to 100.
settings.minDurationSecnumberOptionalThe shortest clip the analysis may propose, in seconds. From 5 to 180, and not longer than maxDurationSec when the analysis starts. From 5 to 180.
settings.maxDurationSecnumberOptionalThe longest clip the analysis may propose, in seconds. From 10 to 300. From 10 to 300.
settings.objectivestringOptionalWhat the clips should be good at. get_setting_options (GET /v1/reference/setting-options) lists every objective with what it means. One of viral, educational, entertaining, emotional, controversial, howto, business.
settings.captionStylestringOptionalThe caption style of the clips. get_setting_options (GET /v1/reference/setting-options) lists every style with what it looks like. One of bold-karaoke, word-pop, boxed, outline.
settings.reframestringOptionalHow a clip follows the speaker: face follows the face of the speaker, center keeps the middle of the frame. One of face, center.
settings.instructionsstring or nullOptionalFree text that tells the analysis what to look for, such as only the moments where a given person speaks. At most 2000 characters; null removes them. At most 2000 characters.
settings.vocabularystring or nullOptionalNames, brands and jargon the transcription should spell right, separated by commas. It is used when the video is transcribed, so set it before the first analysis. At most 311 characters; null removes it. At most 311 characters.

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

Request

Create a project on an uploaded video.

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" \
  -H "Authorization: Bearer $GPT_VIDEO_API_KEY" \
  -H "Idempotency-Key: $IDEMPOTENCY_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "sourceAssetId": "ast_8e21b0d94c6f4a17b358",
    "title": "Product demo clips",
    "settings": {
      "language": "en",
      "clipCount": 5,
      "minDurationSec": 20,
      "maxDurationSec": 45,
      "objective": "howto",
      "captionStyle": "bold-karaoke",
      "reframe": "face"
    }
  }'
// 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", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${process.env.GPT_VIDEO_API_KEY}`,
    "Idempotency-Key": idempotencyKey,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "sourceAssetId": "ast_8e21b0d94c6f4a17b358",
    "title": "Product demo clips",
    "settings": {
      "language": "en",
      "clipCount": 5,
      "minDurationSec": 20,
      "maxDurationSec": 45,
      "objective": "howto",
      "captionStyle": "bold-karaoke",
      "reframe": "face"
    }
  }),
});
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",
    headers={
        "Authorization": f"Bearer {os.environ['GPT_VIDEO_API_KEY']}",
        "Idempotency-Key": idempotency_key,
    },
    json={
        "sourceAssetId": "ast_8e21b0d94c6f4a17b358",
        "title": "Product demo clips",
        "settings": {
            "language": "en",
            "clipCount": 5,
            "minDurationSec": 20,
            "maxDurationSec": 45,
            "objective": "howto",
            "captionStyle": "bold-karaoke",
            "reframe": "face"
        }
    },
)
data = r.json()
print(data)
{
  "method": "tools/call",
  "params": {
    "name": "create_auto_clip_project",
    "arguments": {
      "sourceAssetId": "ast_8e21b0d94c6f4a17b358",
      "title": "Product demo clips",
      "settings": {
        "language": "en",
        "clipCount": 5,
        "minDurationSec": 20,
        "maxDurationSec": 45,
        "objective": "howto",
        "captionStyle": "bold-karaoke",
        "reframe": "face"
      }
    }
  }
}

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_27dd3348d28146ce5a3a",
    "kind": "autoclip",
    "title": "Product demo clips",
    "status": "draft",
    "sourceAssetId": "ast_8e21b0d94c6f4a17b358",
    "compositionId": null,
    "settings": {
      "language": "en",
      "clipCount": 5,
      "minDurationSec": 20,
      "maxDurationSec": 45,
      "objective": "howto",
      "captionStyle": "bold-karaoke",
      "reframe": "face",
      "instructions": null,
      "vocabulary": null
    },
    "missingSettings": [],
    "splitScreen": null,
    "streamer": null,
    "redditStory": null,
    "fakeText": null,
    "vibeEdit": null,
    "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

A video that does not exist

POST /v1/projects

Request body
{
  "sourceAssetId": "ast_0b1e5c9d3a7f40628e2d"
}
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_14c0d8b7f8af5ac83e1b0c01"
  }
}

Errors

CodeStatusWhenWhat to do
NOT_FOUND404A video that does not existChange the request, then send it again.
CONFLICT409The asset is not a video, or the file of the video was deleted to free up storage. 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 analysis is charged when you call analyze_project (POST /v1/projects/{projectId}/analyze).

Questions

Can I change the video of a project after creating it?

No. A project analyzes the video it was created with. To analyze another video, create another project with that video as sourceAssetId.

Do I have to choose every setting when I create the project?

No. Send the settings you know now and set the rest with update_project (PATCH /v1/projects/{projectId}). analyze_project (POST /v1/projects/{projectId}/analyze) refuses until missingSettings is empty.

What happens if I retry a create that timed out?

Send it again with the same Idempotency-Key. If the first try succeeded, you get its answer back and no second project is created. Without a key, a retry creates another project.

View as Markdown