# Everpop — llms-full.txt > The complete agent-facing documentation in one file: llms.txt (canonical facts and index), auth.md (how agents authenticate) and skill.md (the REST API and MCP guide). Generated from those three files by scripts/build-llms-full.mjs; they remain the sources of truth. --- # Everpop > Everpop is an AI clipping tool that turns a creator's own uploaded videos into published YouTube Shorts, Instagram Reels, Facebook Reels and TikTok posts, never downloads from YouTube, publishes to the creator's own connected channels after their confirmation, and reports 48-hour and 7-day YouTube Analytics receipts for eligible Shorts. > It is built to be driven by AI agents: a model has the brains, Everpop gives it the hands to actually clip and publish. ## Canonical facts - Everpop is a Shorts automation tool: your video in (a file you upload — never a YouTube download), published Short out — to YouTube Shorts, Instagram Reels, Facebook Reels or TikTok (review-first) — with measured receipts on eligible YouTube Shorts. - Everpop exposes a public REST API and a Model Context Protocol (MCP) server, so AI agents can operate it directly. - Eligible YouTube Shorts receive aggregate metrics pulled from the YouTube Analytics API at 48h and 7d. A receipt may include a separately signed pre-publish prediction; measured metrics are not separately signed. - Manual/API publishing requires exact destination ids, final metadata and visibility, plus explicit user confirmation — agents included. No implicit publish-to-all. - Auth is a per-user API key (`Authorization: Bearer epk_...`), created in Dashboard → API (https://everpop.app/dashboard/api). - The REST API and the MCP server need the Pro or Scale plan. Other accounts get HTTP 402 with `reason: "subscription"` (no active subscription) or `reason: "plan"` (the plan doesn't include API access); over MCP the 402 comes inside each tool result. - Which Everpop: The AI video clipping and publishing software at everpop.app, operated by Very - Fast Ltd., Vratsa, Bulgaria. Very - Fast Ltd. is registered in Bulgaria, in the EU; the services that process data for Everpop, and where each is based, are listed at [everpop.app/data-processors](https://everpop.app/data-processors). ## Plans and limits - Starter: $9/mo or $86/yr. 1 YouTube channel, 8 videos a month, 3 clips per video. You review and approve every post. No REST API or MCP. - Pro: $49/mo or $470/yr. 3 YouTube channels, 30 videos a month, up to 10 clips per video. Hands-free auto-posting, the REST API and MCP, and Campaign Mode. - Scale: from $149/mo, shaped on a call. 10 YouTube channels, up to 75 videos a month, up to 15 clips per video. Hands-free auto-posting, the REST API and MCP, and Campaign Mode. - Campaign Mode comes with Pro and Scale. - One episode counts as one video (files up to 32 GB). - Your first video is free — up to 3 clips, no card. - Upload formats: .mp4, .mov, .webm, .mkv or .m4v, up to 32 GB per file. - Aspect ratios: 9:16, 1:1, 16:9 and 4:5 (REST POST /api/v1/clip takes aspectRatio; MCP clip_video and automatic renders use the account's saved setting). - Captions: Native captions in 9 languages — English, German, Spanish, French, Italian, Portuguese, Dutch, Polish, Bulgarian — and 90+ other spoken languages captioned in English. - Full plan details: https://everpop.app/pricing ## By audience - [Podcasters: Podcast to Shorts](https://everpop.app/podcast-to-shorts): every episode becomes Shorts, Reels and TikToks — one episode counts as one video (files up to 32 GB). - [Streamers: Stream VODs to Shorts](https://everpop.app/streamer-vods-to-shorts): a streamer's own VOD file in, Shorts out to their own accounts; the Gameplay Cut keeps the HUD readable. - [Paid-campaign clippers: Clip for Whop Content Rewards](https://everpop.app/whop-content-rewards-clipper): pay-per-view campaign clipping with rights-attested footage and a token-protected measured report. - [Paid-campaign clippers: Campaign Mode](https://everpop.app/campaigns): for paid pay-per-view clip campaigns — rights-attested ingest, publishing, and a token-protected payout report. Everpop does not submit clips to marketplaces — that step is yours; as of September 2026 none of the marketplaces we checked (Whop Content Rewards, ClipAffiliates) publishes a submission API. - [Campaign owners: For campaign owners](https://everpop.app/for-campaign-owners): pay clippers on measured YouTube Analytics numbers, not screenshots — free to open, no account needed. - [Agencies: AI clipping for agencies](https://everpop.app/ai-clipping-for-agencies): several client channels from one review-first workspace — invited managers clip with a folder per client, publishing stays review-first unless you allow it, and eligible Shorts come back with measured 48-hour and 7-day numbers for each client. - [AI agents: For agents](https://everpop.app/agents): the MCP server and REST API on one page — quickstart, auth, and integration paths. ## Comparisons Each page compares Everpop with one product, cell by cell: where the video comes from, publishing, receipts, pricing and what a 40-minute upload costs. Based on each product’s public pricing pages and documentation, checked 16 September 2026. A “—” means not advertised on the product’s public pages. Trademarks belong to their owners. OpusClip, Klap, Vizard, Ssemble, Choppity, quso.ai and Submagic are not affiliated with and do not endorse Everpop. - [Everpop compared](https://everpop.app/compare): every comparison below, on one page. - [Everpop vs OpusClip](https://everpop.app/compare/opusclip): opus.pro - [Everpop vs Klap](https://everpop.app/compare/klap): klap.app - [Everpop vs Vizard](https://everpop.app/compare/vizard): vizard.ai - [Everpop vs Ssemble](https://everpop.app/compare/ssemble): ssemble.com - [Everpop vs Choppity](https://everpop.app/compare/choppity): choppity.com - [Everpop vs quso.ai](https://everpop.app/compare/quso): quso.ai - [Everpop vs Submagic](https://everpop.app/compare/submagic): submagic.co ## Guides Articles from the Everpop blog: what Everpop is first, then how clipping, rights and proof work. Every post is at [the blog](https://everpop.app/blog). - [What Is Everpop? AI Video Clipping Software](https://everpop.app/blog/what-is-everpop-ai-video-clipping-software): what Everpop does, from your uploaded video to review-first vertical Shorts with captions and 48-hour and 7-day YouTube Analytics receipts. - [Why Everpop? An Honest AI Clipping Software Review](https://everpop.app/blog/why-everpop-honest-review): what the software does and does not do: receipts, review-first approval, upload-only ingestion, no lock-in. - [Is Everpop Safe for My Channel? Compliance Facts](https://everpop.app/blog/is-everpop-safe-for-my-channel-compliance-breakdown): how Everpop handles a channel, files, data and billing: official APIs, no YouTube downloads. - [How to Use Everpop: A Step-by-Step Walkthrough](https://everpop.app/blog/how-to-use-everpop-step-by-step-walkthrough): connect, clip, review, publish and read your receipts. - [Channel-Safe Clipping: No YouTube Downloads](https://everpop.app/blog/channel-safe-clipping): what YouTube's rules say about downloading videos, and how upload-first clipping works. - [Who Owns the Clips an AI Tool Makes?](https://everpop.app/blog/who-owns-the-clips-an-ai-tool-makes): who owns a clip after clipping, per YouTube's terms, the US Copyright Office and open font licenses. - [Can I Clip Someone Else's YouTube Video?](https://everpop.app/blog/can-i-clip-someone-elses-youtube-video-copyright): fair use's four factors, YouTube's copyright rules, and safer ways to clip. - [Podcast Clip Maker: Turn Episodes Into Shorts](https://everpop.app/blog/podcast-clip-maker-turn-episodes-into-shorts): how one episode becomes vertical Shorts with burned-in captions, and what a finished clip looks like. - [Prove Clip Results to Sponsors With Receipts](https://everpop.app/blog/prove-clip-results-to-sponsors-with-receipts): a receipt link a sponsor opens, with numbers from YouTube Analytics, instead of a screenshot. - [Run Clip Campaigns Without Risking the Channel](https://everpop.app/blog/run-clip-campaigns-without-risking-the-channel): for agencies and clippers: work from the creator's files, keep them in the approval loop, prove the work. - [How to Tell if YouTube Views Are Fake](https://everpop.app/blog/spot-bot-inflated-view-campaigns-free-checker): spotting bot-inflated views from public signals, and the free checker at /verify. ## Proof and free tools - [Proof](https://everpop.app/proof): measured performance of eligible YouTube Shorts published with Everpop: views, retention and subscribers from the YouTube Analytics API at 48 hours and 7 days. - [Free YouTube engagement checker](https://everpop.app/verify): check one video or up to 50 unique campaign video links for unusual public engagement. Free Google sign-in creates or opens an Everpop account; no card, paid plan or channel connection is required. Shows public counts, engagement per 1,000 views and average views per day. It cannot see retention, prove purchased views or predict virality. - [Review YouTube campaign submissions — worked examples](https://everpop.app/verify/guide): a public, no-login guide to batch checks, the four result labels, exact calculations, limitations and follow-up questions. Fictional examples are labeled as such. - [How receipt signatures work](https://everpop.app/receipts/verify): the ed25519 public key and exact payload to check a receipt's signed pre-publish prediction yourself. The measured metrics are not signed. - [Sample receipt](https://everpop.app/r/sample): what a receipt looks like, with illustrative 48-hour and 7-day numbers and a real signature over a clearly labeled demo payload. - [See it on a real video](https://everpop.app/see-it): a real 4-minute source and the Shorts the engine cut from it, unedited; the same sample can be run in your own account with nothing to upload. - [Pick your Pop](https://everpop.app/pops): the four cut styles (Recap, Top, Punch and Killer Pop) and what each one is for. - [Blog RSS feed](https://everpop.app/blog/rss.xml): the newest 100 published posts, newest first. ## YouTube checker: scope and limits Everpop Verify is useful when reviewing public YouTube video engagement or deciding which campaign submissions need closer human review. It accepts individual watch, youtu.be and Shorts URLs, not channel handles or playlists. Whole campaign checks up to 50 unique valid video links per batch, ignores unrecognized text, deduplicates links and reports when a larger input was truncated. Unavailable videos are listed separately. The checker reads public views, likes, comments and publication dates from the YouTube Data API. Likes per 1,000 views = likes / views × 1,000; comments per 1,000 views = comments / views × 1,000. Average views per day = total views / video age in days, with the current view count used for videos under one day old. That average is not observed burst history or a live growth rate. Public counts may be cached for up to three hours. The result labels are consistent, suspicious, mixed and not enough data. They are review heuristics, not probabilities or proof of fraud. A consistent result does not certify genuine viewers. Low engagement can reflect niche, format, missing counts or traffic source. The checker cannot access viewer identities, retention or traffic sources from a pasted link, and does not predict future reach. It does not download, clip or publish the submitted video. The free browser checker is separate from Everpop’s paid REST API/MCP access and from owner-authorized YouTube Analytics receipts for eligible Shorts published through Everpop. A receipt supplies available measurements at 48 hours and 7 days; it does not certify every view as genuine. ## Markdown versions Clean Markdown twins of key pages, built from the same content as the HTML page; each HTML page links its twin with ``. skill.md and auth.md are Markdown already (see Docs). - [For agents (Markdown)](https://everpop.app/agents.md): Markdown twin of https://everpop.app/agents. - [Pricing (Markdown)](https://everpop.app/pricing.md): Markdown twin of https://everpop.app/pricing. - [Podcast to Shorts (Markdown)](https://everpop.app/podcast-to-shorts.md): Markdown twin of https://everpop.app/podcast-to-shorts. - [Stream VODs to Shorts (Markdown)](https://everpop.app/streamer-vods-to-shorts.md): Markdown twin of https://everpop.app/streamer-vods-to-shorts. - [Clip for Whop Content Rewards (Markdown)](https://everpop.app/whop-content-rewards-clipper.md): Markdown twin of https://everpop.app/whop-content-rewards-clipper. - [For campaign owners (Markdown)](https://everpop.app/for-campaign-owners.md): Markdown twin of https://everpop.app/for-campaign-owners. - [AI clipping for agencies (Markdown)](https://everpop.app/ai-clipping-for-agencies.md): Markdown twin of https://everpop.app/ai-clipping-for-agencies. - [Everpop vs OpusClip (Markdown)](https://everpop.app/compare/opusclip.md): Markdown twin of https://everpop.app/compare/opusclip. - [Everpop vs Klap (Markdown)](https://everpop.app/compare/klap.md): Markdown twin of https://everpop.app/compare/klap. - [Everpop vs Vizard (Markdown)](https://everpop.app/compare/vizard.md): Markdown twin of https://everpop.app/compare/vizard. - [Everpop vs Ssemble (Markdown)](https://everpop.app/compare/ssemble.md): Markdown twin of https://everpop.app/compare/ssemble. - [Everpop vs Choppity (Markdown)](https://everpop.app/compare/choppity.md): Markdown twin of https://everpop.app/compare/choppity. - [Everpop vs quso.ai (Markdown)](https://everpop.app/compare/quso.md): Markdown twin of https://everpop.app/compare/quso. - [Everpop vs Submagic (Markdown)](https://everpop.app/compare/submagic.md): Markdown twin of https://everpop.app/compare/submagic. Every published blog article has one too, at its URL plus `.md`: `https://everpop.app/blog/.md` (title, dates, body and FAQ). ## Docs - [Agent skill / API guide](https://everpop.app/skill.md): how an agent uploads, clips, publishes, and pulls receipts. - [Auth guide](https://everpop.app/auth.md): how agents authenticate — OAuth 2.1 + PKCE for MCP clients, or a per-user Bearer key. - [llms-full.txt](https://everpop.app/llms-full.txt): this file plus auth.md and skill.md in one document, for agents that read once. - [Pricing](https://everpop.app/pricing): plans and limits. - [Terms](https://everpop.app/terms) and [Privacy](https://everpop.app/privacy). ## API surface (see skill.md for full detail) Requires Pro or Scale; other accounts get 402 reason subscription|plan. - `POST /api/v1/generate` — paused: returns 403 `{reason:"disabled"}` and creates nothing (not part of the MCP connector). - `POST /api/v1/clip` — clip moments from one of the user's videos (clipCount 1–20, capped by the plan's clips per video; the response echoes clipCountApplied). `language` names the language SPOKEN: omit = the saved choice, `null` = English captions from any speech; never send `en` for non-English speech. - `POST /api/v1/videos/upload` — exact-size presigned slot for the user's video FILE; PUT exactly `expectedBytes` with every returned `requiredHeaders` entry (≤5 GB per PUT; files up to 32 GB go through browserUploadUrl). - `DELETE /api/v1/videos/upload` — cancel a failed/abandoned slot; 503 `cleanup_pending` means durable automatic cleanup, not permission to finalize. - `POST /api/v1/videos/complete` — finalize an upload into a clippable video; auto-clips for active plans. - `POST /api/v1/videos/import` — register a YouTube video's metadata (own channel; clipping needs the FILE — see upload). - `GET /api/v1/videos` — list the user's videos, 50 per page (follow `nextCursor`); each says whether it is `clippable` and carries its `latestJob`. - `GET /api/v1/usage` — the plan, videos used and remaining this month (with the reset date), clips per video, and whether finishing an upload auto-clips. - `GET /api/v1/jobs` — list clip jobs newest first (`?sourceVideoId=`, follow `nextCursor`); finds the render an upload started. - `GET /api/v1/posts` — list posts on every platform with status, published URL and the reason a post did not go out (`?clipId=` follows one clip's publish). - `GET /api/v1/jobs/{id}` — poll a clip job until it leaves PENDING/PROCESSING; clips carry the `clipId` publish takes. - `GET /api/v1/publish` — list exact connected destination ids. - `POST /api/v1/publish` — publish a completed clip to exact destination ids with reviewed metadata and visibility (requires user confirmation). - `GET /api/v1/campaigns` — list campaigns with post counts, measured views and each campaign's public payout-report link. - `POST /api/v1/campaigns` — create a paid-clipping campaign (Campaign Mode, Pro or Scale). - `POST /api/v1/campaigns/{id}/attach` — attach published posts (`postId` values from receipts) to a campaign. - `GET /api/v1/campaigns/{id}/proof` — a campaign's measured payout report; `?csv=1` for a spreadsheet. - `GET /api/v1/receipts` — measured performance per published clip. - MCP connector: `https://everpop.app/api/mcp/mcp` (16 tools; OAuth 2.1 + PKCE, or an `Authorization: Bearer epk_...` header; requires Pro or Scale — other accounts get 402 reason subscription|plan in each tool result) - [OpenAPI 3.1 spec](https://everpop.app/openapi.json) — machine-readable schema of every endpoint above. - [For agents](https://everpop.app/agents): quickstart, auth, and integration paths on one page. --- # Authentication How AI agents authenticate to Everpop. Everpop is built to be operated by agents, and every way in is documented here. Base URL: https://everpop.app ## 1. API key (simplest) - A human creates the key: Dashboard → API (https://everpop.app/dashboard/api). Keys look like `epk_...`. - Send it on every request: `Authorization: Bearer epk_...` - The key acts as that user, within their plan limits. Treat it as a secret; never embed it in client-side code or share it in logs. - The REST API and MCP need the **Pro or Scale plan**. Other accounts get HTTP 402 with `reason: "subscription"` (no active subscription) or `reason: "plan"` (the plan doesn't include API access). ## 2. MCP (Model Context Protocol) - Endpoint: `https://everpop.app/api/mcp/mcp` - Two auth modes: - **OAuth 2.1 + PKCE (S256)** — discovery at [`/.well-known/oauth-authorization-server`](https://everpop.app/.well-known/oauth-authorization-server). Public clients only; dynamic client registration is open at the `registration_endpoint` listed there. The human approves access in a consent popup on everpop.app. Any account can complete consent and list the tools; each tool answers an account without Pro or Scale with a 402 result (`reason` subscription or plan) instead of acting. - **Bearer header** — clients without an OAuth flow send an API key as `Authorization: Bearer epk_...`. API keys are never accepted in URL query strings. ## Key lifecycle - **Scope.** A key is *Full (read + write)*, the default, or *Read-only*. A read-only key can call every `GET` endpoint. These calls need a full key: `POST /api/v1/clip`, `POST /api/v1/generate`, `POST` and `DELETE /api/v1/videos/upload`, `POST /api/v1/videos/complete`, `POST /api/v1/videos/import`, `POST /api/v1/publish`, `POST /api/v1/campaigns` and `POST /api/v1/campaigns/{id}/attach`. A read-only key there gets HTTP 403 with `code: "scope"`. - **Expiry.** When creating a key, the user picks 30 days, 90 days (the default), 1 year or Never. An expired key cannot be renewed: create a new one. - **Revocation.** Revoking a key in Dashboard → API stops it at once; it then answers like a key that never existed. - The full key is shown once, when it is created. Everpop stores only a hash of it. ## When the REST API refuses a key | HTTP | `code` | Meaning | What to do | |---|---|---|---| | 401 | `key_missing` | No `Authorization: Bearer epk_...` header. | Send the header. | | 401 | `key_invalid` | The key is unknown or was revoked. | Ask the user for a current key. | | 401 | `key_expired` | The key passed its expiry. | The user creates a new key in Dashboard → API. | | 402 | `subscription` or `plan` | No active subscription, or a plan without API access. | Tell the user; retrying won't change it. | | 403 | `scope` | A read-only key on a write. | The user creates a key with write access. | | 403 | `suspended` | The account is suspended. | The user contacts support@everpop.app. | Every other error code is in [skill.md](https://everpop.app/skill.md) (Error codes). ## What auth does NOT unlock Publishing is never implicit. `POST /api/v1/publish` requires exact destination ids, final reviewed metadata and visibility, and explicit confirmation from the human user — agents included. There is no publish-to-all. ## More - [llms.txt](https://everpop.app/llms.txt) — canonical facts and API surface. - [skill.md](https://everpop.app/skill.md) — the full agent guide. - [openapi.json](https://everpop.app/openapi.json) — machine-readable schema. --- # Everpop — agent skill Everpop is an AI clipping tool that turns a creator's own uploaded videos into published YouTube Shorts, Instagram Reels, Facebook Reels and TikTok posts, never downloads from YouTube, publishes to the creator's own connected channels after their confirmation, and reports 48-hour and 7-day YouTube Analytics receipts for eligible Shorts. 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 → API — https://everpop.app/dashboard/api) Plan: the REST API and MCP need the Pro or Scale plan. Other accounts get HTTP 402 with `reason: "subscription"` or `reason: "plan"` (see Notes for agents). ## Check the plan and allowance first ```bash curl -s https://everpop.app/api/v1/usage -H "Authorization: Bearer $EVERPOP_API_KEY" ``` GET /api/v1/usage → `{ "ok": true, "data": { "plan": "pro", "videos": { "used": 3, "limit": 30, "remaining": 27, "resetsAt": "..." }, "clipsPerVideo": 10, "capabilities": { "apiAccess": true, "autoPost": true, "campaigns": true, "fourK": true, "customFonts": true }, "destinationsConnected": 2, "autoClipOnFinalize": true } }` Every clip job uses one video of the monthly allowance (one episode is one video; files up to 32 GB), except the first render of a video in a month whose only clip repeats a moment you already clipped (its `qcWarnings` carry `repeat_moment`): that render hands its video back. Tell the user how many videos remain before you start a render. `autoClipOnFinalize` says whether finishing an upload will start a render on its own. ## Poll a job ```bash curl -s https://everpop.app/api/v1/jobs/ -H "Authorization: Bearer $EVERPOP_API_KEY" ``` GET /api/v1/jobs/{jobId} → `{ "ok": true, "data": { "jobId": "...", "status": "PENDING|PROCESSING|COMPLETED|FAILED|CANCELED", "error": null, "clipCountApplied": 3, "clips": [{ "clipId": "...", "id": "...", "title": ..., "clipUrl": ..., "thumbnailUrl": ..., "durationSeconds": ..., "status": ..., "review": { "qcWarnings": [{ "flag": "...", "label": "...", "detail": "..." }], "sourceStartSeconds": ..., "sourceEndSeconds": ..., "archetype": ..., "captions": ..., "hook": ..., "width": ..., "height": ..., "heldForReview": false } }] } }` Poll every 15–30s and stop on any status other than PENDING or PROCESSING (COMPLETED, FAILED or CANCELED). `error` is a customer-safe explanation when the job did not complete. `clips[].clipId` is the id `POST /api/v1/publish` takes (`id` carries the same value). How long a render takes: in the 30 days to 2026-09-23, half of the completed clip jobs had their clips within about 10 minutes of the request, and 9 in 10 within about 19 minutes (from the request to the last clip, across all source lengths). The engine gives each render a 60-minute budget and stops a render that runs past it; time spent waiting in the queue before the render starts is not part of that budget. If a job is still PENDING or PROCESSING after 90 minutes, stop polling, tell the user it is taking longer than usual, and check it again later. Polling never changes the job. Each clip's `review` is what to tell the user before asking them to confirm a publish: `qcWarnings` (quality-check warnings; a flagged clip can still be published by the user's explicit choice, so name the warnings), where the clip sits in the source (`sourceStartSeconds`/`sourceEndSeconds`), the `hook` (the opening words), `captions`, and the measured `width`/`height`. `heldForReview` is true when an earlier publish attempt left the clip held for content review. A clip job you request (`clip_video` or `POST /api/v1/clip`) on a video whose strong moments were all clipped already does not fail: it returns one clip that reuses the best of them, flagged `repeat_moment` in `qcWarnings`. Tell the user it repeats a moment they already have before they publish it. ## 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" # → { "ok": true, "data": [{ "id": "...", "title": "...", "status": "...", "detectedAt": "...", "detectionMethod": "...", "clippable": true, "notClippableReason": null, "latestJob": { "jobId": "...", "status": "PROCESSING", "error": null, "createdAt": "..." } }], "nextCursor": "..." } ``` - Newest first, 50 per page (`?limit=` 1–100). While `nextCursor` is not null, pass it back as `?cursor=` for the next (older) page. - Only clip videos with `clippable: true`. When it is false, `notClippableReason` is the code `/api/v1/clip` would return: `upload_required` (upload the file and attach it with `linkSourceVideoId`, below), `generated_source` (a generated short's placeholder) or `demo_source` (Everpop's sample). - `latestJob` is the newest clip job for that video (or null) — after an upload auto-clips, this is where its job id shows up. ## Find jobs and posts again ```bash curl -s "https://everpop.app/api/v1/jobs?sourceVideoId=" -H "Authorization: Bearer $EVERPOP_API_KEY" # → { "ok": true, "data": [{ "jobId": "...", "sourceVideoId": "...", "status": "...", "error": null, "clipCountApplied": 3, "createdAt": "...", "poll": "/api/v1/jobs/..." }], "nextCursor": null } curl -s https://everpop.app/api/v1/posts -H "Authorization: Bearer $EVERPOP_API_KEY" # → { "ok": true, "data": [{ "postId": "...", "clipId": "...", "destinationId": "...", "destinationName": "...", "platform": "TIKTOK", "status": "DELIVERED", "publishedUrl": null, "scheduledAt": null, "postedAt": null, "error": null, "createdAt": "..." }], "nextCursor": null } ``` - Both are newest first, 20 per page (`?limit=` 1–100); follow `nextCursor`. - `/posts` covers every platform. `DELIVERED` means the video is in the creator's TikTok inbox as a draft; going public stays their tap. `error` is the reason a post did not go out, as the Posts page shows it. - `/posts?clipId=` returns only that clip's posts: how you follow a publish (below). ## 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}' # → { "ok": true, "data": { "putUrl": "...", "key": "...", "requiredHeaders": { "Content-Type": "video/mp4", "If-None-Match": "*" }, "expectedBytes": 734003200, "expiresInSeconds": 900, "next": "PUT exactly expectedBytes ... then POST /api/v1/videos/complete ..." } } # 2. PUT exactly expectedBytes straight to storage (valid 15 min, up to 5 GB — one PUT's limit; files up to 32 GB go through browserUploadUrl). # Send every requiredHeaders entry; curl supplies Content-Length automatically. curl -s -X PUT "$PUT_URL" -H "content-type: video/mp4" -H "if-none-match: *" --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":"","title":"Episode 42","rightsConfirmed":true}' # → { "ok": true, "data": { "videoId": "...", "title": "Episode 42", "existing": false, "linked": false, "autoClipping": true } } # autoClipping true = a render is ALREADY running; optional parked:"quota" = uploaded safely, but monthly videos are used up # add "renderMode":"manual" to skip the automatic render (the response then carries renderMode:"manual") ``` At most 3 uploads can be open at once; a fourth `POST /api/v1/videos/upload` answers 429 `upload_slots`. Finalize or cancel one first (a canceled slot keeps counting until its 15-minute window ends). If the PUT times out, the connection drops, or a retried PUT answers `412` (`If-None-Match: *` refuses to overwrite, so a 412 means the bytes are already stored), do not cancel. Call `/api/v1/videos/complete` with the same key first. Only a 400 there ("Upload not found") means the bytes never landed: PUT again while `putUrl` is still valid, or release the slot and start over. If the PUT fails or is abandoned, release the slot with the same durable key: ```bash curl -s -X DELETE https://everpop.app/api/v1/videos/upload \ -H "Authorization: Bearer $EVERPOP_API_KEY" \ -H "content-type: application/json" \ -d '{"key":""}' ``` A 503 with `reason: "cleanup_pending"` means provider cleanup is durably queued and will retry automatically. If finalization returns a network error, 429, 5xx, or `upload_not_ready`, retry finalization with the same key. Do not upload the bytes again, and never cancel after a successful or ambiguously acknowledged finalization. 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). - **Can't send file bytes?** (e.g. you run inside a chat app) GET /videos carries `browserUploadUrl` beside `data`: an Everpop page, behind the user's own sign-in, where they upload a new file themselves. It opens no upload slot. The 422 and a /videos row carry `uploadUrl` for that one video, and /videos/import returns its `browserUploadUrl`. /videos/upload returns the link too, but don't call it just for the link: its slot counts against the user's open uploads until it expires (15 minutes), even if you cancel it. Give them the link, then list videos to continue. - Uploads **auto-clip on completion** for active subscribers, so after an upload check `latestJob` on /videos (or `GET /api/v1/jobs?sourceVideoId=`) — clips may already be rendering. - Pass `renderMode: "manual"` to /videos/complete when you will call /clip with your own options; otherwise the automatic render is this video's one allowance, and a later /clip with options is a second render that uses another. - 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 32 GB are not accepted on any path (413 `code: "file_too_large"`) — re-export at 1080p around 4 Mbps or 720p, or trim. One PUT carries at most 5 GB: a bigger file answers 413 `file_too_large` with `reason: "single_put"` and `browserUploadUrl` — the user uploads it there (up to 32 GB). ## 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":"","prompt":"the most surprising moment, ending on a cliffhanger","clipCount":2,"targetSeconds":45,"captionStyle":"pop"}' ``` - `clipCount` is 1–20; omit it for the account's saved clip count (3 if unset). Your plan's clips per video caps it (Starter 3, Pro 10, Scale 15), and the response's `clipCountApplied` says what the job runs with. - `prompt` is optional — omit it and the AI picks the best moments itself. - `archetype` is optional: `top_moments`, `summary` (a stitched montage), `punch`, `action`, or `all` (a Summary, a Top-moment and a Punch from one pass). - `targetSeconds` (10–180) biases the clip length; `captionStyle` is `pop | boxed | minimal | clean | hormozi`. - `aspectRatio` (`9:16 | 1:1 | 16:9 | 4:5`) sets the frame and `captionsEnabled` (`true` or `false`) turns burned-in captions on or off for this render. Omit either for the account's saved setting (9:16 with captions if unset). - Send an `Idempotency-Key` header so a retried request never mints a second render. - Returns the job; poll it with `GET /api/v1/jobs/{id}`: `{ "ok": true, "data": { "jobId": "...", "status": "PENDING", "poll": "/api/v1/jobs/...", "clipCountApplied": 2, "aspectRatio": "9:16", "captionsEnabled": true } }`. `clipCountApplied`, `aspectRatio` and `captionsEnabled` are the values the job runs with, including the saved settings it used for anything you omitted. ### Language `language` sets the language of the captions, headlines and hooks. It names the language that is SPOKEN in the video, not the one you want to read: - **omit it** → the account's saved language choice (English unless the creator pinned a language in Settings). - **`null`** → English captions from any speech: the speech language is auto-detected and non-English speech is translated to English. - **an ISO-639-1 code** (`bg`, `de`, `es`, …) → the speech is in that language; captions stay in it. `"en"` means the speech IS English. Never send `"en"` to get English captions from non-English speech — it tells the speech recognizer to hear English and leaves the clip nearly caption-less. Send `null` instead. The original audio is always kept. ## Publish a clip to exact connected destinations First list the destination ids and show the user the exact platform/account: ```bash curl -s https://everpop.app/api/v1/publish \ -H "Authorization: Bearer $EVERPOP_API_KEY" ``` Then show the user the final title, description, visibility, and every selected destination. Only after their explicit confirmation: ```bash curl -s -X POST https://everpop.app/api/v1/publish \ -H "Authorization: Bearer $EVERPOP_API_KEY" \ -H "content-type: application/json" \ -d '{"clipId":"","destinationIds":[""],"metadata":{"title":"","description":"","privacyStatus":"public"}}' # → { "ok": true, "data": { "clipId": "...", "posts": [ # { "destinationId": "...", "platform": "YOUTUBE_SHORTS", "status": "PUBLISHING" }, # { "destinationId": "...", "platform": "INSTAGRAM_REELS", "status": "CONFLICT", "currentStatus": "PUBLISHED", # "errorCode": "PUBLISH_INTENT_CONFLICT", "errorMessage": "This destination already has a publish with different reviewed choices. Refresh to see the active post before trying again." } ] } } ``` `ok: true` means Everpop took the request, not that every destination went out. Check each `posts[].status` (and `errorCode`) and tell the user what happened on each account: | `status` | Final? | Meaning | |---|---|---| | `PUBLISHED` | final | Live on the platform; `/posts` carries `publishedUrl`. | | `DELIVERED` | final | In the creator's TikTok inbox as a draft; going public stays their tap. | | `FAILED` | final | Did not go out; `errorMessage` (and `error` on `/posts`) says why. | | `DISMISSED` | final | Discarded by the creator; Everpop does not retry it on its own. | | `CONFLICT` | final for this call | Nothing new was sent there. `errorCode` `PUBLISH_INTENT_CONFLICT`: that destination already has a publish of this clip with different choices (`currentStatus` is its status). `META_PUBLISH_HISTORY_REVIEW_REQUIRED`: Everpop cannot tell whether an earlier Instagram or Facebook publish of this clip went live, so it is held for support review to avoid a duplicate. | | `PENDING`, `QUEUED`, `PUBLISHING` | in flight | Still going out. | | `SCHEDULED` | in flight | Waits for its go-live time (`scheduledAt`). | | `DEFERRED` | in flight | Held for a later retry because a daily YouTube upload quota was reached; not a failure. | A post that is not final but carries `errorMessage` (`error` on `/posts`) is held, and that text says why (for example an Autopilot Reel waiting for the creator to choose public visibility): tell the user what it says and check back later instead of polling. Follow the other in-flight posts with `GET /api/v1/posts?clipId=`: every 30–60 seconds for the first few minutes, then every few minutes, until every destination is final. A `SCHEDULED` or `DEFERRED` post can take hours or a day: tell the user and check back later instead of polling. If a post is still `PENDING`, `QUEUED` or `PUBLISHING` after an hour, stop polling, tell the user it is taking longer than usual, and check it again later. Polling never changes a post. - `clipId` comes from a COMPLETED job's `clips[].clipId`. - `destinationIds` must contain the exact ids returned by `GET /api/v1/publish`; omission never means "all connected accounts." If any id is not connected and healthy, nothing publishes: 422 `reason: "unknown_destination"` lists them in `destinationIds` — re-read the list and re-confirm with the user. - A YouTube destination only takes clips whose source video came from that same channel (a clip from an uploaded file can use it when it is the one healthy connected YouTube channel). Otherwise: 422 `reason: "no_eligible_destination"`. - Other refusals carry a `reason`: 403 `content_review` (held for review), 409 `clip_removed`, 404 `not_found`, 422 `clip_not_ready` / `rights_unconfirmed`. - `metadata` is the final reviewed title/caption, description, and visibility. `private` and `unlisted` work only when every destination is YouTube: with any other destination in the request, a non-public choice returns 422 and nothing is published. - Idempotent per (clip, destination): a clip already published returns its existing post. - Retries: send an `Idempotency-Key` header on `POST /api/v1/clip` and `POST /api/v1/generate` (MCP: `operationId`) so a retried request never mints a second metered render; without it, only option-less requests inside a 20-second window are deduplicated. - **Only publish after the user explicitly confirms all destinations, metadata, and visibility** — provider publication is not easily undone. ## Pull receipts (real measured performance) ```bash curl -s "https://everpop.app/api/v1/receipts?limit=20" -H "Authorization: Bearer $EVERPOP_API_KEY" # → { "ok": true, "data": { "receipts": [{ "postId": "...", "title": "...", "publishedUrl": "...", "postedAt": "...", "outcomes": { "h48": { "views": ..., "averageViewPercentage": ..., "likes": ..., "comments": ..., "shares": ..., "subscribersGained": ..., "measuredAt": "..." }, "d7": null }, "receiptUrl": "..." }], "campaignReportUrl": "..." }, "nextCursor": "..." } ``` → per eligible YouTube Short published through Everpop: 48h and 7d aggregate metrics (views, retention %, likes, comments, shares, subscribers gained), a public token-protected `receiptUrl`, and a `campaignReportUrl` bundling the measured receipts on the page. - Newest first, 100 per page (`?limit=` 1–100). While `nextCursor` is not null, pass it back as `?cursor=` for older receipts. - `campaignReportUrl` bundles the measured receipts on that page (`null` when none of them is measured yet); a window that is not measured yet is `null`. A receipt may also contain a separately signed pre-publish prediction; the later measured metrics are fetched from YouTube and are not separately signed. These links are a measured report a campaign owner can open; the marketplace's own view count and snapshot date govern payout. Measured numbers are not cryptographically signed — the link token controls access only. ## Notes for agents - MCP `clip_video` and `finalize_upload` renders stay drafts even on Autopilot: they require review and an explicit `publish_clip` call. This also applies to render retries and upload recovery. A `review_required_conflict` means an existing render has incompatible publication settings; review that job in Everpop, never bypass the conflict with a new key. Other upload/API automation retains the account's configured publishing behavior. - 402 carries a `reason`: `subscription` means the account has no active subscription (subscribe or redeem an invite code); `plan` means its plan doesn't include API and agent access (REST and MCP need the Pro or Scale plan). 401 means the key did not authenticate: `key_missing`, `key_invalid` (unknown or revoked) or `key_expired` (see auth.md). 429: see the table below. - Every error body carries a stable `code` (the specific one such as `upload_required` or `quota_exhausted`, else the `reason`, else by status: `bad_request`, `not_found`, `rate_limited`, `internal_error`, …). Branch on `code`; `reason` stays where it existed. MCP errors add `status`, and MCP rate limits add `retryAfterSeconds`. - 503 with "engine is offline" (`code: "engine_offline"`) → Everpop's clipping service is briefly unavailable. Tell the user nothing was charged and retry the same request in a few minutes (the failed attempt is recorded as a failed job). - Clip URLs are publicly fetchable MP4s (Cloudflare R2) — download and publish them anywhere. MCP drafts require explicit publishing; eligible renders created outside MCP can follow the account's Autopilot settings. - Measured receipts exist only for eligible clips published through Everpop to a connected YouTube channel. The displayed metrics are pulled from the YouTube Analytics API; they are not themselves cryptographically signed. ### When you get a 429 | `code` | `Retry-After` | `retryable` | Do this | |---|---|---|---| | `rate_limited` | 60 | — | Wait, then send the same request again. | | `upload_slots` | 60 | — | 3 uploads are already open: finalize or cancel one (a canceled slot counts until its 15-minute window ends), then retry. | | `queue_capacity` | 180 | `true` | The render queue is full. Retry after the wait. | | `quota_exhausted` | seconds until `resetsAt` | `false` | The monthly allowance is used up. Tell the user `used`, `limit` and `resetsAt`; don't wait it out. | | `upload_cleanup_backlog`, `upload_retention_backlog` | none | `false` | Earlier canceled uploads are still being cleaned up, which can take days. Stop and tell the user. | | `posting_cap` | none | `false` | An Instagram account reached the posting-safety cap (10 posts in a rolling 30 days); nothing was published. Tell the user. | ### Rate limits Per account, per minute. Over the limit: 429 `rate_limited` with `Retry-After: 60`. | Endpoint | Requests per minute | |---|---| | `POST /api/v1/generate` | 10 | | `POST /api/v1/clip` | 10 | | `POST /api/v1/videos/upload` | 20 (one budget with DELETE) | | `DELETE /api/v1/videos/upload` | 20 (one budget with POST) | | `POST /api/v1/videos/complete` | 20 | | `POST /api/v1/videos/import` | 10 | | `GET /api/v1/videos` | 60 | | `GET /api/v1/usage` | 60 | | `GET /api/v1/jobs` | 60 | | `GET /api/v1/jobs/{id}` | 60 | | `GET /api/v1/posts` | 60 | | `GET /api/v1/publish` | 30 | | `POST /api/v1/publish` | 6 | | `GET /api/v1/receipts` | 30 | | `GET /api/v1/campaigns` | 30 | | `POST /api/v1/campaigns` | 10 | | `POST /api/v1/campaigns/{id}/attach` | 30 | | `GET /api/v1/campaigns/{id}/proof` | 30 | ### Error codes | HTTP | `code` | What to do | |---|---|---| | 400 | `bad_request` | Something the request needs is missing (e.g. no connected YouTube channel for import); `error` says what. | | 401 | `key_missing` | Send `Authorization: Bearer epk_...`. | | 401 | `key_invalid` | The key is unknown or was revoked; ask the user for a current key. | | 401 | `key_expired` | The key passed its expiry; the user creates a new one in Dashboard → API. | | 401 | `unauthorized` | What a missing, invalid or expired key answered before 1.1.0. For any 401 code not listed here, the key did not authenticate: ask the user for a current key. | | 402 | `subscription`, `plan`, `payment_required` | See the 402 note above; retrying won't change it. | | 403 | `scope` | A read-only key on a write; the user creates a key with write access. | | 403 | `suspended` | The account is suspended; the user contacts support@everpop.app. | | 403 | `disabled` | Prompt generation is paused. | | 403 | `content_review` | The clip is held for content review. | | 403 | `forbidden` | Another refusal (ownership, the rights answer); `error` says why. | | 404 | `not_found` | That id is not on this account. | | 405 | `method_not_allowed` | Use a method from the `Allow` header. | | 409 | `idempotency_conflict` | That Idempotency-Key was used with different options; use a new key. | | 409 | `clip_removed` | The clip was removed from the library. | | 409 | `upload_not_ready` | Retry `/videos/complete` with the same key. | | 409 | `conflict` | A state change conflicts or is still settling; read `error` before retrying. | | 413 | `file_too_large` | Over 32 GB; re-export smaller or trim. With `reason: "single_put"`: over 5 GB for one PUT — give the user `browserUploadUrl`. | | 422 | `validation_failed` | `issues` names the field. | | 422 | `invalid_cursor` | Pass `nextCursor` back unchanged. | | 422 | `upload_required` | Upload the file (above); `uploadUrl` is the user's own upload page. | | 422 | `generated_source`, `demo_source` | This video cannot be clipped. | | 422 | `unknown_destination` | `destinationIds` lists the ids to re-confirm with the user. | | 422 | `no_eligible_destination` | No requested destination can take this clip. | | 422 | `clip_not_ready` | The clip has no video yet; wait for its job. | | 422 | `rights_unconfirmed` | The clip's source has no rights confirmation; ask the user. | | 422 | `unprocessable` | Another refusal; `error` says why. | | 429 | `rate_limited`, `upload_slots`, `queue_capacity`, `quota_exhausted`, `upload_cleanup_backlog`, `upload_retention_backlog`, `posting_cap` | See "When you get a 429". | | 500 | `internal_error` | Retry once later; tell the user if it repeats. | | 502 | `upstream_error` | A platform (e.g. YouTube) refused; `error` says why. | | 503 | `engine_offline` | See above. | | 503 | `meta_publish_frozen` | Instagram and Facebook publishing is paused for maintenance, and nothing in the request was published. Tell the user and retry after maintenance, or publish now without the Instagram and Facebook destinations. | | 503 | `cleanup_pending` | The cancel is queued and retries on its own. | | 503 | `unavailable` | Briefly unavailable; retry in a few minutes. | ## Campaigns over REST (Pro or Scale) A campaign groups published posts into one payout report a sponsor can open. Campaign Mode comes with Pro and Scale; other accounts get 402 `reason: "plan"`. ```bash # Create. sourceVideoId (optional) is the sponsor's footage in the library: posts published from its clips attach on their own. curl -s -X POST https://everpop.app/api/v1/campaigns \ -H "Authorization: Bearer $EVERPOP_API_KEY" -H "content-type: application/json" \ -d '{"name":"Sponsor S2","cpmCents":200,"sourceVideoId":""}' # → { "ok": true, "data": { "campaign": { "id": "...", "name": "Sponsor S2", ... } } } # Attach published posts (postId values from GET /api/v1/receipts). curl -s -X POST https://everpop.app/api/v1/campaigns//attach \ -H "Authorization: Bearer $EVERPOP_API_KEY" -H "content-type: application/json" \ -d '{"postIds":[""]}' # → { "ok": true, "data": { "attached": 1 } } # The payout report; add ?csv=1 for a spreadsheet. curl -s https://everpop.app/api/v1/campaigns//proof -H "Authorization: Bearer $EVERPOP_API_KEY" # → { "ok": true, "data": { "campaign": { ... }, "items": [ ... ], "totals": { ... }, "estimatedPayoutCents": ..., "publicUrl": "..." } } # List campaigns with post counts, measured views and each report link. curl -s https://everpop.app/api/v1/campaigns -H "Authorization: Bearer $EVERPOP_API_KEY" ``` - Only published posts attach, and a post counts toward one campaign at a time. - `publicUrl` is the report the sponsor opens; the numbers in it are the measured YouTube Analytics windows. ## One full run in bash Upload a file, let the automatic render run, and wait for it. It stops before publishing: that needs the user's explicit confirmation (above). ```bash set -euo pipefail API=https://everpop.app/api/v1 AUTH="Authorization: Bearer $EVERPOP_API_KEY" FILE=episode-42.mp4 SIZE=$(wc -c < "$FILE" | tr -d ' ') SLOT=$(curl -sf -X POST "$API/videos/upload" -H "$AUTH" -H "content-type: application/json" \ -d "{\"filename\":\"$FILE\",\"sizeBytes\":$SIZE}") curl -sf -X PUT "$(jq -r .data.putUrl <<<"$SLOT")" \ -H "content-type: $(jq -r '.data.requiredHeaders["Content-Type"]' <<<"$SLOT")" -H "if-none-match: *" \ --data-binary @"$FILE" # rightsConfirmed is the user's own answer: ask before sending it. DONE=$(curl -sf -X POST "$API/videos/complete" -H "$AUTH" -H "content-type: application/json" \ -d "{\"key\":\"$(jq -r .data.key <<<"$SLOT")\",\"rightsConfirmed\":true}") VIDEO=$(jq -r .data.videoId <<<"$DONE") [ "$(jq -r .data.autoClipping <<<"$DONE")" = true ] || { echo "No automatic render: call POST /api/v1/clip"; exit 1; } until JOB=$(curl -sf "$API/jobs?sourceVideoId=$VIDEO" -H "$AUTH" | jq -re '.data[0].jobId'); do sleep 15; done while STATUS=$(curl -sf "$API/jobs/$JOB" -H "$AUTH" | jq -r .data.status); [ "$STATUS" = PENDING ] || [ "$STATUS" = PROCESSING ]; do sleep 20 done echo "job $JOB: $STATUS" # COMPLETED: show each clip's review, then publish only after the user confirms ``` ## API changes The version is `info.version` in [openapi.json](https://everpop.app/openapi.json), and `info.x-changelog` lists each release. Each entry says what the release added and, under **Changed**, what an existing request now gets back differently. Handle a `code` you do not know by its HTTP status. - **1.3.0** (2026-10-08). **Changed:** `POST /api/v1/clip` and `clip_video` on a video whose strong moments were all clipped already completed `FAILED` with nothing new to clip; they now complete with one clip that reuses the best of them, flagged `repeat_moment` in `qcWarnings`. The first such render of a video in a month hands its video back, so `GET /api/v1/usage` does not count it. Automatic renders keep the old answer. - **1.2.0** (2026-10-01). **Changed:** the upload size limit was 4 GB; it is now 32 GB. `POST /api/v1/videos/upload` and `request_upload` answered 413 `file_too_large` for a file over 4 GB; they now take a file up to 5 GB, the most one PUT can carry. A file over 5 GB and up to 32 GB answers 413 `file_too_large` with `reason: "single_put"` and `browserUploadUrl`: the user uploads it there. Over 32 GB still answers 413 `file_too_large`. **Added:** `browserUploadUrl` on that error body. - **1.1.0** (2026-09-24). **Changed:** a 401 answered `code: "unauthorized"`; it now names its case (`key_missing`, `key_invalid`, `key_expired`). The Instagram posting-safety cap answered 429 `rate_limited`; it now answers `posting_cap`. Every 429 sent `Retry-After: 60`; it now fits the cause, and causes that waiting will not fix send none and carry `retryable: false`. An unsupported method answered an empty 405; it now answers 405 `method_not_allowed` with an `Allow` header. **Added:** errors document their detail fields and codes (including `meta_publish_frozen`); `GET /api/v1/posts` takes `clipId`; the paused generate endpoint is marked deprecated. - **1.0.0** (2026-07-03): first published spec. ## Use it from Claude (MCP connector) OAuth is the recommended setup: add `https://everpop.app/api/mcp/mcp` with no key and Claude walks the user through consent (tokens appear in Dashboard → API → Connected apps, revocable). Everpop also runs a Model Context Protocol server. In Claude's connector settings, choose Add custom connector: URL: https://everpop.app/api/mcp/mcp Clients without MCP OAuth may authenticate with an API key in an HTTP header: URL: https://everpop.app/api/mcp/mcp Header: Authorization: Bearer epk_... Never put an API key in the connector URL. URL query strings can be retained in browser history, server logs, proxy telemetry, and shared screenshots. ### Available tools - `list_videos` — The 20 most recent source videos (detected, API, Drive, or dashboard uploads), newest first, each with `clippable` / `notClippableReason` and `latestJob` (the newest job's id, status and error, or null); pass `nextCursor` as `cursor` for older ones. The result also carries `browserUploadUrl`, the sign-in-gated page where the user uploads a new file themselves (no upload slot needed). - `request_upload` — Exact-size presigned slot for the user's video FILE (sizeBytes is required; PUT bytes yourself with returned requiredHeaders, 15-min validity, ≤5 GB per PUT; files up to 32 GB go through browserUploadUrl). Can't send bytes? Don't request a slot (it counts against the user's open uploads until it expires): give the user `list_videos`' `browserUploadUrl`, then call `list_videos`. - `cancel_upload` — Cancel a failed/abandoned upload slot. A `cleanup_pending` result is durably queued; never cancel after successful or ambiguous finalization. - `finalize_upload` — Turn the uploaded file into a clippable library video; auto-clips for active plans unless `renderMode` is `"manual"` (use it when you will call `clip_video` with your own options); `linkSourceVideoId` attaches it to a parked detection; optional `parked: "quota"` means the file is safe but monthly videos are used up. - `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` after the file is uploaded (`request_upload` → `finalize_upload` with `linkSourceVideoId`). - `clip_video` — Create short clips from one of your source videos; optional `prompt`, `clipCount`, `captionStyle`, `archetype`, `targetSeconds` and `language` (same meanings as REST `/api/v1/clip`); errors carry the REST `status` and `code` (e.g. `upload_required`); returns a jobId. - `get_job` — Check a clip job; holds up to ~20s while the job is still rendering, so one call usually returns the finished job (call again if it is still PROCESSING); returns status, exact connected destinations, and, when COMPLETED, clips with video URLs and clipIds (use a clipId with `publish_clip`). - `publish_clip` — Publish a READY clip to explicitly named destination ids with final title, description, and visibility. Confirm every account and field first — provider publication is not easily undone. - `list_receipts` — Eligible YouTube Shorts' aggregate measured performance (48h & 7d views, retention, likes, subscribers gained) with each post's `postId` and token-protected share links. - `create_campaign` — Create a paid-clipping campaign to group measured clips into one shareable payout report; returns a campaignId. - `list_campaigns` — List your campaigns with post counts, measured views, CPM, and each campaign's public payout-report link. - `attach_to_campaign` — Attach your published posts to a campaign so they count toward its payout report; `postIds` come from `list_receipts` or `campaign_proof` items. A post already in another campaign is moved, removing it from that campaign's report. - `campaign_proof` — A campaign's measured payout report: per-clip 48h/7d numbers, totals, the estimated payout, and the public report link. - `list_jobs` — Your clip jobs, newest first, 20 per page (pass `nextCursor` as `cursor`), each with `jobId`, `sourceVideoId`, `status`, `error` and `clipCountApplied`; pass `sourceVideoId` to find the render `finalize_upload` started. Same data as `GET /api/v1/jobs`. - `list_posts` — Your posts on every platform, newest first, 20 per page (pass `nextCursor` as `cursor`), with each post's status, published URL and the reason it did not go out. Same data as `GET /api/v1/posts`. - `get_usage` — Your plan, videos used and remaining this month with the reset date, clips per video, and whether finishing an upload starts a render on its own. Same data as `GET /api/v1/usage`. (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.) The read-only tools (`list_videos`, `get_job`, `list_receipts`, `list_campaigns`, `campaign_proof`, `list_jobs`, `list_posts`, `get_usage`) declare an `outputSchema` and also return their result as `structuredContent`: the same `{ "ok": true, "data": ... }` object their text content carries.