---
name: hooks-video
description: Make 6 new AI-spoken opening hooks for a UGC video with hooks.video. Same person, same voice, same shot; each hook cuts into the real footage. Use when the user asks to test hooks, remake an ad opening, or "make hooks for this video".
---

# hooks.video

Base URL: `https://hooks.video`.
Auth: `Authorization: Bearer hk_...`. The user creates the key at `/account` and gives it to you. Never print it back.

## Make a pack

```bash
curl -X POST $BASE/v1/packs \
  -H "Authorization: Bearer $HOOKS_KEY" -H "Content-Type: application/json" \
  -H "Idempotency-Key: <any unique string per pack>" \
  -d '{
    "video_url": "https://.../video.mp4",
    "hooks": ["Optional line 1", "Optional line 2"],
    "write_the_rest": true,
    "person": "new",
    "webhook": "https://optional.example/hook-done"
  }'
```

- `video_url`: a direct https link to an MP4 or MOV file (not a TikTok or Drive page), up to 50 MB, 4 s to 3 min, with the person talking.
- `hooks`: up to 6 lines, under 90 characters each (about 4 seconds spoken). Leave out to let us write all 6.
- `write_the_rest`: fill up to 6 with our own lines. Default true.
- `person`: `"new"` the first time someone is on camera; later use their saved id like `"person_emma"` (see `GET /v1/people`).
- Send the same `Idempotency-Key` when retrying so you never pay twice.

The response is `202` with a `pack_id` and what the user has to do:

- `checkout_url`: the user's first pack ($10, normally $48) needs them to pay once in Stripe. Send them the link.
- After the first pack, each hook costs $8 ($48 for 6), paid from the account's prepaid credits. The pack's cost is held when it starts; hooks that can't be made are released back, so only delivered hooks are charged.
- `confirm_url`: the person on camera isn't confirmed yet. Send the user the link; one tap confirms they have permission. Until then, takes are watermarked previews.
- `next_step`: plain-English summary of the above.

## Check progress

`GET $BASE/v1/packs/{pack_id}`. Poll every 30 to 60 seconds, or wait for the webhook. A pack usually takes 10 to 15 minutes after payment.

`status`: `uploaded` → `analyzing` → `drafted` (waiting for payment) → `queued` → `processing` → `ready` (or `failed` with `error`).

Each entry in `takes` has `hook`, `status`, `word_match` (0 to 1, how exactly the line was spoken), `preview_url` (watermarked) and `url` (clean, only after permission is confirmed). URLs expire after an hour; fetch the pack again for fresh ones.

Webhook events (POST JSON `{event, pack_id, status}`): `permission.confirmed`, `pack.ready`, `pack.failed`. Treat them as a nudge and re-read the pack with your key.

## Other calls

- `GET /v1/me`: `balance_cents`, `hook_price_cents`, `next_pack_price_cents` and `buy_credits_url`.
- `POST /v1/packs/{pack_id}/pay`: pay for a saved pack after the user adds credits.
- `GET /v1/people`: saved people and whether each is confirmed.
- `GET /v1/packs`: the 20 most recent packs.

## Errors

JSON `{ "error": "..." }`. `401` bad key, `400` bad input (message says what), `402` not enough credits (`code: "insufficient_balance"`, with `balance_cents`, `needed_cents` and `buy_url`; send the user `buy_url`, the user buys credits, you don't), `429` too many packs this hour (limit 6).

## Rules

- Only use videos of the user, or of someone who agreed to AI versions of their face and voice. The user confirms this; don't confirm it for them.
- Don't run watermarked previews as ads.
