# Everpop — agent skill

Everpop turns prompts and YouTube uploads into published vertical shorts with
animated captions, then measures real performance ("receipts") via the
YouTube Analytics API. This file teaches an AI agent to use the public API.

Base URL: https://everpop.app
Auth: `Authorization: Bearer epk_...` (create a key at Dashboard → Settings → API keys)

## Generate a short from a prompt

POST /api/v1/generate
```json
{
  "prompt": "3 psychology tricks that make people instantly like you",
  "clipCount": 1,
  "voice": "nova",            // alloy | echo | fable | onyx | nova | shimmer
  "tone": "educational",      // educational | storytime | hype | calm
  "targetSeconds": 45,        // 20-60
  "captionStyle": "pop"       // pop | boxed | minimal
}
```
→ `{ "ok": true, "data": { "jobId": "...", "poll": "/api/v1/jobs/{id}" } }`

Generation takes ~1–3 minutes: script → TTS voiceover → visuals →
word-timed animated captions → 9:16 MP4.

## Poll a job

GET /api/v1/jobs/{jobId}
→ `{ "data": { "status": "PENDING|PROCESSING|COMPLETED|FAILED", "clips": [{ "clipUrl": ..., "thumbnailUrl": ..., "title": ..., "durationSeconds": ... }] } }`

Poll every 15–30s until status is COMPLETED or FAILED.


## List the user's videos (to pick what to clip)

```bash
curl -s https://everpop.app/api/v1/videos \
  -H "Authorization: Bearer $EVERPOP_API_KEY"
```

## Upload the video file (upload-first — the compliant ingestion path)

Everpop clips from the creator's FILE, never from a YouTube download
(compliance cutover, 2026-07-02). Agents can deliver the file end-to-end —
no dashboard detour:

```bash
# 1. Request a presigned upload slot (write-scope key)
curl -s -X POST https://everpop.app/api/v1/videos/upload   -H "Authorization: Bearer $EVERPOP_API_KEY"   -H "content-type: application/json"   -d '{"filename":"episode-42.mp4","sizeBytes":734003200}'
# → { putUrl, key, expiresInSeconds }

# 2. PUT the raw bytes straight to storage (valid 15 min, up to 4 GB)
curl -s -X PUT "$PUT_URL" -H "content-type: video/mp4" --data-binary @episode-42.mp4

# 3. Finalize — rightsConfirmed must be the USER's answer, never assumed
curl -s -X POST https://everpop.app/api/v1/videos/complete   -H "Authorization: Bearer $EVERPOP_API_KEY"   -H "content-type: application/json"   -d '{"key":"<key from step 1>","title":"Episode 42","rightsConfirmed":true}'
# → { videoId, autoClipping } — autoClipping true = a render is ALREADY running
```

Rules of the road:

- /clip on a video whose source is a YouTube URL returns **422 `upload_required`**
  — don't retry; upload the file (above), or pass the parked video's id as
  `linkSourceVideoId` in /videos/complete to ATTACH the file to it (un-parks it
  and keeps its YouTube attribution — the best option for detected uploads).
- Uploads **auto-clip on completion** for active subscribers, so after an upload
  check /videos and /jobs — clips may already be rendering.
- New uploads to a CONNECTED channel are still detected instantly; Everpop parks
  them and emails the creator — or ingests them AUTOMATICALLY if the creator
  connected a Drive "Finals folder" (Settings → Finals folder; zero-step).
- `POST /api/v1/videos/import` still registers a YouTube video's METADATA
  (own-channel only, idempotent) — pair it with linkSourceVideoId to upload
  its file in the same session.
- Files over 4 GB need the dashboard's resumable multipart uploader.

## Clip moments from one of their videos (ClipAnything)

```bash
curl -s -X POST https://everpop.app/api/v1/clip \
  -H "Authorization: Bearer $EVERPOP_API_KEY" \
  -H "content-type: application/json" \
  -d '{"sourceVideoId":"<id from /videos>","prompt":"the most surprising moment, ending on a cliffhanger","clipCount":2,"targetSeconds":45,"captionStyle":"pop"}'
```

- `clipCount` is 1–5 (default 1).
- `prompt` is optional — omit it and the AI picks the best moments itself.
- Returns `data.jobId`; poll the same as generate.

## Publish a clip to the connected channel

```bash
curl -s -X POST https://everpop.app/api/v1/publish \
  -H "Authorization: Bearer $EVERPOP_API_KEY" \
  -H "content-type: application/json" \
  -d '{"clipId":"<clipId from a COMPLETED /jobs/{id}>"}'
```

- `clipId` comes from a COMPLETED job's `clips[].clipId`.
- Publishes the clip as a YouTube Short on the user's connected channel.
- Idempotent per (clip, channel): a clip already published returns its existing post.
- **Only publish after the user explicitly confirms** — publishing is public and not easily undone.

## Pull receipts (real measured performance)

GET /api/v1/receipts
→ per published clip: 48h and 7d aggregate metrics (views, retention %,
likes, comments, shares, subscribers gained), a public tamper-evident
`receiptUrl`, and a `campaignReportUrl` bundling all measured clips —
suitable as payout proof for clip campaigns.

## Notes for agents

- Rate limits per account: 10 generate/min, 10 clip/min, 6 publish/min,
  60 videos/min. 402 means the account needs an active subscription.
  401 means bad/revoked key. 429 means slow down (a `Retry-After` may be set).
- 503 with "engine is offline" → the user's clipping engine is down: tell
  them to start it, then retry the same request (the failed attempt is
  recorded as a failed job).
- Clip URLs are publicly fetchable MP4s (Cloudflare R2) — download and
  publish them anywhere, or let Everpop auto-publish to the connected channel.
- Receipts only exist for clips published through Everpop to a connected
  YouTube channel; they are pulled from the YouTube Analytics API and cannot
  be edited by the user.

## Use it from Claude (MCP connector)

OAuth is supported: add `https://everpop.app/api/mcp/mcp` with NO key and Claude walks the
user through consent (tokens appear in Settings → API keys, revocable). The keyed URL below
also still works.

Everpop also runs a Model Context Protocol server. In Claude → Settings →
Connectors → Add custom connector:

    URL:     https://everpop.app/api/mcp/mcp
    Header:  Authorization: Bearer epk_...

Prefer the header — it keeps your key out of the URL, and therefore out of browser
history, server logs, referrers, and shared screenshots. If your client genuinely
can't send a header, the key can ride in the URL as a fallback
(`https://everpop.app/api/mcp/mcp?key=epk_...`) — but treat that whole URL like a
password, and rotate the key from Settings → API keys if it ever leaks.

### Available tools

- `generate_short` — Generate a vertical short from a text prompt (AI script, voiceover, visuals, animated captions); returns a jobId — poll with `get_job` (1–3 min).
- `list_videos` — List your detected source YouTube uploads, newest first.
- `request_upload` — Presigned slot for the user's video FILE (PUT bytes yourself, 15-min validity, ≤4 GB).
- `finalize_upload` — Turn the uploaded file into a clippable library video; auto-clips for active plans; `linkSourceVideoId` attaches it to a parked detection.
- `import_video` — Import a specific YouTube video by URL/id when it isn't in `list_videos` yet (e.g. an older upload). Own-channel only; returns a videoId for `clip_video`.
- `clip_video` — Create short clips from one of your source videos; an optional prompt directs which moments to clip; returns a jobId.
- `get_job` — Check a clip/generation job; returns status and, when COMPLETED, the clips with their video URLs and clipIds (use a clipId with `publish_clip`).
- `publish_clip` — Publish a READY clip to your connected channel (e.g. a YouTube Short). Asks you to confirm first — publishing is public and not easily undone.
- `list_receipts` — Your published clips' real measured performance (48h & 7d views, retention, likes, subscribers gained) with shareable proof links.
- `create_campaign` — Create a paid-clipping campaign to group published clips into one verifiable payout proof; returns a campaignId.
- `list_campaigns` — List your campaigns with post counts, verified views, CPM, and each campaign's public payout-proof link.
- `attach_to_campaign` — Attach your published posts to a campaign so they count toward its payout proof.
- `campaign_proof` — A campaign's verified payout proof: per-clip 48h/7d numbers, totals, the estimated payout, and the public proof link.

(The `import_video` MCP tool is own-channel only. To import licensed/third-party footage you hold the rights to, use the REST endpoint `POST /api/v1/videos/import` with `rightsConfirmed: true` — that rights-attestation path is intentionally not exposed over MCP.)
