Plans & limits
Workspace plans
| Plan | Monthly credits | vs Free | Queue priority | Per-video length |
|---|---|---|---|---|
free | 10,000 | 1× | low | Up to 1 hour |
starter | 20,000 | 2× | low | Up to 1 hour |
pro | 50,000 | 5× | normal | Up to 1 hour |
business | 200,000 | 20× | high | Up to 1 hour |
enterprise | Unlimited (fair use) | — | high | Up to 1 hour by default; longer media available on request |
New workspaces default to free. Paid tiers are assigned manually — contact your account team. Plan is reflected on each job as priority (set at creation, not overridable in the request body).
Plan catalog and per-action credit costs: GET /v1/billing/limits returns plans (monthlyCredits, multiplierVsFree) and creditCosts. With a workspace API key, GET /v1/workspace or GET /v1/workspace/usage returns the unified pool (limit, used, remaining, byService[]). GET /v1/projects/{projectId}/usage returns per-project consumption and optional creditLimit.
Monthly credit pool
All billable actions draw from one workspace credit pool for the current billing period. Each action costs credits according to creditCosts on GET /v1/billing/limits (defaults below):
POST /v1/jobswithserviceType: transcription— 100 credits per job.POST /v1/jobswithserviceType: indexer— 10 credits pertranscriptionIdininput.transcriptionIds(up to 50 per job).POST /v1/jobswithserviceType: clip_generation— 1 credit per clip ininput.options.maxClips.POST /v1/jobswithserviceType: thumbnail— 10 credits per variant ininput.options.thumbnailCount(1–3).POST /v1/jobswithserviceType: metadata— 10 credits per job.POST /v1/jobswithserviceType: summarization— 20 credits per job.POST /v1/jobswithserviceType: translation— 20 credits per job.POST /v1/catalog/search— 1 credit per search request.
Credits are reserved when the API accepts the request (job queued or search executed). Failed jobs after queueing still count toward usage.
When the pool is exhausted, the API returns 403 with error.code: quotaExceeded:
{
"data": null,
"error": {
"code": "quotaExceeded",
"message": "credit limit: need 100, 0 remaining this period; resets at 2026-06-01T00:00:00.000Z"
},
"metadata": { ... }
}Check balances before bulk loops via GET /v1/workspace/usage (remaining on the unified pool). Projects may optionally set creditLimit for a sub-cap within the workspace pool.
This is an envelope error (not job.error). Integrators should surface it before polling. See Errors.
API rate limits (project & workspace keys)
Programmatic callers using project or workspace API keys share per-key HTTP rate limits (rolling one-minute window). Dashboard JWT sessions and platform admin routes are not capped this way — job volume is gated by monthly quota instead.
| Methods | Limit (per API key) |
|---|---|
GET, HEAD | 10,000 / minute |
POST, PUT, PATCH, DELETE | 50 / minute |
Read and write counters are independent — heavy polling on GET /v1/jobs/… does not consume your write budget. On exceed, the API returns 429 with error.code: rateLimited.
Max source duration & word timings
Max source duration is configured in platform settings (default 1 hour). Sources longer than this fail with duration_exceeded. Word-level timings are stored through the same limit — longer jobs return segments without per-word timings.
The worker rejects sources longer than this limit before transcription runs. Duration is checked from local media after download. Configure the limit in platform admin settings (transcription.maxSourceDurationSec).
Live values: GET /v1/transcription/policy → data.plans.free.maxSourceDurationSec and data.plans.enterprise.maxSourceDurationSec. There is no duration field on POST /v1/jobs — invalid length is discovered asynchronously. Poll the job; on failure, status is failed and error.code is duration_exceeded.
{
"code": "duration_exceeded",
"message": "Video duration 7200.0s exceeds limit 3600s (checked at local_probe)"
}Transcript size
Completed transcripts are stored in MongoDB with a BSON size guard (default ~15 MiB estimated before write). Extremely long or word-dense outputs fail at persist time with transcript_too_large on the job — the job ends failed even if the engine finished transcribing.
{
"code": "transcript_too_large",
"message": "Transcription payload is too large to store (estimated 18.42 MB, limit 15.0 MB, pre_persist)"
}The public Transcript API still returns full segments (and words when stored). See Transcripts.
Job failure codes
When status is failed, read error (code + message). Full segment text is never on the Job object — use resultSummary / Transcripts API on success only. For how error relates to lastError, stage errors, and retries, see Jobs → Job failures & retries.
| error.code | Typical cause |
|---|---|
duration_exceeded | Source longer than the worker max duration. |
unsupported_source_language | Auto-detect (or resolved) source language is not in the platform transcription allowlist. |
transcript_too_large | Transcript BSON estimate or Mongo 16 MB limit on persist. |
processing_failed | Engine, download, or worker misconfiguration (missing API keys, network, etc.). |
Inspect progress[] for stage-level failed events and nested error objects — especially for early download failures.