Make videos from code or from Claude.
Connect Claude, ChatGPT or Cursor in a minute, or call the REST API from your own code. Same models, same credits, same results as the app.
Start with AI
Let your coding agent build it. You approve every spend.
Copy one prompt into Claude Code, Codex, Cursor, Claude or ChatGPT. It points your AI at the docs, keeps your key in CLIPPIE_API_KEY and checks the cost with you before anything is spent.
Paste it into any AI assistant. The shortcuts open with the prompt typed in; nothing is sent until you press enter.
https://api.clippie.ai/mcpThe MCP server URL. Paste it into your AI client and sign in with your Clippie account.
What you can build. Everything Clippie makes, one call away.
AI Story videos
A topic or a script in, a finished narrated video out: an AI image for every scene, a voice, captions and music. Keep it editable in Clippie or get the MP4.
create_ai_story_videowrite_scriptrender_videoClippie Recast
Put the person in any photo into a trending clip. Pick a motion template, send the photo, get the video back.
recast_videolist_motion_templatesAI video and image models
Seedance, Veo, Genjutsu, Flux, Imagen, Seedream and Nano Banana behind one API, at the same credit prices as AI Studio.
generate_videogenerate_imageupscaleText to speech
Clippie voices and your own cloned voices, returned as an MP3 with word timings for captions.
text_to_speechlist_voicesCaptions and transcripts
Words with timings, SRT and VTT from any video or audio file, in more than 100 languages.
transcribelist_caption_stylesEverything around it
Catalogs of voices, styles, music and footage, file uploads, job history and your credit balance, so an agent can plan before it spends.
get_accountestimate_costupload_file
Connect your AI. Paste one URL, sign in, approve.
Claude, ChatGPT, Cursor and VS Code sign in with OAuth. Your assistant checks the price and asks you before anything spends credits.
Connect Clippie to your AI
Cursor and VS Code open with Clippie ready to add. Claude and ChatGPT open their settings with the URL copied. Every client signs in with your Clippie account.
Or set it up by hand
Claude (web and desktop)
- Open Customize, then Connectors.
- Choose + then Add custom connector, name it Clippie and paste the server URL.
- Click Connect, sign in to Clippie and allow access.
https://api.clippie.ai/mcpClaude Code
- Run this once in your terminal.
- Inside Claude Code, run
/mcp, pick clippie and sign in.
claude mcp add --transport http clippie https://api.clippie.ai/mcpCursor
- Add Clippie to
~/.cursor/mcp.json, or to.cursor/mcp.jsonin a project. - Cursor opens a Clippie sign-in the first time it connects.
{
"mcpServers": {
"clippie": {
"url": "https://api.clippie.ai/mcp"
}
}
}VS Code
- Add Clippie to
.vscode/mcp.jsonin your workspace, or run MCP: Add Server from the command palette. - Start the server from the file and sign in to Clippie when VS Code asks.
{
"servers": {
"clippie": {
"type": "http",
"url": "https://api.clippie.ai/mcp"
}
}
}ChatGPT
- Open Settings, then Apps.
- Under Advanced settings, turn on Developer mode.
- Choose Create app, paste the server URL, choose OAuth and sign in to Clippie.
https://api.clippie.ai/mcpClients that send a fixed header
- Create a key in Settings, API. It starts with
clp_pat_and is shown once. - Send it as
Authorization: Bearer clp_pat_…instead of signing in.
claude mcp add --transport http clippie https://api.clippie.ai/mcp \
--header "Authorization: Bearer clp_pat_..."{
"mcpServers": {
"clippie": {
"url": "https://api.clippie.ai/mcp",
"headers": { "Authorization": "Bearer clp_pat_..." }
}
}
}{
"inputs": [
{ "type": "promptString", "id": "clippie-key", "description": "Clippie API key", "password": true }
],
"servers": {
"clippie": {
"type": "http",
"url": "https://api.clippie.ai/mcp",
"headers": { "Authorization": "Bearer ${input:clippie-key}" }
}
}
}curl https://api.clippie.ai/mcp \
-H "Authorization: Bearer $CLIPPIE_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'Or call the REST API. One request makes a video.
Create a key in Settings, then send it as Authorization: Bearer clp_pat_… to https://api.clippie.ai/v1.
- 01
Create the video
POST /v1/videos/ai-storyanswers202with a job straight away. Send anIdempotency-Keyso a retry can never charge twice. - 02
Wait for the job
GET /v1/jobs/:id?wait=30holds the request until the job changes, so you never poll in a tight loop. The finished job has the MP4 and an editor link. - 03
Or get a webhook
Pass a
webhookUrland Clippie postsjob.completedorjob.failedto it, signed with your secret.
# 1. Create the video. Send the same Idempotency-Key if you retry,
# so a retry returns the first job instead of charging twice.
# Add "dryRun": true to see the exact cost without spending anything.
curl https://api.clippie.ai/v1/videos/ai-story \
-H "Authorization: Bearer $CLIPPIE_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 5d1c0e2a-7c4f-4a51-9b1e-2f0c6f1d9a77" \
-d '{
"prompt": "The lost library of Alexandria",
"aspectRatio": "9:16",
"durationSeconds": 60,
"webhookUrl": "https://example.com/clippie-webhook"
}'
# => 202 { "job": { "id": "job_...", "status": "queued", ... } }
# 2. Wait for it. ?wait= holds the request open for up to 50 seconds.
curl "https://api.clippie.ai/v1/jobs/job_...?wait=30" \
-H "Authorization: Bearer $CLIPPIE_API_KEY"
# => { "job": { "status": "completed", "output": { "videoUrl": "...", "editorUrl": "..." } } }import { randomUUID } from 'node:crypto';
const API = 'https://api.clippie.ai/v1';
const auth = { Authorization: `Bearer ${process.env.CLIPPIE_API_KEY}` };
const video = { prompt: 'The lost library of Alexandria', aspectRatio: '9:16', durationSeconds: 60 };
// Check the cost first. A dry run spends nothing.
const dry = await fetch(`${API}/videos/ai-story`, {
method: 'POST',
headers: { ...auth, 'Content-Type': 'application/json' },
body: JSON.stringify({ ...video, dryRun: true }),
}).then((res) => res.json());
console.log(dry.estimate); // { credits, minutes, wouldSucceed, reason }
// Make one key per video and reuse it on retries, so you are never charged twice.
const idempotencyKey = randomUUID();
let { job } = await fetch(`${API}/videos/ai-story`, {
method: 'POST',
headers: { ...auth, 'Content-Type': 'application/json', 'Idempotency-Key': idempotencyKey },
body: JSON.stringify(video),
}).then((res) => res.json());
// Long-poll: each call waits up to 30 seconds for the job to change.
while (!['completed', 'failed', 'canceled'].includes(job.status)) {
({ job } = await fetch(`${API}/jobs/${job.id}?wait=30`, { headers: auth }).then((res) => res.json()));
}
console.log(job.status, job.output?.videoUrl, job.output?.editorUrl);import os, uuid, requests
API = "https://api.clippie.ai/v1"
auth = {"Authorization": f"Bearer {os.environ['CLIPPIE_API_KEY']}"}
video = {"prompt": "The lost library of Alexandria", "aspectRatio": "9:16", "durationSeconds": 60}
# Check the cost first. A dry run spends nothing.
dry = requests.post(f"{API}/videos/ai-story", json={**video, "dryRun": True}, headers=auth).json()
print(dry["estimate"])
# Make one key per video and reuse it on retries, so you are never charged twice.
idempotency_key = str(uuid.uuid4())
job = requests.post(
f"{API}/videos/ai-story",
json=video,
headers={**auth, "Idempotency-Key": idempotency_key},
).json()["job"]
# Long-poll: each call waits up to 30 seconds for the job to change.
while job["status"] not in ("completed", "failed", "canceled"):
job = requests.get(f"{API}/jobs/{job['id']}", params={"wait": 30}, headers=auth, timeout=60).json()["job"]
print(job["status"], (job.get("output") or {}).get("videoUrl"))Verify the webhook. Before you trust the body.
Your signing secret (whsec_…) is in Settings, API. Check Clippie-Signature against the raw body, reject anything older than five minutes, and dedupe on Clippie-Job-Id plus the event, since a delivery can arrive twice.
import { createHmac, timingSafeEqual } from 'node:crypto';
// header: the Clippie-Signature header, "t=<unix>,v1=<hex>"
// rawBody: the request body exactly as received, before JSON parsing
// secret: your whsec_... signing secret from Settings > API
export function verifyClippieWebhook(rawBody, header, secret, toleranceSeconds = 300) {
const parts = Object.fromEntries(header.split(',').map((part) => part.trim().split('=')));
const timestamp = Number(parts.t);
if (!Number.isInteger(timestamp) || !parts.v1) return false;
if (Math.abs(Date.now() / 1000 - timestamp) > toleranceSeconds) return false;
const expected = createHmac('sha256', secret).update(`${timestamp}.${rawBody}`).digest();
const given = Buffer.from(parts.v1, 'hex');
return given.length === expected.length && timingSafeEqual(given, expected);
}import hashlib, hmac, time
# header: the Clippie-Signature header, "t=<unix>,v1=<hex>"
# raw_body: the request body bytes exactly as received
# secret: your whsec_... signing secret from Settings > API
def verify_clippie_webhook(raw_body: bytes, header: str, secret: str, tolerance: int = 300) -> bool:
parts = dict(part.strip().split("=", 1) for part in header.split(",") if "=" in part)
try:
timestamp = int(parts.get("t", ""))
except ValueError:
return False
if abs(time.time() - timestamp) > tolerance:
return False
signed = f"{timestamp}.".encode() + raw_body
expected = hmac.new(secret.encode(), signed, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, parts.get("v1", ""))See the cost first
Add
"dryRun": trueto any create call, or callPOST /v1/estimate. You get the exact credits and minutes, and nothing is spent.Retries are safe
Replaying an
Idempotency-Keywithin 24 hours returns the first job. The same key with a different body is a409.Signed webhooks
Every delivery carries
Clippie-Signature: t=…,v1=…, an HMAC-SHA256 of the timestamp and body, retried for about a day.Typed errors and limits
402 insufficient_credits,403 subscription_required,429withRetry-After. 120 requests a minute and 5 running jobs per account.
Every tool, one registry. The same actions over MCP and REST.
Tools that spend credits or minutes say so, and run the same checks and prices as the app. The full request and response schemas are in the OpenAPI spec.
Create
- generate_imageSpends credits
Generates 1-4 images with an AI Studio model (Nano Banana, Seedream, Flux, Imagen). Spends credits: about 6 credits for one 1-megapixel Nano Banana image; bigger sizes, more images and premium models cost more (list_models has every price). Run with dryRun: true (or estimate_cost) first and confirm the cost. Returns a job; get_job with waitSeconds returns the image URLs, usually within a minute.
POST /v1/ai/images
- generate_videoSpends credits
Generates a short AI video clip with an AI Studio model: Seedance and Veo from text or images, Clippie Recast and Genjutsu from a source video (referenceVideoUrl or motionTemplateId) plus photos. Spends credits, from tens to hundreds a clip depending on model, length and resolution (list_models has the prices). Run with dryRun: true (or estimate_cost) first and confirm the cost. Returns a job; clips take 1-10 minutes, so use get_job with waitSeconds.
POST /v1/ai/videos
- recast_videoSpends credits
Clippie Recast: puts the people in your photos into a trending motion template (list_motion_templates), keeping its moves, camera and sound. Send one photo per person in the template. Spends credits by the template's length: about 413 credits for a 10-second clip at 720p; 1080p costs more. Run with dryRun: true (or estimate_cost) first and confirm the cost. Returns a job; recasts take a few minutes, so use get_job with waitSeconds.
POST /v1/ai/recast
- upscaleSpends credits
Upscales an image (2x-6x) or a video (to 720p, 1080p or 4K) with Topaz. Spends credits: about 7 for a 2x image (more at 4x and 6x) and 155 for a video of up to 30 seconds to 1080p at 60 fps. The price follows the real file: bigger images, longer videos (up to 10 minutes) and 4K cost more. Run with dryRun: true (or estimate_cost) first and confirm the cost. Images finish within the call; videos return a running job, so use get_job with waitSeconds.
POST /v1/ai/upscale
- text_to_speechSpends credits
Turns text into an mp3 narration with a Clippie voice or one of your cloned voices, with word timings. Spends voiceover minutes for the audio's length (about 150 words a minute), and the same in caption minutes for the word timings. Finishes within the call: the job comes back completed with audioUrl and captions.words.
POST /v1/ai/speech
- transcribeSpends credits
Transcribes an audio or video file (up to 30 minutes) into punctuated text, word timings, and SRT and WebVTT captions split at sentence ends. Spends caption minutes for the file's length. Finishes within the call: the job comes back completed with captions.words, captions.srt and captions.vtt.
POST /v1/ai/transcribe
- create_ai_story_videoSpends credits
Makes a narrated AI Story video (script, voiceover, scene images, captions, music) and renders it to MP4. Give one of prompt (a script is written to fill durationSeconds, 30-300, default 60), script, or voiceoverFileId. Spends minutes, not credits: about 1 voiceover, 1 caption and 1 export minute per minute of video (render: false skips the export minutes and returns an editable project). Run estimate_cost (or dryRun: true) first and confirm the cost. Takes a few minutes: wait with get_job (waitSeconds). At most 3 videos are made at once per account. The result has videoUrl and editorUrl.
POST /v1/videos/ai-story
- render_videoSpends credits
Renders an AI Story project you own to MP4: one made with create_ai_story_video (render: false) or in the Clippie editor. Spends export minutes for the video length (1 per minute of video). Run estimate_cost (or dryRun: true) first. Projects with placeholder scene images are refused: regenerate those scenes in the editor first.
POST /v1/videos/:projectId/render
- cancel_jobCreate
Cancels a job that is still queued and refunds what it was charged. Jobs that have started cannot be canceled.
POST /v1/jobs/:id/cancel
- upload_fileCreate
Imports an image, video or audio file from a public https URL (up to 100 MB) so other tools can use it as fileId. REST callers can also send the file itself as multipart/form-data (field "file").
POST /v1/files
- write_scriptCreate
Writes a narration script for a short video from a topic, with the AI Story editor's writer, a theme, a tone and a target length. Free: spends no credits or minutes. Finishes within the call: the job comes back completed with output.script. Pass the script on to text_to_speech or create_ai_story_video.
POST /v1/ai/scripts
Read
- get_accountRead
Shows the user's Clippie plan, AI credit balance (plan and top-up), the voiceover, caption and export minutes left, when the period ends and whether videos are watermarked. Call this first, and before anything that spends.
GET /v1/me
Lists credit movements (top-ups, plan credits, generations, refunds) and minute spends, newest first, each linked to its API job when there is one.
GET /v1/credits/history
- list_voicesRead
Lists narration voices: the user's own cloned voices first, then the popular voices, then the rest. Filter with search (name, accent, style), gender, language or mine. Pass a voice's id as voiceId.
GET /v1/voices
Lists the burned-in caption styles (font, colours, one word at a time or lines). Pass an id as captionStyleId.
GET /v1/caption-styles
- list_art_stylesRead
Lists the looks an AI Story video can have. Either pass a type "style" id as artStyleId, or pass one of imageModels as imageModel together with a type "stylePrompt" id as stylePromptId. Direct-model scene images are included on paid plans.
GET /v1/art-styles
Lists ready-made AI Story formats (an art style plus a frame shape, e.g. "History documentary" 16:9). Pass an id as storyTemplateId to set the look and aspect ratio in one go.
GET /v1/story-templates
Lists the trending motion clips used by Clippie Recast and motion-control video models, in the same order as AI Studio (newest hand-picked uploads first, then by trend). Pass an id as motionTemplateId. Each template says its length and whether Recast accepts it (recastCompatible); offer only those for recast_video.
GET /v1/motion-templates
- list_modelsRead
Lists the AI Studio video and image models with their resolutions, aspect ratios, durations and credit price per generation (images: per image). Use an id as model for generate_video / generate_image.
GET /v1/models
Lists the gameplay and satisfying background clips (Minecraft parkour, Roblox, ...) used behind story videos.
GET /v1/background-videos
- list_musicRead
Lists background music tracks, popular first. Tracks with hasCopyrightWarning may be muted on some platforms. Pass an id as musicId.
GET /v1/music
Lists the short sound effects (whoosh, bell, punch, ...) that can be placed on a video timeline.
GET /v1/sound-effects
- list_languagesRead
Lists the languages for captions, transcription and narration. Pass a code as language.
GET /v1/languages
- list_jobsRead
Lists the jobs started through the API or MCP, newest first, with their status, output and what they cost. Filter by status or kind.
GET /v1/jobs
- get_jobRead
Gets one job: status (queued, processing, rendering, completed, failed, canceled), step, progress, output (videoUrl, imageUrls, audioUrl, captions, editorUrl) and cost. Pass waitSeconds (up to 50) to wait for it to finish instead of polling in a loop.
GET /v1/jobs/:id
- estimate_costRead
Shows what a create tool would charge (credits and voiceover, caption and export minutes) and whether it would go through, without spending anything. Pass the tool name and the same input you would send it. Confirm the cost with the user before creating.
POST /v1/estimate
- get_fileRead
Gets a file uploaded with upload_file: its type and URL.
GET /v1/files/:id
Requires a paid plan
Included in every paid plan. No API surcharge.
API keys and connected apps need an active subscription. Everything you make comes out of the same credits and minutes as the app, at the same prices, and lands in your Clippie library.


