Plans & limits

Workspace plans control monthly submission quotas, queue priority, and operational caps on video length and transcript size. Limits are enforced at job creation (quota) and during worker processing (duration, storage).

Workspace plans

PlanTranscription jobs / monthIndexing credits / monthClip credits / monthThumbnail credits / monthSemantic search queries / monthQueue priorityPer-video length
free10 (resets on your billing period)100 (1 credit per txt_… indexed)1,000 (1 credit per clip in input.options.maxClips)100 (1 credit per variant in input.options.thumbnailCount; max 3 per job)1,000lowUp to 1 hour
enterpriseUnlimited (fair use)UnlimitedUnlimitedUnlimitedUnlimitedUnlimitedhighUp to 1 hour by default; longer media available on request

New workspaces default to free. Enterprise is assigned manually — contact your account team. Plan is reflected on each job as priority (set at creation, not overridable in the request body).

Free-plan monthly credit caps are configured in platform settings (billing.free on GET /v1/platform/config for admins). Public read: GET /v1/billing/limits. With a workspace API key, GET /v1/workspace or GET /v1/workspace/usage returns workspace-wide usage.services[]. GET /v1/projects/{projectId}/usage returns per-project consumption and optional project caps.

Monthly submission quota

Billable actions consume workspace credits for the current billing period (see GET /v1/workspace/usage):

  • POST /v1/jobs with serviceType: transcription — 1 credit per job.
  • POST /v1/jobs with serviceType: indexer — 1 credit per transcriptionId in input.transcriptionIds (up to 50 per job).
  • POST /v1/jobs with serviceType: clip_generation 1 credit per clip requested in input.options.maxClips (default and cap from platform settings — live values: GET /v1/jobs/policy?serviceType=clip_generation). A job asking for 5 clips consumes 5 credits at create time.
  • POST /v1/jobs with serviceType: thumbnail — 1 credit per variant in input.options.thumbnailCount (1–3; maximum 3 variants per job).
  • POST /v1/jobs with serviceType: metadata — 1 credit per job.
  • POST /v1/catalog/search — 1 credit per search request (response fields such as groupCount, groups[], and camelCase results[] hits — see Semantic search → Search transcriptions).

Credits are reserved when the API accepts the request (job queued or search executed). Failed jobs after queueing still count toward usage.

When a service's monthly cap is reached, the API returns 403 with error.code: quotaExceeded. The message names the billable service and remaining credits (camelCase envelope; snake_case service id in the message text):

{
  "data": null,
  "error": {
    "code": "quotaExceeded",
    "message": "ai_search credit limit: need 1, 0 remaining this period; resets at 2026-06-01T00:00:00.000Z"
  },
  "metadata": { ... }
}

Transcription, indexer, clips, thumbnail, and metadata jobs use the same pattern (transcription credit limit, indexer credit limit, clip_generation credit limit, thumbnail credit limit, metadata credit limit). Check balances before bulk index or search loops via GET /v1/workspace/usage (services[] with used, limit, and remaining).

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.

MethodsLimit (per API key)
GET, HEAD10,000 / minute
POST, PUT, PATCH, DELETE50 / 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.codeTypical cause
duration_exceededSource longer than the worker max duration.
transcript_too_largeTranscript BSON estimate or Mongo 16 MB limit on persist.
processing_failedEngine, 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.