# Video Clips

Read a job that cut a long video into short clips, approve the ones you want, and fine-tune each clip.

Video Clips takes one long video (a talk, a podcast, a live) and proposes the moments that work on their own as short vertical clips. Each approved clip becomes a post of format `video_clip`, with its own hook, captions and caption text, that you schedule and publish like any other post.

> The job itself is started from the app or in a conversation with the assistant, where the video is sent. The API reads a job and approves it: `GET /clip-jobs/{id}` and `POST /clip-jobs/{id}/approve`. These are a job's proposed clips, not the reel's library clips of `GET /posts/{id}/clips`. Video Clips is enabled per workspace; a workspace without it answers `403` with `forbidden`, and nothing is charged.

## Two phases, and where the credits go

- Analysis: the job reads the video and proposes the moments. It takes a few minutes and costs no credits. A video that cannot be used (too short, too long, no speech, not enough good moments) ends the job as `failed` with `refusal`, before anything is charged.
- Approval: you choose which proposals become clips. Each one costs 1 credit, charged all at once when you approve, so approving 3 clips uses 3 credits. Without enough credits for all of them, nothing is charged and the job stays `ready`.

| Limit | Value |
| --- | --- |
| The long video | from 2 to 60 minutes, up to 2 GB |
| Each clip | from 20 to 60 seconds |
| Clips approved per job | from 1 to 8 |
| Hook | up to 60 visible characters, no links and no @handles |
| Trimming a clip | up to 5 seconds either way at each end, from the proposed moment |
| Keeping the long video | the original video is kept for 7 days after the job is `done` or `ready`, 1 day after it is `failed`, and then deleted. The approved clips are never deleted. |

## Read a job and approve two clips

Poll the job until it is `ready`, then approve by `index`.

### 1. Read the job. While `status` is `analyzing`, poll again in a minute.

```bash
curl -H "Authorization: Bearer $POSTTAR_KEY" "https://api.posttar.com/v1/clip-jobs/5f0c7a2e-..."
```

```json
{
  "id": "5f0c7a2e-...",
  "status": "ready",
  "durationSec": 1520.4,
  "refusal": null,
  "proposals": [
    { "index": 0, "start": 95.2, "end": 138.6, "hook": "Why most freelancers **undercharge**", "title": "Pricing", "approved": false },
    { "index": 2, "start": 811.5, "end": 858.3, "hook": "The **one** question I ask every client", "title": "Discovery call", "approved": false }
  ],
  "clips": []
}
```

### 2. Approve two proposals, changing the hook of one. This charges 2 credits.

```bash
curl -X POST -H "Authorization: Bearer $POSTTAR_KEY" -H "Content-Type: application/json" \
  -d '{"clips":[0,2],"hooks":{"2":"The one question I ask before any quote"}}' \
  "https://api.posttar.com/v1/clip-jobs/5f0c7a2e-.../approve"
```

```json
{
  "jobId": "5f0c7a2e-...",
  "postIds": ["0e4d9b1a-...", "7a3b5c9d-..."],
  "credits": 2
}
```

### 3. Read the job again until every clip has `renderState` `done`. Each clip is also a post you read with `GET /posts/{id}`.

```bash
curl -H "Authorization: Bearer $POSTTAR_KEY" "https://api.posttar.com/v1/clip-jobs/5f0c7a2e-..."
```

> A job can be approved again later, for the proposals not approved yet, while its original video is kept (`sourceAvailable` in the job). A proposal that was already approved is never charged twice: it comes back in `alreadyApproved`, so retrying after a network error is safe and answers the same `postIds` with `credits` 0.

## Fine-tuning a clip

`GET /posts/{id}` on a clip returns `content.clip`: the `hook`, the stretch in use (`startSec`, `endSec`) and the proposed one (`proposalStartSec`, `proposalEndSec`). `PATCH /posts/{id}/video-clip` changes the hook and moves each end. It is free: the post is marked as having an outdated video, and the MP4 is rebuilt before it is downloaded, scheduled or published. The caption is edited with `PATCH /posts/{id}`, as in every format.

Start the clip 1.3 seconds earlier and change its hook.

```bash
curl -X PATCH -H "Authorization: Bearer $POSTTAR_KEY" -H "Content-Type: application/json" \
  -d '{"hook":"The **one** question I ask every client","startSec":810.2}' \
  "https://api.posttar.com/v1/posts/7a3b5c9d-.../video-clip"
```

> A clip that failed is made again with `POST /posts/{id}/regenerate`, the same call as every other format, and a failed clip is made again without spending a credit.
