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 split screen project

create_split_screen_projectPOST/v1/projects/split-screenBeta

Creates a split screen project from two videos you uploaded: the main video on top and a background video under it.

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 ids of two videos. The two videos and the language are chosen here and only here: to use other videos, create another project. The layout, the captions and the start of the background can be changed later with update_split_screen_project (PATCH /v1/projects/{projectId}/split-screen). Nothing is built and no credits are used until you call build_split_screen_video (POST /v1/projects/{projectId}/split-screen/build). Send an Idempotency-Key: a retry without one creates a second project.

Example use

A channel that posts interview moments uploads an interview clip and a gameplay video, then creates a project with the interview on top and the gameplay under it. It checks the price with estimate_analysis (POST /v1/projects/{projectId}/analyze/estimate) before it builds.

Endpoint

Code
POST https://api.gpt-video.com/v1/projects/split-screen
  • 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
mainAssetIdstringRequiredThe main video, shown on top and transcribed for the captions: the asset id that complete_upload (POST /v1/uploads/{uploadId}/complete) returned. It cannot be changed later. Matches ^ast_n?[0-9a-f]{20}$.
backgroundAssetIdstringRequiredThe background video, shown under the main video, such as gameplay footage. It cannot be changed later. Matches ^ast_n?[0-9a-f]{20}$.
layoutstringRequiredHow the screen is split: 50-50 gives each video half the screen, 60-40 gives the main video more. One of 50-50, 60-40.
captionStylestring or nullRequiredThe caption style, or null for a video with no captions. get_setting_options (GET /v1/reference/setting-options) lists every style with what it looks like. One of bold-karaoke, word-pop, boxed, outline.
languagestringRequiredThe language spoken in the main video: en, it, or auto to detect it. It cannot be changed later. One of auto, it, en.
backgroundStartSecnumberOptionalWhere the background video starts, in seconds, before the end of the background video. Leave it out to let the first build choose a random start, which is then kept. At least 0.
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 split screen 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/split-screen" \
  -H "Authorization: Bearer $GPT_VIDEO_API_KEY" \
  -H "Idempotency-Key: $IDEMPOTENCY_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "mainAssetId": "ast_8e21b0d94c6f4a17b358",
    "backgroundAssetId": "ast_8ac5d8b97546145cdbf6",
    "layout": "60-40",
    "captionStyle": "bold-karaoke",
    "language": "en",
    "title": "Product demo over the city"
  }'
// 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/split-screen", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${process.env.GPT_VIDEO_API_KEY}`,
    "Idempotency-Key": idempotencyKey,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "mainAssetId": "ast_8e21b0d94c6f4a17b358",
    "backgroundAssetId": "ast_8ac5d8b97546145cdbf6",
    "layout": "60-40",
    "captionStyle": "bold-karaoke",
    "language": "en",
    "title": "Product demo over the city"
  }),
});
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/split-screen",
    headers={
        "Authorization": f"Bearer {os.environ['GPT_VIDEO_API_KEY']}",
        "Idempotency-Key": idempotency_key,
    },
    json={
        "mainAssetId": "ast_8e21b0d94c6f4a17b358",
        "backgroundAssetId": "ast_8ac5d8b97546145cdbf6",
        "layout": "60-40",
        "captionStyle": "bold-karaoke",
        "language": "en",
        "title": "Product demo over the city"
    },
)
data = r.json()
print(data)
{
  "method": "tools/call",
  "params": {
    "name": "create_split_screen_project",
    "arguments": {
      "mainAssetId": "ast_8e21b0d94c6f4a17b358",
      "backgroundAssetId": "ast_8ac5d8b97546145cdbf6",
      "layout": "60-40",
      "captionStyle": "bold-karaoke",
      "language": "en",
      "title": "Product demo over the city"
    }
  }
}

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_5b8e2d71c4a94f06b3e9",
    "kind": "splitscreen",
    "title": "Product demo over the city",
    "status": "draft",
    "sourceAssetId": "ast_8e21b0d94c6f4a17b358",
    "compositionId": null,
    "settings": null,
    "missingSettings": [],
    "errorMessage": null,
    "splitScreen": {
      "mainAssetId": "ast_8e21b0d94c6f4a17b358",
      "backgroundAssetId": "ast_8ac5d8b97546145cdbf6",
      "layout": "60-40",
      "captionStyle": "bold-karaoke",
      "language": "en",
      "backgroundStartSec": null,
      "vocabulary": null
    },
    "streamer": null,
    "redditStory": null,
    "fakeText": null,
    "vibeEdit": 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 background video that does not exist

POST /v1/projects/split-screen

Request body
{
  "mainAssetId": "ast_8e21b0d94c6f4a17b358",
  "backgroundAssetId": "ast_0b1e5c9d3a7f40628e2d",
  "layout": "50-50",
  "captionStyle": null,
  "language": "en"
}
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_6d2a9f1c4e7b03a85d1f2c96"
  }
}

A background that is not a video

POST /v1/projects/split-screen

Request body
{
  "mainAssetId": "ast_8e21b0d94c6f4a17b358",
  "backgroundAssetId": "ast_e8a35ed674148f27b585",
  "layout": "50-50",
  "captionStyle": null,
  "language": "en"
}
HTTP 409
{
  "error": {
    "code": "CONFLICT",
    "message": "This asset is not a video. A split screen needs two videos: the main video and the background video.",
    "requestId": "req_1f8c3e6a0d2b49f75a3e8c01"
  }
}

A background start past the end of the background

POST /v1/projects/split-screen

Request body
{
  "mainAssetId": "ast_8e21b0d94c6f4a17b358",
  "backgroundAssetId": "ast_8ac5d8b97546145cdbf6",
  "layout": "50-50",
  "captionStyle": "word-pop",
  "language": "en",
  "backgroundStartSec": 90
}
HTTP 400
{
  "error": {
    "code": "VALIDATION_FAILED",
    "message": "backgroundStartSec (90) is past the end of the background video (60 seconds). Use a smaller value.",
    "hint": "Fix the request as the message says, then send it again.",
    "requestId": "req_9b4e1a7d3c0f5e28b6a1d4c7"
  }
}

Errors

CodeStatusWhenWhat to do
NOT_FOUND404A background video that does not existChange the request, then send it again.
CONFLICT409A background that is not a videoRead 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 build is charged when you call build_split_screen_video (POST /v1/projects/{projectId}/split-screen/build).

Questions

Can I change the videos or the language after creating the project?

No. The two videos and the language are chosen when the project is created, because the price and the captions depend on them. To use other videos, create another project.

What does a split screen build cost?

One credit per started minute of the main video and of the background video together. estimate_analysis (POST /v1/projects/{projectId}/analyze/estimate) tells you the price before you build.

View as Markdown