Reject a clip
reject_clipPOST/v1/clips/{clipId}/rejectBeta
Sets a proposed clip aside, so it no longer counts among the clips waiting for a decision.
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
Use it to separate the clips you do not want from the ones still to review. A rejected clip stays in the project with status rejected, and restore_clip (POST /v1/clips/{clipId}/restore) brings it back. Rejecting a clip that is already rejected changes nothing and answers the clip. An accepted clip cannot be rejected, because it has a composition: the answer is CONFLICT. Analyzing the project again removes the rejected clips. Works on clips of Auto Clip projects only.
Example use
A review tool has a button for clips the editor does not want. The button calls this, so the clip leaves the list of clips to review but stays in the project if the editor changes their mind.
Endpoint
POST https://api.gpt-video.com/v1/clips/{clipId}/reject- Scope
clips:write. - Rate limit 60 requests a minute for each key and 120 for each account, shared by every
writecall. See rate limits. Idempotency-Keyis optional.
Parameters
Path
| Name | Type | Required | Description |
|---|---|---|---|
clipId | string | Required | The id of the clip, as list_clips (GET /v1/projects/{projectId}/clips) returns it. Matches ^cnd_[0-9a-f]{20}$. |
Headers
| Name | Type | Required | Description |
|---|---|---|---|
Idempotency-Key | string | Optional | Send the same key on every retry of this request. From 1 to 255 visible characters, such as a UUID. See idempotency. |
Request
Reject a proposed clip.
curl -X POST "https://api.gpt-video.com/v1/clips/cnd_2b7f4e91a0c84d35e6f0/reject" \
-H "Authorization: Bearer $GPT_VIDEO_API_KEY"const res = await fetch("https://api.gpt-video.com/v1/clips/cnd_2b7f4e91a0c84d35e6f0/reject", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.GPT_VIDEO_API_KEY}`,
},
});
const data = await res.json();
console.log(data);import os
import requests
r = requests.post(
"https://api.gpt-video.com/v1/clips/cnd_2b7f4e91a0c84d35e6f0/reject",
headers={
"Authorization": f"Bearer {os.environ['GPT_VIDEO_API_KEY']}",
},
)
data = r.json()
print(data){
"method": "tools/call",
"params": {
"name": "reject_clip",
"arguments": {
"clipId": "cnd_2b7f4e91a0c84d35e6f0"
}
}
}Response
A successful call answers HTTP 200. Returns a Clip object in clip.
Fields to check
| Name | Type | Description |
|---|---|---|
clip.id | string | The clip id. It starts with cnd_. |
clip.status | string | proposed is waiting for a decision, accepted has a composition, rejected was set aside and can be restored. |
Response example
{
"clip": {
"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": "rejected",
"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
}
}All response fields
| Name | Type | Required | Description |
|---|---|---|---|
clip | Clip object | Required | Described in Clip object. |
More examples
Reject a clip that was accepted
POST /v1/clips/cnd_9e04a6c3d12b4f78a5b9/reject
{
"error": {
"code": "CONFLICT",
"message": "This clip was accepted and has a composition (cmp_4e8c2a6f09d14b73a1e5), so it cannot be rejected.",
"requestId": "req_9d1e6b3a0f7c42d5a8e4b0c1"
}
}Errors
| Code | Status | When | What to do |
|---|---|---|---|
NOT_FOUND | 404 | See the error reference. | Change the request, then send it again. |
CONFLICT | 409 | Reject a clip that was accepted | 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.
Related operations
restore_clip(POST /v1/clips/{clipId}/restore) Restore a rejected clipaccept_clip(POST /v1/clips/{clipId}/accept) Accept a cliplist_clips(GET /v1/projects/{projectId}/clips) List the clips of a projectget_clip(GET /v1/clips/{clipId}) Get a clip
Questions
Can I reject a clip I already accepted?
No. An accepted clip has a composition, and rejecting it answers CONFLICT. Keep it, or delete its composition in the GPT-Video app.
Is a rejected clip deleted?
No. It stays in the project with status rejected until the project is analyzed again, and restore_clip (POST /v1/clips/{clipId}/restore) brings it back.