Error fix
The OpusClip API allows 30 requests a minute per key and 4 running projects on Pro Beta and Max, then answers 429. Past 900 credits in a month it answers 403. clipsdk bills $0.03 per source minute with no monthly cap.
OpusClip API 429 Too Many Requests and the monthly API cap
Three answers look alike and need different fixes: a plain 429 (too many requests this minute), a 429 with X-Cap-Reason: concurrent (too many projects running) and a 403 with API_MONTHLY_CAP_REACHED (the month is used up).
Updated
Or one API call
$0.03per source minute
- Every clip included, up to 1080p60 and 20 Mb/s
- $1 free to start, 33 minutes of video
- Prepaid credit, no subscription
What OpusClip sends back
POST https://api.opus.pro/api/clip-projects
429 Too Many Requests
429 Too Many Requests, X-Cap-Reason: concurrent
403 Forbidden
{
"code": "API_MONTHLY_CAP_REACHED",
"reset_at": "2026-06-01T00:00:00Z",
"upgrade_url": "https://www.opus.pro/contact-api"
}POST /api/clip-projects, on the Pro Beta, Max and Business plans. The 403 body is the example from OpusClip's own docs.Source: OpusClip API limits, checked 7 November 2026
OpusClip allows 30 requests a minute per API key on the core project and clip APIs. Past 30 in a minute, the next request gets a 429. Polling for clips uses the same key, so every poll counts toward the 30.
Pro Beta and Max run 4 projects at once, Business 50. A project started while all slots are busy also gets a 429, with the header X-Cap-Reason: concurrent. The slot frees as soon as any running project finishes.
Pro Beta and Max include 15 hours, 900 credits, of API use per calendar month per workspace. After that the API answers 403, not 429, so a retry loop stops instead of spinning. It resumes on the first day of the next month (UTC), and the web app keeps working meanwhile.
Every API project costs at least 10 credits, about 10 minutes, so a month of short videos reaches the cap after 90 projects.
OpusClip API limits next to clipsdk
What each limit is and what you get back past it.
| Limit | OpusClip API, Pro Beta and Max | clipsdk API |
|---|---|---|
| Requests | 30 a minute per key, then 429 | No cap on valid keys; 30 failed auth attempts a minute per IP, then 429 |
| Running at once | 4 projects, 50 on Business, then 429 with X-Cap-Reason: concurrent | 3 jobs per account, then 429 RATE_LIMITED |
| Retry-After | Not documented | On every 429: 10 s when busy, the seconds to 00:00 UTC past a daily limit, 60 s after too many failed auths, and up to a day after too many failed jobs |
| Per month | 900 credits, 15 hours, then 403 API_MONTHLY_CAP_REACHED until the 1st (UTC) | No cap; $0.02 a minute past 2,000 minutes |
| Per day | None documented for projects | 200 jobs and 20 GB of uploads |
| Smallest job | 10 credits, about 10 minutes | No minimum, billed per second |
| Longest video | 10 hours, 30 GB | 3 hours, 5 GB |
clipsdk limits from our limits docs and pricing.
Source: OpusClip API limits, checked 7 November 2026
Fix it: pace, cap, back off, stop
The code below does all four. Retrying a 429 at once only adds requests to the minute that is already full.
Tell the three answers apart
A 429 without
X-Cap-Reasonmeans the key sent more than 30 requests in a minute. A 429 withX-Cap-Reason: concurrentmeans 4 projects are already running, or 50 on Business. A 403 withcode: API_MONTHLY_CAP_REACHEDmeans the workspace used its 900 credits this month.Pace every request to one per 2 seconds
30 a minute is one request every 2 seconds. Share one pacer across every worker and every polling loop that uses the key, since they all draw from the same 30.
Keep at most 4 projects running
Count the projects you have in flight and free a slot when one finishes, from your webhook or your poll. A fifth project then waits for a slot instead of collecting 429s.
Back off on 429, with jitter
Wait 2 seconds and double the wait on every try, up to 60, plus up to 1 second of jitter so workers don't retry in step. On
concurrent, start at 15 seconds. OpusClip doesn't documentRetry-After, so the code only uses it when a response carries it.opus_retry.py import os import random import threading import time import requests API = os.environ.get("OPUS_API", "https://api.opus.pro/api") KEY = os.environ["OPUS_API_KEY"] MAX_TRIES = 6 class MonthlyCapReached(Exception): def __init__(self, body): super().__init__(f"OpusClip API cap reached until {body['reset_at']}") self.reset_at = body["reset_at"] self.upgrade_url = body["upgrade_url"] class Pacer: # 30 requests a minute per key is one every 2 s, shared by every thread def __init__(self, per_minute): self.gap = 60 / per_minute self.next_at = 0.0 self.lock = threading.Lock() def wait(self): with self.lock: now = time.monotonic() at = max(now, self.next_at) self.next_at = at + self.gap time.sleep(at - now) pacer = Pacer(30) started = time.monotonic() def backoff(attempt, reason, retry_after): # OpusClip doesn't document Retry-After, so we only use it when it shows up if retry_after and retry_after.isdigit(): return float(retry_after) base = 15.0 if reason == "concurrent" else 2.0 return min(60.0, base * 2**attempt) + random.uniform(0, 1) def create_project(video_url): for attempt in range(MAX_TRIES): pacer.wait() response = requests.post( f"{API}/clip-projects", headers={"Authorization": f"Bearer {KEY}"}, json={"videoUrl": video_url}, timeout=30, ) # The monthly cap is a 403, not a 429: no retry helps before reset_at is_json = response.headers.get("Content-Type", "").startswith("application/json") if response.status_code == 403 and is_json and response.json().get("code") == "API_MONTHLY_CAP_REACHED": raise MonthlyCapReached(response.json()) if response.status_code != 429: response.raise_for_status() return response.json() reason = response.headers.get("X-Cap-Reason", "rate") seconds = backoff(attempt, reason, response.headers.get("Retry-After")) print(f"{time.monotonic() - started:5.1f} s 429 ({reason}), try {attempt + 2} in {seconds:.1f} s") time.sleep(seconds) raise RuntimeError(f"still 429 after {MAX_TRIES} tries") if __name__ == "__main__": for _ in range(2): try: create_project("https://api.clipsdk.com/f/lib/demo/rocket-ranch-podcast.mp4") print(f"{time.monotonic() - started:5.1f} s 200, project created") except MonthlyCapReached as cap: print(f"{time.monotonic() - started:5.1f} s 403 API_MONTHLY_CAP_REACHED, paused until {cap.reset_at}")Stop on 403 API_MONTHLY_CAP_REACHED
Don't retry it: nothing changes before
reset_at. Park the work until then, upgrade throughupgrade_url, or send the overflow to another API. We ran the script against a local stub that answers the way OpusClip's limits page documents: two 429s, a 429 withX-Cap-Reason: concurrent, a 200, then the 403.output $ python opus_retry.py 0.0 s 429 (rate), try 2 in 2.4 s 2.5 s 429 (rate), try 3 in 4.4 s 6.8 s 429 (concurrent), try 4 in 60.7 s 67.5 s 200, project created 69.5 s 403 API_MONTHLY_CAP_REACHED, paused until 2026-12-01T00:00:00Z
The same job on clipsdk
clipsdk has no monthly cap and no per-minute cap on valid keys. Each account runs 3 jobs at once, and a fourth gets 429 RATE_LIMITED with Retry-After: 10, so the same backoff code works with the header read first. A job that fails still comes back as HTTP 200, with job.status set to "failed" and no charge, so check job.status too.
A 429 never creates a job, so retrying it can't double up. To retry a timeout, resend the same body with the same Idempotency-Key and you get the first job back. A different body, or a retry while the first request is still running, gets 409 IDEMPOTENCY_CONFLICT.
This is a real request: a NASA lesson just over 4 minutes long, 3 clips with karaoke captions, back in 80 seconds. It costs $0.13 at $0.03 per source minute, where the OpusClip API counts any project as at least 10 credits.
curl https://api.clipsdk.com/v1/clips \
-H "Authorization: Bearer $CLIPSDK_KEY" \
-H "Content-Type: application/json" \
-d '{
"video_url": "https://api.clipsdk.com/f/lib/demo/thermal-energy-lesson.mp4",
"clips": 3,
"captions": "karaoke"
}'Why retrying at once makes it worse
A 429 on the rate limit means the minute is already full. Retrying straight away adds another request to that same minute, and with several workers on one key they all retry together and stay locked out.
Backoff spreads the retries out and jitter keeps workers from lining up again. The pacer does the rest: when every request waits its turn, the rate limit is never hit in the first place.
When the monthly cap is the real problem
If you hit API_MONTHLY_CAP_REACHED every month, retries won't help. 900 credits is 15 hours of video, and with the 10-credit minimum it is at most 90 short projects.
For more, OpusClip's Business plans follow a contract. Or send the overflow to an API that bills per use: clipsdk charges $0.03 per source minute, $0.02 past 2,000 minutes in a month, with no cap. New accounts get $1 free.
Questions, answered
Does the OpusClip API send Retry-After on a 429?
Its limits page doesn't say. It says to retry after backoff, so treat a Retry-After header as a bonus: use it when it's there and back off on your own when it isn't.
Why do I get 403 instead of 429?
That is the monthly cap. Past 900 credits on Pro Beta or Max, OpusClip answers 403 with the code API_MONTHLY_CAP_REACHED so retry loops stop. It lifts on the first day of the next month (UTC).
Is the 30 a minute limit per key or per workspace?
Per API key. The monthly 900 credits are per workspace, so more keys raise the request rate but not the month's hours.
Can I still use OpusClip when the API is capped?
Yes. OpusClip says the web app stays fully usable while the API is capped.
Keep reading
- clipsdk vs OpusClip for developersclipsdk costs $0.03 per source minute with no monthly cap. OpusClip is about $0.097 on Pro credits, with a 15 hour monthly API cap. Prices, limits and a migration guide.
- clipsdk limitsclipsdk limits per account: 3 jobs at once, 200 jobs and 20 GB of uploads per UTC day. Videos up to 3 hours and 5 GB, 1 to 20 clips of 10 to 90 s, files kept 7 days.
- clipsdk error codesEvery clipsdk error has one JSON shape with a stable code: 11 HTTP errors from 400 to 500 and 11 job failure codes. Failed jobs cost nothing; retry 429 after Retry-After and 500 with backoff.
Sources
- OpusClip API limits, checked 7 November 2026
- How OpusClip credits are used, checked 7 November 2026
- STEMonstrations: Thermal Energy Transfer on the NASA Image and Video Library, public domain, checked 7 November 2026
Start free
Your back catalog is full of shorts
Your first $1 is free: 33 minutes of video, every clip included up to 1080p60 and 20 Mb/s.
