Sume rate limit scope: /v1 and MCP count, OPTIONS preflights do not
The Sume limiter covers /v1 paths and the MCP route. CORS OPTIONS preflights are exempt, and reads and writes use separate buckets. What that means.

Not every request to api.sume.com spends from your rate limit. In the API source the limiter applies to paths that start with /v1/ and to the MCP route. An OPTIONS request is exempt, whatever the path. Knowing the boundary stops you from counting requests that cost nothing, and from expecting protection on requests that do count.
What is counted
| Request | Counted | Bucket |
|---|---|---|
| GET or HEAD under /v1/ | yes | read |
| POST, PUT, PATCH or DELETE under /v1/ | yes | write |
| POST /v1/generation/admission-preview | yes | read |
| POST to the MCP endpoint | yes | read |
| OPTIONS to any path | no | none |
Browsers and preflight
A browser sends an OPTIONS preflight before a cross-origin request that carries a custom header such as x-api-key. Those preflights do not spend from the bucket, so a page that makes 100 calls does not make 200 requests against the budget. The CORS configuration exposes ratelimit-limit, ratelimit-remaining, ratelimit-reset, retry-after and x-sume-poll-after to the page, so client JavaScript can read them. Do not ship an API key to a browser, though. Call the API from your server.
Reads and writes
The two buckets are separate. A read is any GET or HEAD, plus the two POSTs that submit nothing. Everything else is a write. Reads get forty times the plan's write number, so a Free key has 120 writes and 4800 reads a minute.
Count with the headers
The simplest proof is to read the header on two calls. An OPTIONS call leaves ratelimit-remaining unchanged on the next real request, apart from your own other traffic.
import os, urllib.request
def remaining():
req = urllib.request.Request("https://api.sume.com/v1/me", headers={"x-api-key": os.environ["SUME_API_KEY"]})
with urllib.request.urlopen(req, timeout=15) as resp:
return int(resp.headers["ratelimit-remaining"])
before = remaining()
opts = urllib.request.Request("https://api.sume.com/v1/me", method="OPTIONS",
headers={"Origin": "https://example.com", "Access-Control-Request-Method": "GET"})
urllib.request.urlopen(opts, timeout=15).read()
print("spent by OPTIONS + next GET:", before - remaining()) # 1, the GET onlyPractical rule
Budget by the plan number, pace writes, and let reads be cheap. Do not try to avoid preflights to save budget, because they were never charged.
Sources
Related posts
More in Developers
- Which short-video lengths fit one video-trim call? 0.2 to 900 seconds
One Sume video-trim call outputs 0.2 to 900 seconds, so a 3-minute Short fits easily. A 10-minute TikTok ad fits; a 60-minute source does not.
- whisper-1 or gpt-transcribe for subtitles: what OpenAI assigns to each
OpenAI recommends gpt-transcribe, gpt-4o-transcribe-diarize for speakers, whisper-1 for translation and subtitles. Plus the 25 MB limit and a chunking script.
- Why adaptive and auto are missing from /v1/videos/models
Seedance and Wan list auto and adaptive aspect ratios in the Video Router catalog, but /v1/videos/models filters them out. Which models, and a script to see it.
- Windsurf now redirects to Devin Desktop: where Sume MCP setup lives
Windsurf redirects to Devin Desktop, and Cascade was removed in v3.9.19. Re-add Sume's hosted MCP URL there and verify it with mcp_health and tools_list.
Written by Sume