HomeAI Video ToolsClip Maker API
Developer API

A clip maker API you can point a queue at

The same engine behind the app, exposed as plain HTTP. Send a video URL to one endpoint, receive a job id, then take a signed webhook or poll until the clips are ready. What comes back is a list of finished MP4s with titles, durations, viral scores and permanent download links — no rendering infrastructure of your own.

🎬 Free demo: use a video under 30 minutes · paid plans up to 2 hours
  • POST /clips/generate → job id
  • Signed clips.completed webhook
  • Permanent download manifest
  • Credits metered per source minute
  • Every endpoint has an MCP twin
One long video in, a week of posts out

Paste a link. Get the best moments.

Real ClipSpeedAI output — every clip below was scored, cut, reframed to 9:16 and captioned automatically from the video above it.

https://youtu.be/z_bX3runikk
Source video: Matthew McConaughey's Concerns Over AI Source video 15:27
Matthew McConaughey's Concerns Over AI
9 clips found  ↓  top 5
Matthew McConaughey speaking, captioned vertical clip
Score 92
9:16
Joe Rogan gesturing, captioned vertical clip
Score 90
9:16
Matthew McConaughey listening, captioned vertical clip
Score 89
9:16
Joe Rogan mid-sentence, captioned vertical clip
Score 89
9:16
Matthew McConaughey talking to camera, captioned vertical clip
Score 88
9:16

Integrating in four calls

The whole surface fits on one screen. Base URL is https://api.clipspeed.ai/api/v1.

  1. 1

    Mint a key, then confirm it works

    Generate a key from your dashboard. It looks like csai_live_…, it is displayed exactly once, and only a SHA-256 hash of it is kept on our side, so treat it the way you treat a database password. Send it as X-API-Key or as a standard bearer token — both are accepted. A GET /status costs nothing and confirms three things at once: the key is valid, the plan attached to it, and how many credits are left.

  2. 2

    POST the video and get an id back

    Send url plus whatever you want to control — clip_count, caption_style, aspect_ratio, and a webhook_url if you want to skip polling. The response returns immediately with an id like proj_8f2a1c9e and a status_url, because the work behind it runs for minutes rather than milliseconds and no sane integration holds a socket open that long. Persist that id in your own database in the same transaction that triggered the request.

  3. 3

    Take the webhook, keep the poll as a backstop

    When the render finishes we POST a clips.completed event to your URL carrying the project id and the clip array. Verify the X-ClipSpeedAI-Signature header before you trust the body, acknowledge with a fast 2xx, and do the real work afterwards. Then run a slow reconciliation sweep over your own open jobs anyway — a webhook you never received is a job your users will never hear about again.

  4. 4

    Pull the files and put them where they belong

    Each finished clip carries a video_url, and GET /clips/:id/download/all returns a manifest of every clip in the job with force-download links and sensible filenames derived from the titles. If you would rather stream a single file straight to disk, GET /clips/:id/download/:index issues a 302 to it, which is exactly what curl -L -O wants.

What the API surface actually covers

Nine things worth knowing before you write the first request.

Async by design, with a real job object

Clipping a fifty-minute video is minutes of transcription, scoring and rendering. The API models that honestly: creation returns an id, and the job reports processing, complete or failed. There is no long-lived request to time out behind your load balancer and nothing to retry blindly when a gateway gives up at thirty seconds.

Signed webhooks, not just a callback URL

Every delivery carries an HMAC-SHA256 of the raw request body in X-ClipSpeedAI-Signature. Compute the digest over the bytes you received, not over the object your framework already parsed and re-serialised, and compare in constant time. Non-2xx responses and timeouts are retried with backoff, so make the handler idempotent on the project id.

A download manifest per job

The manifest endpoint hands back the whole job in one payload — index, clip id, title, score, duration, filename and a permanent link served with Content-Disposition: attachment. That is the endpoint to loop over when you are mirroring output into your own bucket, because it saves you reconstructing filenames from titles yourself.

Restyle captions without re-transcribing

POST /captions/restyle re-renders an existing project in a different caption look and reuses the transcript it already has. If you are letting customers A/B a caption style, this is the call that makes it affordable — you are paying to re-render, not to redo the expensive analysis step.

A credit ledger you can reconcile against

One credit equals one minute of source video, and GET /usage/history returns a paginated ledger of debits and credits with the project id attached to each row. If you resell clipping, that ledger is what lets you attribute cost per customer instead of guessing from a monthly total.

Two independent ceilings, stated plainly

Rate limits are counted per key in requests per day and reset at 00:00 UTC; credits are consumed only by work that renders. You can be well inside your request quota and still get a 402 because a batch of long podcasts ate the month, which is why a balance check belongs in front of any bulk enqueue.

One error envelope for everything

Errors always arrive as a typed object, and the interesting ones carry extra fields: insufficient_credits includes credits_remaining and credits_needed, subscription_required includes an upgrade_url you can surface directly to your user. A 503 is transient and safe to retry shortly; a 500 is not, and hammering it will only burn your daily quota.

URLs are validated before anything is fetched

Both the source url and your webhook_url are checked server-side against private and internal address ranges before a single byte is requested. If your integration lets end users paste arbitrary links — and most do — that check is one class of server-side request forgery you do not have to build defences for yourself.

Discovery and scheduling are in the same v1

POST /discover scans a niche and returns a ranked pick with velocity and channel-lift figures, which you can feed straight into a generate call. POST /schedule queues a finished clip to TikTok, Instagram Reels or YouTube Shorts once the account is connected, and GET /platforms tells you which of those a given user has actually linked. Those three are the destinations the product supports end to end, because they all take the same 9:16 file, and the clip scheduler is the page that spells out where that queue stops. Build the posting side of your UI around them rather than around a longer list. Full reference: the developer docs.

Who wires this in

Agencies with many client accounts

One queue, one key per client account, and a ledger row per job to bill against. The manual alternative does not survive the tenth client.

SaaS products adding clips as a feature

Course platforms, webinar tools and community apps already hold their customers’ video. Adding a clip button is one POST and a webhook handler rather than a rendering team.

Media orgs with a back catalogue

Hundreds of archived episodes are a batch job, not a project plan. Enqueue at a rate your credit balance supports and let the webhooks land over a weekend.

Automation platforms and internal tools

An HTTP node in n8n, Make or Zapier plus a webhook catch is a complete integration. No SDK is required because there is nothing here but headers and JSON.

Teams that want clips in their own UI

The response is data, not an embedded player, so the review interface stays yours. Sort by score in your own table and keep your design system intact.

Agent builders

Every endpoint has a tool equivalent, so an agent can drive the same pipeline in plain language. See MCP video clipping for that route.

The integration workflow: design around a job, not a request

The single most common mistake with a rendering API is treating it like a synchronous function that happens to be slow. It is not. A job is a durable object with a lifecycle, and your side of the integration needs a row in a table that mirrors it: the id we returned, the customer it belongs to, the state you last observed, and the time you last checked. Once that row exists, everything else becomes ordinary — retries are safe, a restart loses nothing, and a support question about a missing clip has an answer.

Treat the webhook as the fast path and the polling sweep as the thing that makes the whole integration dependable. Callbacks fail for reasons outside anyone’s control: a deploy at the wrong second, a proxy that swallows the request, a certificate that quietly expired. A sweep that looks for jobs older than a threshold and still open costs one request each and turns a class of silent failure into a delay of a few minutes.

Write the handler so a duplicate delivery is harmless. Retried callbacks are a feature of any webhook system worth using, and the cheapest defence is a uniqueness constraint on the project id rather than clever logic.

Budget in minutes of source, not in clips

Cost tracks the input, not the output. A ninety-minute interview costs the same whether you ask for five clips or fifteen, because the expensive part is reading the ninety minutes. That changes how you shape a bulk run: batching forty hour-long episodes is roughly two thousand four hundred credits before you have looked at a single result, so check the balance first and fail the batch loudly rather than discovering the ceiling at episode nineteen.

It also changes what you charge for, if you are reselling. Per-clip pricing looks natural to a customer and inverts your own cost curve. Pricing on source duration keeps your margin flat across a customer who wants three clips from a short talk and one who wants twenty from a marathon stream.

Rate limits are the other ceiling, and they are the friendlier of the two: they are per key, counted daily, and reset on the UTC boundary. Space a large enqueue over the day rather than firing everything in one loop, and handle 429 by waiting for the rollover instead of retrying immediately.

Mistakes that surface after the first hundred jobs

Polling every two seconds. It does not make a render finish sooner, it eats the daily request allowance that your actual traffic needs, and it turns one busy afternoon into a 429 that blocks new submissions. Thirty to sixty seconds is the interval the endpoint is designed for, and an exponential backoff on top of that costs you nothing.

Collapsing a 402 into a generic error. The payload tells you exactly how many credits were available and how many the job required, which is the difference between a user seeing "something went wrong" and a user seeing that a ninety-minute upload needed more headroom than the account had. One of those produces a support ticket and the other produces an upgrade.

Firing an entire archive in a single loop. The daily allowance resets on the UTC boundary, not on your local midnight, so a batch kicked off in the evening can hit the ceiling halfway through and leave you unsure which half went out. Meter the enqueue and record each submission as you make it.

Assuming the number of clips you asked for is the number you will get. A short or sparse source legitimately returns fewer, so any UI that renders a fixed grid of ten placeholders will look broken on perfectly good output.

Storing only the link. The download URLs are durable, but your product should not depend on somebody else's storage for an asset your customer thinks they own. Copy the file into your own bucket as part of the completion handler and keep the original link as a fallback.

Troubleshooting an integration that is dropping jobs

A key that worked yesterday and returns 401 today has usually been rotated, revoked, or copied with a trailing newline by whatever pasted it into your secret store. Trim it and retry before you suspect anything deeper. If the plaintext is genuinely gone there is nothing to recover — only a SHA-256 hash of it exists on our side — so the fix is to mint a replacement and deploy that, not to open a ticket asking us to read the old one back.

A source URL that opens perfectly in your browser but comes back rejected is almost always one of two things. Either it resolves to a private or internal address and the pre-fetch validation refused it, or it only works because your browser is carrying a session cookie. The fetch happens server-side with no session, so a link behind a login will fail no matter how well it renders for you; issue a signed public link from your object storage instead.

Signature verification that fails on every single delivery is not a key problem, it is a body problem. Frameworks that parse JSON before your handler sees it hand you an object, and re-serialising that object changes key order and whitespace, which changes the digest. Capture the raw bytes at the point the request arrives — in Express that means the verify hook on the body parser — and compute the HMAC over those.

A job still reporting processing well past the usual window is worth a GET before it is worth alarm, because queue depth and source length both move that number and the status endpoint is the only authoritative answer. What should worry you is the opposite shape: an open-jobs table whose oldest row keeps getting older. That is a reconciliation sweep that is not running, and it is the failure that hides longest.

Downloads that return what looks like an empty file are usually a client that was not told to follow redirects. The per-clip endpoint answers with a 302 to the asset rather than streaming the bytes itself, so curl needs -L. If you would rather not deal with redirects at all, read the manifest instead and fetch the direct links it lists.

Generation settings, and the export shapes worth deciding up front

Four parameters do almost all of the work: url, clip_count, aspect_ratio and caption_style. Of those, only the first is load-bearing. clip_count is a target rather than a contract — a sparse source returns fewer and that is correct behaviour, not a bug — so treat the number you send as an upper bound and build the UI to render whatever length of array arrives.

aspect_ratio is the one that catches people, because a job produces one shape. Ask for 9:16 and you get vertical files; if the same source also needs a 1:1 for a feed placement or a 16:9 for a site embed, that is a second submission and a second charge against the same minutes. Most people wire the ratio to a global config value and then discover a customer who wants both, so it is worth exposing per-request from day one even if your first release only ever sends vertical.

caption_style is the cheap decision to change and the expensive one to change badly. The six documented presets are karaoke, hormozi, beasty, fire, youshaei and cinematic, and the restyle endpoint re-renders an existing project in a different look while reusing the transcript it already produced. That distinction is the whole reason the endpoint exists: transcription and scoring are the costly pass, and burning different word-by-word captions over an existing cut is not.

On export: the durable link in the payload is a convenience, not a storage strategy. Say you run a course platform and clips are a feature customers pay for — mirror every file into your own bucket inside the completion handler, key it by your own clip id, and keep our link as a fallback rather than as the primary. Source length is capped at two hours per submission on a paid plan, so anything longer needs splitting before it reaches the queue, and the split points are your decision because they are editorial ones.

Doing it by hand, and the other options on the table

The honest baseline is a person in the dashboard. For a handful of videos a week it costs nothing to build, produces better selection than an unattended queue because a human is judging, and needs no error handling. Work out how many jobs a week justify the integration before you write any of it: the crossover is not about volume alone but about who triggers the work. The moment the trigger is an RSS item, a customer button or a nightly sweep rather than a person remembering, hand-driving stops being an option at any volume.

Rolling your own on ffmpeg plus a transcription model is the other serious choice, and for some teams it is the right one. It turns out the transcript is the easy half. What consumes the quarter is everything downstream: keeping caption timing glued to the words through a re-encode, deciding cut points that land on sentence boundaries instead of on silence, following the active speaker so a two-person shot does not centre-crop into the gap, and running a render fleet that does not fall over when four customers upload at once.

Generic transcoding and media APIs are a different category rather than a competitor. They execute the operation you name — crop this, burn that subtitle track, resize to these dimensions — flawlessly and cheaply. None of them will tell you which forty seconds of a two-hour recording is worth publishing, and if your product needs that judgement you are buying the wrong layer. Conversely, if you already know your timecodes, you do not need anything on this page.

For example, a team that only ever clips a fixed pre-roll and post-roll off webinar recordings should use a transcoder and save the money. In practice the question to ask is whether the interesting decision in your product is which moment or which encoding. If it is the encoding, this is not the API you want, and the clip scheduler is probably not either — you want a pipeline that takes orders, not one that has opinions.

What v1 does not do

It does not take a multipart file upload. The generate endpoint wants a URL it can fetch, so if your users hold local files you will need somewhere to put them first — a signed link from your own object storage is the usual answer, and it works fine because the fetch happens server-side. For one-off local files, the web app is the shorter path.

There is no idempotency key today. A retried POST creates a second job and spends the credits twice, so deduplicate on your side: record your intent before the call, and treat a request whose response you never saw as needing a lookup rather than a resend.

Real-time clipping of a broadcast is not a v1 REST flow. Live capture is driven from the app and from the MCP connector, because a live session is a long-running subscription with start, extend and stop semantics rather than a single job — see the YouTube live clipper for how that side works.

And there is no AI video generation anywhere in the product. Nothing here invents footage, generates B-roll, or synthesises a voice. Every frame the API returns came from the video you sent it.

What integrations actually break on, in production

Observations from operating the pipeline in production — not general advice.

The daily quota is spent on polling, not on clipping

Rate limits count requests per key per UTC day; credits count minutes of source. Those are different currencies, and the one people exhaust first is almost never the one they budgeted for. A job that renders for twenty minutes polled every two seconds is about six hundred requests; the same job polled once a minute is twenty. That is the reason a modest integration can hit a 429 while barely touching its credit balance, and why the webhook exists at all.

A dropped callback and a broken renderer look identical from your side

Silence carries no information. A webhook that was never delivered, a handler that 500ed, a proxy that ate the request and a job that genuinely failed all present to your application as a row that never changed state. Only the job object knows which happened, which is why the reconciliation sweep is not belt-and-braces engineering — it is the single thing that converts an unbounded silent failure into a delay measured in minutes.

Without an idempotency key, a blind retry is a duplicate invoice

Credits meter on the source at one per minute, and v1 has nothing that deduplicates a repeated POST. Put those two facts together and a generic retry wrapper — the kind that transparently re-sends any request that timed out — will spend ninety credits a second time on a ninety-minute file and hand your user two identical jobs. In practice this is the most expensive mistake on the list, because it bills quietly and only shows up when someone reconciles the ledger.

Compared with the alternatives

vs. building it on ffmpeg and a transcription model

The first version of that is a weekend and it genuinely works. The version that survives contact with real footage is not: speaker-aware cropping, caption timing that stays glued through a re-encode, cut points that respect sentence boundaries, and a render farm that does not fall over when four customers upload at once. The build is not the transcript — it is everything after it.

vs. a generic transcoding or media API

Transcoding services execute the operation you specify. They will crop, burn a subtitle track and resize on command, but nothing in them decides which forty seconds of a two-hour recording is worth publishing. That judgement is the part being sold here; the encoding is table stakes.

vs. having a human drive the dashboard

For a handful of videos a week that is fine and cheaper. It stops working the moment output has to be triggered by something other than a person remembering — a new episode landing in an RSS feed, a customer clicking a button in your product, a nightly job over yesterday’s uploads.

vs. the MCP connector

Same engine, different control surface. MCP is better when a human is in the loop and the next step depends on what came back; the REST API is better when the flow is fixed and nobody is watching. Plenty of teams use both — an agent to explore, a cron to run the thing that works.

Frequently asked questions

How do I authenticate a request?
Pass your key as an X-API-Key header, or as Authorization: Bearer if that fits your HTTP client better — both forms are accepted on every endpoint. A key is bound to one account and inherits that account’s plan, credit balance and daily request ceiling.
Where do I get an API key?
Generate one from the API key section of your dashboard. The plaintext value appears once at creation and is never shown again, because we store only a SHA-256 hash of it. You can rotate or revoke a key from the same screen at any time.
Do I need a paid plan to use the API?
Yes. Minting a key and calling any endpoint that renders requires an active paid plan, and the $1 three-day trial counts. Accounts without a plan receive a 403 with the type subscription_required and an upgrade_url in the payload. Read endpoints against your own data stay available so an agent can always show a user where to upgrade.
What does one job cost?
Credits are metered against the source: one credit per minute of the video you submit. A forty-two-minute episode costs forty-two credits whether it produces four clips or fourteen, because the analysis pass over the full runtime is where the work is.
What is the difference between credits and rate limits?
They are separate ceilings that fail differently. Rate limits cap how many requests a key may make in a UTC day and produce a 429 when exceeded. Credits cap how much video you can render in a billing cycle and produce a 402. Both are visible from a single GET /status call.
How long does a job take to finish?
Typically in the range of ten to thirty minutes, driven mostly by source length and current queue depth. Poll no more often than every thirty to sixty seconds — faster polling does not make the render finish sooner and it does eat your daily request quota.
Should I poll or use a webhook?
Use the webhook as your primary path because it removes the latency of the polling interval entirely. Keep a low-frequency sweep over jobs that have been open too long as insurance. Relying on callbacks alone means one dropped delivery becomes a job that sits unfinished forever.
How do I verify the webhook signature?
Compute an HMAC-SHA256 over the raw request body, keyed on the project id, and compare it to the X-ClipSpeedAI-Signature header using a constant-time comparison. The common bug is hashing a re-serialised copy of the JSON rather than the exact bytes that arrived, which changes whitespace and breaks the digest.
What happens if my webhook endpoint is down?
Deliveries that return a non-2xx status or time out are retried with backoff. Acknowledge quickly with a 2xx and push the actual processing onto a queue, since a handler that does thirty seconds of work before responding will look like a failure and get replayed.
Can I upload a file instead of passing a URL?
The generate endpoint takes a URL it can reach over public HTTP or HTTPS. For files your users hold locally, put them in your own object storage and pass a signed link; the fetch happens on our side, so the link only needs to be reachable from the internet, not from the browser.
Is there an idempotency key?
Not in v1. A repeated POST is treated as a new job and will spend credits again, so deduplication is your responsibility. Record the intent before you send the request, and if a response is lost in flight, look the job up rather than resubmitting.
How many clips will a job return?
clip_count sets the target and defaults to ten. It is a target rather than a promise, because the engine returns the moments that are actually worth posting instead of padding a short source to hit a number. A dense hour of conversation will comfortably fill the request; a thin twenty minutes may not.
Which aspect ratios can I request?
Pass aspect_ratio as 9:16, 1:1 or 16:9. Vertical is the default because that is what short-form feeds expect. If you need more than one shape from the same source, submit the job again with a different ratio.
What caption styles does the API expose?
The documented set is karaoke, hormozi, beasty, fire, youshaei and cinematic. Pass one as caption_style at generation time, or change it later on an existing project through the restyle endpoint without paying for a fresh transcription.
Are the download links permanent?
Yes — the manifest returns durable links rather than short-lived signed URLs, so you can store them alongside your own records. Mirroring the files into your own bucket is still the right call if you need them to survive independently of your account.
Can I schedule posts through the API?
Yes, to the same three destinations the app publishes to: TikTok, Instagram Reels and YouTube Shorts. Call GET /platforms to see which of them the user has connected, then POST /schedule with a clip id, one or more platform ids and an optional publish time. A queued post can be cancelled with a DELETE while its status is still scheduled; once it has started sending you get a 409.
Can the API post to LinkedIn, X or Facebook?
No — publishing is scoped to the vertical short-form destinations described on the clip scheduler, and those are the ones supported end to end. Do not design a posting flow that depends on a business network arriving later. If one belongs in your customer's calendar, pull the finished MP4 from the download manifest and hand it to a general-purpose scheduler, which is the arrangement most teams running both already have.
Can the API pick a video for me?
POST /discover scans a niche over a freshness window and returns a ranked pick with its view velocity and how far above that channel’s norm it is running, plus the runners-up. The pick’s URL drops straight into a generate call, which makes an entirely unattended find-and-clip loop possible.
What are the exact rate limits?
They scale with plan and are counted per key per UTC day. The current table lives in the developer docs and that table is the authority — a ceiling quoted on a marketing page ages badly. Exceeding it returns rate_limit_error and clears at the day boundary.
Which errors should I handle explicitly?
At minimum: 401 for a bad key, 402 for exhausted credits, 403 for a missing plan, 429 for the daily quota, and 503 as a transient you can retry after a short pause. Everything arrives in the same envelope with a type field, so a switch on that string covers the whole surface.
Can I clip a live stream through the REST API?
Live capture runs from the app and the MCP connector rather than the v1 clipping endpoints, because a broadcast is a session you start, extend and stop rather than a fixed-length file. If real-time is the requirement, start with the live clipping page and then talk to us about the integration.
Does the response include the transcript?
The documented job payload gives you per-clip title, viral score, duration and video URL — enough to build a review UI without touching the media. If you need fields beyond that, check the endpoint reference in the docs before designing around an assumption.
Is there an official SDK?
There is no SDK to install and none is needed: the whole thing is JSON over HTTP with one header, so whatever your language already has for requests is sufficient. The npm MCP package exists if you want the agent-facing wrapper instead.
Will clips generated through the API have a watermark?
No. Watermarks apply to the free in-app demo; API access requires a paid plan or the trial, so what the endpoint returns is a clean export. Your own logo can be applied deliberately through the Brand Kit if you want it there.
How do I test without burning credits?
Status and usage calls do not consume credits, so wire the auth and error paths first against those. When you are ready to render, run one short video end to end rather than a batch — a five-minute source is five credits and exercises exactly the same code path as a two-hour one.
What happens when the account runs out of credits?
The generate call returns 402 with the type insufficient_credits and includes both how many credits remain and how many the job needed, plus an upgrade link. Surface those numbers to your user rather than a generic failure — they turn a dead end into an obvious next step.
Can several teammates share one key?
A key belongs to a single account and inherits that account’s plan and limits, so sharing one means sharing a rate limit and a credit pool with no attribution between people. For a team, a dedicated service account with a rotated key is cleaner than passing a personal key around.
How long can a source video be?
Paid plans accept up to two hours per submission. Longer recordings need splitting before submission. The free in-app demo, which is for evaluating quality rather than for integration work, is limited to thirty minutes.
Is my source video stored or published anywhere?
It is processed to produce your clips and is not posted anywhere by us. Nothing is published on a user’s behalf unless a scheduling call explicitly asks for it. Details of retention and handling are in the privacy policy.
Can I use this from a no-code automation tool?
Yes, and it is a good fit. A generic HTTP node with a JSON body plus a webhook trigger to catch the completion event is a whole integration in most of those platforms, with no glue code to host.
How do I try it before committing?
Start the $1 three-day trial, mint a key, and run a real video through it — the API behaves identically on the trial. Cancelling takes one click, and we email before the trial converts so nothing renews quietly.

Ship your first job in one POST

Mint a key, send a URL, catch the webhook. The full endpoint reference and copy-paste curl examples are in the developer docs.

⚡ Get A.I Clips — $1 trial
3-day trial · just $1 · cancel anytime