Skip to main content

Generations

A generation job runs one model once. Submitting returns a job in queued state along with the credit estimate that was reserved; you poll until it reaches a terminal state and read resultUrls / resultStorageIds.

Every generation flows through this resource — including Applications, whose run endpoint returns a standard generation job.

The generation job object

FieldTypeDescription
idstringJob id (UUID).
modelstringModel id the job ran on.
kindenumvideo · image · audio · upscale.
statusenumqueued · running · succeeded · failed · canceled.
paramsobjectThe parameters as submitted. See Generation parameters.
resultUrlsstring[] | nullFreshly signed media URLs, present once succeeded. These expire — re-fetch the job rather than storing them.
resultStorageIdsstring[] | nullThe results persisted into your storage. Durable; reuse these as inputs instead of re-uploading resultUrls.
errorMessagestring | nullWhy it failed, when status is failed.
costCreditsnumber | nullCredits actually charged. null until the job settles.
createdAtstringISO 8601.
completedAtstring | nullISO 8601, once terminal.
projectIdstring | nullThe project the job is billed and scoped to.
cutIdstring | nullThe cut it was attributed to, if any.

:::tip Chain jobs with resultStorageIds, not resultUrls resultStorageIds are permanent handles that every media-taking parameter accepts. Feeding one generation's output into the next needs no download, re-upload, or URL juggling. :::


POST /v1/generations

Submit a job. Returns immediately with the job in queued — poll GET /v1/generations/:id for the result.

Body

NameTypeRequiredDescription
modelstringyesModel id from GET /v1/models.
paramsobjectyesMust match the model's kind and capabilities. See below.
projectIdstringnoBill this job to a shared project — the owner pays and you're recorded as the actor. Defaults to your own default project (self-billed).
cutIdstringnoAttribute the job to a cut within the project.

Returns { "job": GenerationJob, "estimatedCredits": number }.

estimatedCredits is what was checked against the balance. The final charge lands on costCredits.

Request
curl -s -X POST https://api.corte.so/v1/generations \
-H "Authorization: Bearer corte_sk_…" \
-H "Content-Type: application/json" \
-d '{
"model": "kling-3",
"params": {
"kind": "video",
"prompt": "Slow dolly-in on a foggy ridgeline at dawn",
"duration": 5,
"aspectRatio": "16:9",
"resolution": "1080p"
}
}'
Response
{
"job": {
"id": "5f2b9c14-8a3d-4b21-9e77-0c4a1d6f8e02",
"model": "kling-3",
"kind": "video",
"status": "queued",
"params": {
"kind": "video",
"prompt": "Slow dolly-in on a foggy ridgeline at dawn",
"duration": 5,
"aspectRatio": "16:9",
"resolution": "1080p"
},
"resultUrls": null,
"resultStorageIds": null,
"errorMessage": null,
"costCredits": null,
"createdAt": "2026-07-28T14:03:11.482Z",
"completedAt": null,
"projectId": "1b6d4f90-77c2-4a5e-b3d8-2e9a0c15f7b4",
"cutId": null
},
"estimatedCredits": 85
}

Errors

CodeWhen
invalid_paramsmodel or params missing, params.kind doesn't match the model, a value outside the model's capabilities, or an unknown/uncommitted storageId.
not_foundUnknown or disabled model id.
plan_requiredThe model is paidOnly and the paying account is on Free.
insufficient_creditsYour balance can't cover estimatedCredits. Nothing charged.
owner_insufficient_creditsSame, but the project owner is short.
forbiddenGeneration is disabled for the workspace.

Generation parameters

params.kind must equal the model's kind. Every value is validated against the model's declared capabilities before the job is created, so mistakes cost nothing.

All *StorageId / *StorageIds fields must be committed objects you can read — yours, or linked to a shared project you belong to. See Files.

kind: "video"

NameTypeRequiredDescription
kind"video"yes
promptstringyes¹What to generate.
durationnumberyesSeconds. Must be a member of the model's durations.
aspectRatiostringyesMust be in the model's aspectRatios.
resolutionstringnoMust be in the model's resolutions. Also selects the creditsPerSecond rate.
sourceVideoStorageIdstringcond.Required when requiresSourceVideo — video-to-video, reframe, lip sync.
startFrameStorageIdstringnoFirst frame. Needs supportsFirstFrame.
endFrameStorageIdstringnoLast frame. Needs supportsLastFrame.
referenceImageStorageIdsstring[]noUp to maxReferenceImages.
referenceVideoStorageIdsstring[]noUp to maxReferenceVideos.
referenceAudioStorageIdsstring[]noUp to maxReferenceAudios.
generateAudiobooleannoSoundtrack on or off. false on a supportsAudioToggle model returns a video-only file — the pick for scroll-scrubbed or looping backgrounds.

¹ Optional only when the model has requiresSourceVideo: true. Models with requiresReferenceImage: true additionally need startFrameStorageId or at least one referenceImageStorageIds.

{
"model": "kling-3",
"params": {
"kind": "video",
"prompt": "The product rotates slowly under warm studio light",
"duration": 5,
"aspectRatio": "9:16",
"startFrameStorageId": "b0e7c9a1-4d52-4f0e-8c31-77a2e5d9f6b8"
}
}

kind: "image"

NameTypeRequiredDescription
kind"image"yes
promptstringyesWhat to generate.
aspectRatiostringyesMust be in the model's aspectRatios.
numImagesnumberyesInteger, 1 to the model's maxImages. Multiplies the cost.
resolutionstringnoMust be in the model's resolutions.
qualitystringnoMust be in the model's qualities.
referenceStorageIdsstring[]noImage conditioning. Needs supportsImageReference.
{
"model": "nano-banana-2",
"params": {
"kind": "image",
"prompt": "Editorial flat lay of a trail-running shoe on slate, cold morning light",
"aspectRatio": "4:5",
"numImages": 2
}
}

kind: "audio"

Which fields apply depends on the model's capabilities.category.

NameTypeRequiredDescription
kind"audio"yes
promptstringcond.Required for tts, music, and sfx (unless lyrics is given). For TTS this is the text to speak.
voicestringnoFor tts. Must be in voices; the model's defaultVoice is used when omitted.
lyricsstringcond.For music models with supportsLyrics. Required on vocal-song models — those that support lyrics but not instrumentals.
styleInstructionsstringnoFor models with supportsStyleInstructions.
instrumentalbooleannoFor models with supportsInstrumental.
durationSecondsnumbercond.Bounded by minSeconds / maxSeconds. Required for cleanup — it's the input's length, and the charge is derived from it.
sourceStorageIdstringcond.Required for cleanup and dubbing — the audio to process.
videoStorageIdstringnoVideo whose audio track is the source, for dubbing.
targetLanguagestringnoFor dubbing. Must be in targetLanguages.
{
"model": "minimax-speech",
"params": {
"kind": "audio",
"prompt": "Every frame you export is watermark-free. Always.",
"voice": "Wise_Woman"
}
}

TTS models bill on creditsPerThousandChars, so cost scales with the length of prompt + lyrics.

kind: "upscale"

NameTypeRequiredDescription
kind"upscale"yes
sourceStorageIdstringyesThe media to upscale.
durationSecondsnumberyesInput length in seconds; positive. Upscalers bill by duration, so this must be accurate.
{
"model": "video-upscaler",
"params": {
"kind": "upscale",
"sourceStorageId": "b0e7c9a1-4d52-4f0e-8c31-77a2e5d9f6b8",
"durationSeconds": 12
}
}

GET /v1/generations/:id

Fetch one job. This is the polling endpoint.

Readable by the submitter, and by any member of the job's project.

Returns { "job": GenerationJob }.

Request
curl -s https://api.corte.so/v1/generations/5f2b9c14-8a3d-4b21-9e77-0c4a1d6f8e02 \
-H "Authorization: Bearer corte_sk_…"
Response
{
"job": {
"id": "5f2b9c14-8a3d-4b21-9e77-0c4a1d6f8e02",
"model": "kling-3",
"kind": "video",
"status": "succeeded",
"params": { "kind": "video", "prompt": "Slow dolly-in on a foggy ridgeline at dawn", "duration": 5, "aspectRatio": "16:9", "resolution": "1080p" },
"resultUrls": ["https://media.corte.so/…/out.mp4?X-Amz-Signature=…"],
"resultStorageIds": ["c74a1e08-9b6f-4d13-a205-e8f30b7c9d61"],
"errorMessage": null,
"costCredits": 85,
"createdAt": "2026-07-28T14:03:11.482Z",
"completedAt": "2026-07-28T14:04:47.019Z",
"projectId": "1b6d4f90-77c2-4a5e-b3d8-2e9a0c15f7b4",
"cutId": null
}
}

A failed job is still a 200 — check status:

{
"job": {
"id": "5f2b9c14-…",
"status": "failed",
"errorMessage": "Upstream provider rejected the prompt (content policy)",
"costCredits": 0,
"completedAt": "2026-07-28T14:04:02.771Z"
}
}

Polling

import time, requests

def wait(job_id, timeout=900, interval=3):
deadline = time.time() + timeout
while time.time() < deadline:
job = requests.get(
f"https://api.corte.so/v1/generations/{job_id}",
headers={"Authorization": f"Bearer {KEY}"},
).json()["job"]
if job["status"] in ("succeeded", "failed", "canceled"):
return job
time.sleep(interval)
raise TimeoutError(job_id)

Images usually settle in seconds; video in one to several minutes.


GET /v1/generations

List recent jobs, newest first.

Without projectId this returns your own jobs. With projectId it returns every member's jobs for that project — the shared library view.

Query parameters

NameTypeDefaultDescription
limitnumber50Max 200.
offsetnumber0Page through with limit.
projectIdstringScope to a shared project you belong to. Switches the query to all members' jobs.
cutIdstringNarrow to one cut. Only applies alongside projectId.

Returns { "jobs": GenerationJob[], "total": number }total counts every matching job, not the page.

Request
curl -s "https://api.corte.so/v1/generations?limit=20" \
-H "Authorization: Bearer corte_sk_…"
Response
{
"jobs": [
{ "id": "5f2b9c14-…", "model": "kling-3", "kind": "video", "status": "succeeded", "costCredits": 85, "…": "…" },
{ "id": "8d31a067-…", "model": "nano-banana-2", "kind": "image", "status": "succeeded", "costCredits": 24, "…": "…" }
],
"total": 214
}

POST /v1/generations/:id/cancel

Cancel a queued or running job. Best-effort with the upstream provider; the job row is marked canceled either way.

Idempotent — cancelling an already-terminal job returns it unchanged rather than erroring.

Only the submitter may cancel their own job. For project-billed jobs submitted by someone else, only the project owner may cancel.

Returns { "job": GenerationJob }.

Request
curl -s -X POST https://api.corte.so/v1/generations/5f2b9c14-…/cancel \
-H "Authorization: Bearer corte_sk_…"
Response
{
"job": {
"id": "5f2b9c14-8a3d-4b21-9e77-0c4a1d6f8e02",
"status": "canceled",
"completedAt": "2026-07-28T14:03:39.204Z",
"…": "…"
}
}