Skip to main content

API reference

The Corte REST API is the platform without the UI: the same model catalog, Applications, Workflows, storage, and transcription that power the app, callable from a script, a backend, or an agent.

This section is the reference — every resource, parameter, and response shape. If you want the narrative version first, start with the API overview guide.

https://api.corte.so

Every path in this reference is relative to that base URL. /v1 in the path is the API version; it is the only version, and existing fields are additive-only within it.

Authentication

Send an API key as a bearer token on every request:

curl https://api.corte.so/v1/account \
-H "Authorization: Bearer corte_sk_…"

Corte stores only a SHA-256 hash of the key, so the secret is shown exactly once — at creation. A key carries the full authority of the account that made it: every endpoint in this reference accepts key auth, and any generation, LLM step, workflow run, or transcription it starts spends that account's credits.

Requests with no credentials, an unknown key, or a revoked key fail with unauthenticated (401). Two endpoints in this reference are the exception and need no key: GET /v1/health and GET /v1/plans.

:::note Browser sessions and plugin tokens The app itself authenticates with an eli_session httpOnly cookie, and sandboxed plugins use per-install corte_pk_ tokens restricted to a handful of read-only routes. Neither is part of the public API — build against corte_sk_ keys. :::

Requests

Send JSON bodies with Content-Type: application/json. Path parameters are written :id throughout this reference. Query parameters are documented per endpoint; unknown query parameters are ignored.

The request body limit is 32 MB. Media never travels through a JSON body — it goes through Files and is referenced afterwards by storageId.

Responses

Successful responses are 200 with a JSON object. Resources are nested under a named key rather than returned bare, so responses stay extensible:

{ "job": { "id": "…", "status": "queued" }, "estimatedCredits": 24 }

Collections follow the same rule and use a plural key — { "models": [...] }, { "workflows": [...] }, { "jobs": [...] }. Deletes and other side-effect-only endpoints return { "ok": true }.

Timestamps are ISO 8601 UTC strings (2026-07-28T14:03:11.482Z). Ids are UUIDs unless documented otherwise — model ids (kling-3) and Application ids (flatlay-to-model) are stable slugs.

Signed media URLs expire

Any url or resultUrls field holding media is a presigned read URL with a finite lifetime. Fetch a resource again to get freshly signed URLs; don't persist them. The durable handle is storageId (or resultStorageIds on a generation job) — those never expire, and every endpoint that takes media takes a storageId.

Errors

Errors use conventional HTTP status codes and a single body shape:

{ "error": { "code": "insufficient_credits", "message": "…" } }

Branch on code, not on message — messages are human-facing and change. The full list of codes is in Errors.

Asynchronous work

Generations, transcriptions, and workflow runs are asynchronous. The creating call returns immediately with a record in a non-terminal state; you poll until it settles. There are no webhooks.

ResourceCreatePollTerminal states
GenerationPOST /v1/generationsGET /v1/generations/:idsucceeded · failed · canceled
TranscriptionPOST /v1/transcriptionsGET /v1/transcriptions/:idsucceeded · failed
Workflow runPOST /v1/workflows/:id/executeGET /v1/workflows/:id/runs/:runIdcomplete · error · stopped

A 2–3 second poll interval is a good default. Image generations typically settle in seconds, video in one to several minutes, and workflow runs take as long as the slowest chain of nodes.

Workflow runs are the exception to poll-only: POST /v1/workflows/:id/execute accepts wait: true to block until the run finishes. Practical for short pipelines, risky for long ones.

A workflow run's nodeResults fills in incrementally while status is running, so polling it streams per-node progress rather than flipping from empty to complete.

Pagination and sorting

Every unbounded list follows one contract: it accepts limit and offset, and returns a total that counts every matching row, not the page. Lists are newest first; where an alternate order is useful, a sort parameter selects it.

What varies per endpoint is only the limit default, which follows how the list is consumed:

The one exception is GET /v1/api-keys, served whole — accounts are hard-capped at 20 keys.

Credits and billing

Work that costs money is priced in credits — 100 credits = $1. Endpoints that spend credits check the balance before doing the work and return insufficient_credits (402) if the estimate doesn't fit, so a 402 means nothing was charged.

Creation responses for generations include estimatedCredits, which is the amount reserved against the balance. The actual charge lands on the job's costCredits when it settles.

Who pays. By default, the account that owns the key. When a request carries a projectId for a shared project, the project owner pays and the caller is recorded as the actor. If the owner's balance is short, the error is owner_insufficient_credits (402) rather than insufficient_credits.

Storage is a hard quota with no overage billing: at the cap, uploads and imports fail with storage_limit (402) until files are deleted or the plan is upgraded. Generation results always save.

Every charge appears in the ledger at GET /v1/usage.

Rate limits

There are no per-key request limits today. Credits and the storage quota are the real limits. Two 429s can still reach you, both upstream in origin: rate_limited from a provider under load, and provider_unavailable (503) when one is down — retry both with backoff.

Poll considerately. Nothing throttles a tight polling loop, but nothing rewards it either.

Resources

ResourceWhat it covers
ModelsThe generation catalog: capabilities and credit pricing
GenerationsSubmit, poll, list, and cancel generation jobs
ApplicationsRun the 43 curated one-shot experiences
WorkflowsCreate, read, update, and delete node pipelines
Workflow runsExecute pipelines with custom inputs and read per-node results
FilesUpload, import, list, and delete media; storage quota
TranscriptionsWord- and segment-level transcripts with speakers
ProjectsShared workspaces, members, pooled billing
Account & keysBalance, plans, usage ledger, API key management
MCP toolsThe same primitives as agent tools over Streamable HTTP
ErrorsEvery error code, cause, and how to handle it