---
name: "gpt-video"
description: "Cut a long video into short vertical clips with the GPT-Video REST API. Upload the video, analyze it, accept the clips you want, export them as MP4 files and download them. Use it when the user asks to make clips with GPT-Video."
---

# GPT-Video API

Base URL: https://api.gpt-video.com/v1
Send the API key as Authorization: Bearer <API key>. Read it from the environment variable GPT_VIDEO_API_KEY.
Do not assume endpoints have parameters other than the ones explicitly specified.
The full manual is at https://www.gpt-video.com/developers/api.md. Read it before you call an operation this file does not name.

## Steps

1. [`create_upload`](https://www.gpt-video.com/developers/api/create-upload.md) (`POST /v1/uploads`). Open an upload for the video file with `filename`, `sizeBytes` and `contentType`. The answer says how many parts to send.
2. [`upload_part`](https://www.gpt-video.com/developers/api/upload-part.md) (`PUT /v1/uploads/{uploadId}/parts/{partNumber}`). Send each part as raw bytes.
3. [`complete_upload`](https://www.gpt-video.com/developers/api/complete-upload.md) (`POST /v1/uploads/{uploadId}/complete`). Turn the upload into an asset. Keep `asset.id`.
4. [`create_project`](https://www.gpt-video.com/developers/api/create-project.md) (`POST /v1/projects`). Create a project with that id as `sourceAssetId`. Keep `project.id`.
5. [`update_project`](https://www.gpt-video.com/developers/api/update-project.md) (`PATCH /v1/projects/{projectId}`). Choose the settings that `project.missingSettings` lists, with the values that `get_setting_options` (`GET /v1/reference/setting-options`) returns.
6. [`estimate_analysis`](https://www.gpt-video.com/developers/api/estimate-analysis.md) (`POST /v1/projects/{projectId}/analyze/estimate`). Check what the analysis will cost.
7. [`analyze_project`](https://www.gpt-video.com/developers/api/analyze-project.md) (`POST /v1/projects/{projectId}/analyze`). Start the analysis with an `Idempotency-Key`. Keep `job.id`.
8. [`get_job`](https://www.gpt-video.com/developers/api/get-job.md) (`GET /v1/jobs/{jobId}`). Read the job with `?wait=25` until `job.status` is final.
9. [`list_clips`](https://www.gpt-video.com/developers/api/list-clips.md) (`GET /v1/projects/{projectId}/clips`). List the clips the analysis proposes.
10. [`accept_clip`](https://www.gpt-video.com/developers/api/accept-clip.md) (`POST /v1/clips/{clipId}/accept`). Accept a clip. Keep `composition.id`.
11. [`create_export`](https://www.gpt-video.com/developers/api/create-export.md) (`POST /v1/compositions/{compositionId}/exports`). Export the composition with an `Idempotency-Key`. Keep `export.id`.
12. [`get_export`](https://www.gpt-video.com/developers/api/get-export.md) (`GET /v1/exports/{exportId}`). Read the export with `?wait=25` until it is done, then download `export.downloadUrl`.

Before an operation that spends credits, call its estimate when it has one and tell the user the price.

## Send the same request again on

- `NOT_READY` (409). Wait the number of seconds in the Retry-After header, then send the same request again.
- `IDEMPOTENCY_IN_PROGRESS` (409). Wait the number of seconds in the Retry-After header, then send the same request again to get its result.
- `RATE_LIMITED` (429). Wait the number of seconds in the Retry-After header, then send the request again.
- `INTERNAL` (500). Retry the same request, with the same Idempotency-Key if it has one. If it keeps failing, contact support and quote the requestId.
- `UPSTREAM_FAILED` (502). Retry in a few minutes.
- `UNAVAILABLE` (503). Retry later.

When the answer has a `Retry-After` header, wait that many seconds first. Send the same `Idempotency-Key` again. Try `INTERNAL`, `UPSTREAM_FAILED` and `UNAVAILABLE` at most three times. A 503 with `details.reason: "switched_off"` means the operation is turned off, so do not send it again.

## Change the request on

- `VALIDATION_FAILED` (400). Fix the fields listed in details.issues, then send the request again. Fix the request as the message says, then send it again.
- `UNKNOWN_PARAMETER` (400). Send only the fields listed in details.allowed.
- `IDEMPOTENCY_KEY_REQUIRED` (400). Add an Idempotency-Key header: a random string such as a UUID, the same one on every retry of this request.
- `NOT_FOUND` (404). Check the id. An id that belongs to another account is not found either.
- `METHOD_NOT_ALLOWED` (405). Use one of the methods listed in the Allow header.
- `PAYLOAD_TOO_LARGE` (413). Send a JSON body of at most 1 MB.
- `IDEMPOTENCY_KEY_REUSED` (422). Use a new Idempotency-Key for a different request.
- `SOURCE_MISSING` (422). A project's video cannot be changed through the API. Upload the video, then create a new project with its asset id as sourceAssetId.
- `UNSUPPORTED_SOURCE_URL` (422). Send a direct link to a video file. A link to a web page is refused.

## Stop and tell the user on

- `UNAUTHORIZED` (401). Send an API key in the Authorization header as Bearer gvk_... You create keys in the GPT-Video app.
- `INSUFFICIENT_CREDITS` (402). Buy credits or change plan at https://www.gpt-video.com/app/billing.
- `PLAN_REQUIRED` (402). The API bonus pays first. When it cannot, choose a Creator or Studio plan at https://www.gpt-video.com/app/billing.
- `SCOPE_MISSING` (403). Create a key with the scope named in the message, or use a key that has it.
- `DAILY_LIMIT_REACHED` (429). The limit resets at 00:00 UTC. A higher plan raises it: https://www.gpt-video.com/app/billing.

## Read again, then decide on

- `CONFLICT` (409). Read the resource again, then decide. Do not send the same request again.

## Idempotency

Create one `Idempotency-Key` for each request that spends credits, before you send it. If the request fails or times out, send it again with the same key. A new key is a new charge. Make the key random, such as a UUID, and never a name like upload-1: a key the API has seen before, even in an earlier task, gets that earlier answer back.

## Wait and download

1. `GET /v1/jobs/{jobId}?wait=25` until `job.status` is `done`, `failed` or `cancelled`.
2. If the answer comes back at once while the job is still running, wait 5 seconds before you read it again.
3. At most 10 requests with `wait` can be open at once for each account.
4. Follow an export the same way with `GET /v1/exports/{exportId}?wait=25`.
5. Download `export.downloadUrl` without the `Authorization` header. The link points to the GPT-Video website, so do not send your key to it. It works for 15 minutes.
6. For a new link, read the export again with [`get_export`](https://www.gpt-video.com/developers/api/get-export.md) (`GET /v1/exports/{exportId}`). Save the file as soon as you download it.

## Using the API bonus

API bonus: 50 credits. No card needed.

- [`get_credits`](https://www.gpt-video.com/developers/api/get-credits.md) (`GET /v1/credits`) tells you in `bonus.status` whether the account has the bonus now.
- API bonus credits can be spent only through the API. They expire 30 days after you get them.
- While the bonus pays, an account can make 5 exports a day, each up to 600 seconds long. A longer export answers `PLAN_REQUIRED`.
- The bonus runs 1 job at a time. The next one waits with status `queued`.
- A daily limit answers `DAILY_LIMIT_REACHED`. Do not send the request again until 00:00 UTC.
- After the API bonus, the API needs a Creator or Studio plan.
