List the clips of a project
list_clipsGET/v1/projects/{projectId}/clipsBeta
Returns the clips an analysis found in a project, in the order the analysis ranked them.
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 this when the analysis of a project is done, to see the clips it found: where each one sits in the source video, its title and hook, and a score explained factor by factor. Filter by status to see only the clips still waiting for a decision. Analyzing the project again replaces the proposed and rejected clips with new ones, with new ids, and keeps the accepted ones; a cursor issued before that answers CONFLICT, and you start again without it. Accept a clip with accept_clip (POST /v1/clips/{clipId}/accept) to get a composition you can export. Works on Auto Clip projects only.
Example use
After the analysis of a podcast episode finishes, a review tool lists the clips that still wait for a decision and shows their titles, hooks and scores to an editor, who picks the ones to publish.
Endpoint
GET https://api.gpt-video.com/v1/projects/{projectId}/clips- Scope
clips:read. - Rate limit 120 requests a minute for each key and 240 for each account, shared by every
readcall. See rate limits. - No
Idempotency-Key.
Parameters
Path
| Name | Type | Required | Description |
|---|---|---|---|
projectId | string | Required | The id of the project, as create_project (POST /v1/projects) returns it. Matches ^prj_[0-9a-f]{20}$. |
Query
| Name | Type | Required | Description |
|---|---|---|---|
status | string | Optional | Only the clips with this status. Leave it out to get every clip. One of proposed, accepted, rejected. |
limit | integer | Optional | How many items to return, from 1 to 100. Defaults to 20. From 1 to 100. Default 20. |
cursor | string | Optional | The nextCursor value from the previous page. Leave it out to get the first page. From 1 to 512 characters. |
Request
List the clips of a project.
curl "https://api.gpt-video.com/v1/projects/prj_7c2e9a4f1b3d4e8096a5/clips" \
-H "Authorization: Bearer $GPT_VIDEO_API_KEY"const res = await fetch("https://api.gpt-video.com/v1/projects/prj_7c2e9a4f1b3d4e8096a5/clips", {
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.GPT_VIDEO_API_KEY}`,
},
});
const data = await res.json();
console.log(data);import os
import requests
r = requests.get(
"https://api.gpt-video.com/v1/projects/prj_7c2e9a4f1b3d4e8096a5/clips",
headers={
"Authorization": f"Bearer {os.environ['GPT_VIDEO_API_KEY']}",
},
)
data = r.json()
print(data)Response
A successful call answers HTTP 200.
Fields to check
| Name | Type | Description |
|---|---|---|
data[].id | string | The clip id. It starts with cnd_. |
data[].status | string | proposed is waiting for a decision, accepted has a composition, rejected was set aside and can be restored. |
hasMore | boolean | true when there are more items after this page. |
nextCursor | string or null | Send it as cursor to get the next page. It is null on the last page. |
Response example
{
"data": [
{
"id": "cnd_9e04a6c3d12b4f78a5b9",
"projectId": "prj_7c2e9a4f1b3d4e8096a5",
"sourceAssetId": "ast_3f9a1c7e5b2d4086a1c4",
"summary": "The founder explains how the first customer paid before the product existed.",
"reason": "A clear claim in the first seconds and a result at the end.",
"tags": [
"startups",
"sales"
],
"createdAt": "2026-09-01T09:40:00.000Z",
"status": "accepted",
"rank": 0,
"startSec": 120,
"endSec": 150,
"durationSec": 30,
"title": "Paid before the product",
"hook": "They paid us before we had a product",
"score": 87.5,
"scoreBreakdown": [
{
"factor": "hook",
"label": "Hook (first 3 seconds)",
"score": 9,
"note": "Opens on a concrete claim."
},
{
"factor": "payoff",
"label": "Payoff / ending",
"score": 8,
"note": "Ends on the result."
},
{
"factor": "clarity",
"label": "Clarity",
"score": 7,
"note": "One idea, said plainly."
},
{
"factor": "emotion",
"label": "Emotion",
"score": 9,
"note": "The speaker sounds surprised."
},
{
"factor": "novelty",
"label": "Novelty / surprise",
"score": 8,
"note": "Not the usual advice."
},
{
"factor": "selfContained",
"label": "Self-contained",
"score": 7,
"note": "Needs no context."
},
{
"factor": "quotability",
"label": "Quotability",
"score": 9,
"note": "Has a line people repeat."
},
{
"factor": "dialogue",
"label": "Dialogue (back-and-forth)",
"score": 8,
"note": "A single speaker."
}
],
"transcriptExcerpt": "before we had a product and that changed everything for our team the first customer paid us before we had a product and that changed everything for our team the first customer paid us before we had a product and that changed everything for our team the first customer paid us before we had a product and that changed everything for our team the first customer paid us before we had a product and that",
"social": {
"title": "Paid before the product",
"caption": "How a first customer paid before there was a product.",
"hashtags": [
"#startup",
"#founder"
]
},
"compositionId": "cmp_4e8c2a6f09d14b73a1e5"
},
{
"id": "cnd_2b7f4e91a0c84d35e6f0",
"projectId": "prj_7c2e9a4f1b3d4e8096a5",
"sourceAssetId": "ast_3f9a1c7e5b2d4086a1c4",
"summary": "The founder explains how the first customer paid before the product existed.",
"reason": "A clear claim in the first seconds and a result at the end.",
"tags": [
"startups",
"sales"
],
"createdAt": "2026-09-01T09:40:00.000Z",
"status": "proposed",
"rank": 1,
"startSec": 300,
"endSec": 330,
"durationSec": 30,
"title": "The first customer",
"hook": "Our first customer changed everything",
"score": 81,
"scoreBreakdown": [
{
"factor": "hook",
"label": "Hook (first 3 seconds)",
"score": 8,
"note": "Opens on a concrete claim."
},
{
"factor": "payoff",
"label": "Payoff / ending",
"score": 7,
"note": "Ends on the result."
},
{
"factor": "clarity",
"label": "Clarity",
"score": 6,
"note": "One idea, said plainly."
},
{
"factor": "emotion",
"label": "Emotion",
"score": 8,
"note": "The speaker sounds surprised."
},
{
"factor": "novelty",
"label": "Novelty / surprise",
"score": 7,
"note": "Not the usual advice."
},
{
"factor": "selfContained",
"label": "Self-contained",
"score": 6,
"note": "Needs no context."
},
{
"factor": "quotability",
"label": "Quotability",
"score": 8,
"note": "Has a line people repeat."
},
{
"factor": "dialogue",
"label": "Dialogue (back-and-forth)",
"score": 7,
"note": "A single speaker."
}
],
"transcriptExcerpt": "before we had a product and that changed everything for our team the first customer paid us before we had a product and that changed everything for our team the first customer paid us before we had a product and that changed everything for our team the first customer paid us before we had a product and that changed everything for our team the first customer paid us before we had a product and that",
"social": {
"title": "The first customer",
"caption": "How a first customer paid before there was a product.",
"hashtags": [
"#startup",
"#founder"
]
},
"compositionId": null
},
{
"id": "cnd_6a3d1f8e0b574c29d4e3",
"projectId": "prj_7c2e9a4f1b3d4e8096a5",
"sourceAssetId": "ast_3f9a1c7e5b2d4086a1c4",
"summary": "The founder explains how the first customer paid before the product existed.",
"reason": "A clear claim in the first seconds and a result at the end.",
"tags": [
"startups",
"sales"
],
"createdAt": "2026-09-01T09:40:00.000Z",
"status": "rejected",
"rank": 2,
"startSec": 600,
"endSec": 640,
"durationSec": 40,
"title": "Team habits",
"hook": "What our team does every morning",
"score": 64,
"scoreBreakdown": [
{
"factor": "hook",
"label": "Hook (first 3 seconds)",
"score": 6,
"note": "Opens on a concrete claim."
},
{
"factor": "payoff",
"label": "Payoff / ending",
"score": 5,
"note": "Ends on the result."
},
{
"factor": "clarity",
"label": "Clarity",
"score": 4,
"note": "One idea, said plainly."
},
{
"factor": "emotion",
"label": "Emotion",
"score": 6,
"note": "The speaker sounds surprised."
},
{
"factor": "novelty",
"label": "Novelty / surprise",
"score": 5,
"note": "Not the usual advice."
},
{
"factor": "selfContained",
"label": "Self-contained",
"score": 4,
"note": "Needs no context."
},
{
"factor": "quotability",
"label": "Quotability",
"score": 6,
"note": "Has a line people repeat."
},
{
"factor": "dialogue",
"label": "Dialogue (back-and-forth)",
"score": 5,
"note": "A single speaker."
}
],
"transcriptExcerpt": "before we had a product and that changed everything for our team the first customer paid us before we had a product and that changed everything for our team the first customer paid us before we had a product and that changed everything for our team the first customer paid us before we had a product and that changed everything for our team the first customer paid us before we had a product and that changed everything for our team the first customer paid us before we had a product and that changed everything for our team the first customer",
"social": {
"title": "Team habits",
"caption": "How a first customer paid before there was a product.",
"hashtags": [
"#startup",
"#founder"
]
},
"compositionId": null
}
],
"hasMore": false,
"nextCursor": null
}All response fields
| Name | Type | Required | Description |
|---|---|---|---|
data | array of objects | Required | The items of this page. |
data[] | Clip object | Optional | Described in Clip object. |
hasMore | boolean | Required | true when there are more items after this page. |
nextCursor | string or null | Required | Send it as cursor to get the next page. It is null on the last page. |
More examples
Only the clips waiting for a decision
GET /v1/projects/prj_7c2e9a4f1b3d4e8096a5/clips?status=proposed
{
"data": [
{
"id": "cnd_2b7f4e91a0c84d35e6f0",
"projectId": "prj_7c2e9a4f1b3d4e8096a5",
"sourceAssetId": "ast_3f9a1c7e5b2d4086a1c4",
"summary": "The founder explains how the first customer paid before the product existed.",
"reason": "A clear claim in the first seconds and a result at the end.",
"tags": [
"startups",
"sales"
],
"createdAt": "2026-09-01T09:40:00.000Z",
"status": "proposed",
"rank": 1,
"startSec": 300,
"endSec": 330,
"durationSec": 30,
"title": "The first customer",
"hook": "Our first customer changed everything",
"score": 81,
"scoreBreakdown": [
{
"factor": "hook",
"label": "Hook (first 3 seconds)",
"score": 8,
"note": "Opens on a concrete claim."
},
{
"factor": "payoff",
"label": "Payoff / ending",
"score": 7,
"note": "Ends on the result."
},
{
"factor": "clarity",
"label": "Clarity",
"score": 6,
"note": "One idea, said plainly."
},
{
"factor": "emotion",
"label": "Emotion",
"score": 8,
"note": "The speaker sounds surprised."
},
{
"factor": "novelty",
"label": "Novelty / surprise",
"score": 7,
"note": "Not the usual advice."
},
{
"factor": "selfContained",
"label": "Self-contained",
"score": 6,
"note": "Needs no context."
},
{
"factor": "quotability",
"label": "Quotability",
"score": 8,
"note": "Has a line people repeat."
},
{
"factor": "dialogue",
"label": "Dialogue (back-and-forth)",
"score": 7,
"note": "A single speaker."
}
],
"transcriptExcerpt": "before we had a product and that changed everything for our team the first customer paid us before we had a product and that changed everything for our team the first customer paid us before we had a product and that changed everything for our team the first customer paid us before we had a product and that changed everything for our team the first customer paid us before we had a product and that",
"social": {
"title": "The first customer",
"caption": "How a first customer paid before there was a product.",
"hashtags": [
"#startup",
"#founder"
]
},
"compositionId": null
}
],
"hasMore": false,
"nextCursor": null
}A cursor from before the project was analyzed again
GET /v1/projects/prj_7c2e9a4f1b3d4e8096a5/clips?cursor=eyJrIjp7ImlkIjoiY25kXzRjOGUwYTJmNmQxYjQ5ZTdhM2M1IiwibGlzdCI6IjF4OGtxMnYwbTdkMyIsInJhbmsiOjF9LCJ2IjoxfQ
{
"error": {
"code": "CONFLICT",
"message": "The clips of this project changed after this cursor was issued, because the project was analyzed again. Start again without a cursor.",
"requestId": "req_5a0c2e7d9b3f41a68c1e2d04"
}
}A project that is not an Auto Clip project
GET /v1/projects/prj_7c2e9a4f1b3d4e8096a5/clips
{
"error": {
"code": "CONFLICT",
"message": "This project is not an Auto Clip project. This operation works on Auto Clip projects only. Use the operations of its kind.",
"requestId": "req_7e3b1d9a0c5f42e8b6a1d3c7"
}
}Errors
| Code | Status | When | What to do |
|---|---|---|---|
NOT_FOUND | 404 | See the error reference. | Change the request, then send it again. |
CONFLICT | 409 | A cursor from before the project was analyzed again | 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, RATE_LIMITED, INTERNAL, UNAVAILABLE.
Cost
No credits are used.
Related operations
get_clip(GET /v1/clips/{clipId}) Get a clipaccept_clip(POST /v1/clips/{clipId}/accept) Accept a clipreject_clip(POST /v1/clips/{clipId}/reject) Reject a clipanalyze_project(POST /v1/projects/{projectId}/analyze) Analyze a projectget_project(GET /v1/projects/{projectId}) Get a projectrestore_clip(POST /v1/clips/{clipId}/restore) Restore a rejected clip
Questions
Why did the ids of my clips change?
The project was analyzed again. A new analysis replaces the proposed and rejected clips with new ones, with new ids, and keeps the accepted clips with their ids and compositions.
What does the score mean?
It ranks the clips of one project against each other, from 0 to 100, and scoreBreakdown explains it factor by factor. It is not a probability that a clip goes viral.
In what order do the clips come?
By rank, the order the analysis ranked them in. A new analysis ranks the accepted clips it keeps first, then the new ones. The order does not change between pages, and accepting, rejecting or restoring a clip between two pages keeps the cursor valid.