HeyGen's X-RateLimit-Scope header vs Sume's error.details.scope
HeyGen's October 2026 429s add a scope header. Sume names the bucket in error.details.scope and sends ratelimit-* headers; one parser can read both.

HeyGen's developer changelog (read 2026-10-07) says a rate-limit 429 now carries X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset and X-RateLimit-Scope alongside Retry-After. Sume answers the same question with ratelimit-limit, ratelimit-remaining, ratelimit-reset and retry-after headers, plus error.details.scope in the body, which is read or write.
If you front both vendors, write one function that returns "seconds to wait and which bucket" and keep the vendor spelling at the edge.
The two schemes side by side
Header names differ, the idea is the same. Compare only what each vendor's own page states.
| Signal | HeyGen changelog | Sume docs |
|---|---|---|
| Limit | X-RateLimit-Limit | ratelimit-limit |
| Remaining | X-RateLimit-Remaining | ratelimit-remaining |
| Reset | X-RateLimit-Reset | ratelimit-reset (seconds until the window resets) |
| Which bucket | X-RateLimit-Scope | error.details.scope: read or write |
| Wait hint | Retry-After, alongside the new headers | retry-after seconds on 429 |
Why the bucket name matters on Sume
Sume keeps read and write budgets separate per API key. A read is any GET or HEAD, such as a poll of status_url; everything else, including run creation and cancellation, is a write. Reads get forty times the plan's write number, so a tight poll loop cannot starve your own submits.
A 429 therefore means different things. scope: "write" says slow your submits. scope: "read" says slow your polling. Separately, queue_full is a 429 that is not a request-rate limit at all: it means the workspace's accepted generation capacity is full and only finishing or canceling a job helps.
One parser for both
The function below takes a response status, a lowercase header dict and a parsed body, and returns how long to wait and which bucket tripped. It reads Sume's fields and HeyGen's side by side. Only the HeyGen header names above come from HeyGen's page; the scope value format is not specified there, so the code just passes it through.
def wait_for(status, headers, body):
if status != 429:
return None
err = (body or {}).get("error", {})
if err.get("code") == "queue_full":
return {"wait": None, "bucket": "queue_full"}
scope = (err.get("details") or {}).get("scope") or headers.get("x-ratelimit-scope")
wait = headers.get("retry-after") or headers.get("ratelimit-reset") or headers.get("x-ratelimit-reset")
return {"wait": float(wait) if wait else 5.0, "bucket": scope}
print(wait_for(429, {"retry-after": "7"}, {"error": {"code": "rate_limited", "details": {"scope": "read"}}}))
print(wait_for(429, {}, {"error": {"code": "queue_full"}}))
Limits you still have to read per plan
HeyGen's entry also raises enterprise limits; those are HeyGen's numbers and a different product tier. On Sume the per-minute budget is set by plan (the authentication docs list Free through Scale) and Enterprise is contract-based, so always trust ratelimit-limit on the response over any table, including the one in these docs.
A checklist for a multi-vendor client
Rate-limit handling goes wrong in the same few places. These rules hold on Sume, and they are a sensible default for any vendor whose page does not say otherwise.
Do not log API keys, signed URLs or raw media URLs next to the headers; log the request id from the error body instead, which Sume says is safe to share with support.
- Branch on the HTTP status first, then on
error.code:rate_limitedandqueue_fullare both 429 on Sume and need different waits. - Use
retry-afterwhen it is present; fall back to exponential backoff when it is not. - Never retry a paid submit without an
Idempotency-Key; with one, a retry returns the original job. - Count reads and writes separately in your own metrics, so a
scope: read429 is not blamed on your submit path. - Treat
ratelimit-remainingas advice for the current response only; the budget refills when the window resets.
Sources
Related posts
More in Comparisons
- How many languages do AI avatar tools list? Six pricing pages
Creatify lists 75+, Captions 100+, Colossyan 120+, Synthesia 140+, HeyGen 175+ dialects. Sume's avatar docs give no language count. What to test instead.
- How many stock AI avatars do vendors list? Pages read Oct 2026
Vendors list 9 to 1,500 stock avatars by plan. Sume has no avatar-count tiers: it creates one for $0.95 and its catalog search returns up to 100 results.
- Instagram's Reels page says 3 and 20 minutes: which one to plan for
Instagram's Reels features page says both multi-clip videos up to 3 minutes and clips adding up to 20 minutes. Plan creative for 3, tools for 20, and read both.
- Is GPT Image 2.5 cheaper than Seedream 5.0 Lite? It depends on quality
On Sume a 1024x1024 ChatGPT Image 2.5 costs $0.0074 at low, $0.0165 at medium and $0.0659 at high; Seedream 5.0 Lite is a flat $0.04375. Where they cross.
Written by Sume