Cutline/Docs
v1

On this page

  • Overview
  • Authentication
  • Create a video
  • Poll job status
  • Download the MP4
  • Cancel a job
  • List recent jobs
  • Webhooks
  • Idempotency
  • Error codes
  • Rate limits

API Reference

Cutline REST API

Programmatic access to the same 12-stage pipeline that powers the web app. Submit a sentence, poll the job, download the MP4. JSON in, MP4 out.

Overview

The Cutline API exposes a single asynchronous workflow: submit a job, poll for status, download when ready. All endpoints are versioned under /api/v1/.

Responses are JSON. Error responses always carry a stable, branchable code field - never branch on error message text.

Base URL

https://cutline.cloud/api/v1

Content type

application/json

Authentication

API requests are authenticated with an API key sent in the X-API-Key header. Generate keys from your dashboard. Each key is shown once at creation time and stored as a hash on our side - keep it safe.

curl
curl https://cutline.cloud/api/v1/generate/jobs \
  -H "X-API-Key: ck_live_••••••••••••••••"

Create a video

POST/api/v1/generate

Submits a generation job. Returns immediately with a jobId - rendering happens asynchronously in a worker. Poll status (next section) until completed or failed.

Request body

ParameterTypeDescription
input*stringYour one-sentence prompt. 5-500 characters.
durationSecondsnumberTarget video length, 10-60. Defaults to inferred from prompt.
modestring"slideshow" (default) or "talking_object" (Veo-backed character video).
captionsstring"on" (default) or "off". Burned-in subtitles.
platformstring"general" / "linkedin" / "twitter" / "youtube_shorts". Tunes pacing and tone.
assetIdsstring[]IDs from /api/assets/upload - logos, product photos, reference media.
brandColorsobject{ primary?: hex, secondary?: hex }. Used by the visual stage.
callbackUrlstringWebhook URL fired on terminal job state. See Webhooks below.
textModelstringOpenRouter model ID override for this job's LLM stages.

Example

curl
curl -X POST https://cutline.cloud/api/v1/generate \
  -H "X-API-Key: ck_live_••••••••••••••••" \
  -H "Content-Type: application/json" \
  -H "X-Idempotency-Key: order_12345" \
  -d '{
    "input": "Explain how Redis works in 30 seconds",
    "durationSeconds": 30,
    "captions": "on",
    "platform": "youtube_shorts"
  }'
javascript
const res = await fetch("https://cutline.cloud/api/v1/generate", {
  method: "POST",
  headers: {
    "X-API-Key": process.env.CUTLINE_API_KEY,
    "Content-Type": "application/json",
    "X-Idempotency-Key": crypto.randomUUID(),
  },
  body: JSON.stringify({
    input: "Explain how Redis works in 30 seconds",
    durationSeconds: 30,
    captions: "on",
    platform: "youtube_shorts",
  }),
});
const { jobId } = await res.json();
python
import os, requests, uuid

res = requests.post(
    "https://cutline.cloud/api/v1/generate",
    headers={
        "X-API-Key": os.environ["CUTLINE_API_KEY"],
        "X-Idempotency-Key": str(uuid.uuid4()),
    },
    json={
        "input": "Explain how Redis works in 30 seconds",
        "durationSeconds": 30,
        "captions": "on",
        "platform": "youtube_shorts",
    },
)
job_id = res.json()["jobId"]

Response (200)

json
{
  "jobId": "job_01HK8Z9X2YBN5T7QM3R4S5T6"
}

Poll job status

GET/api/v1/generate/:jobId

Returns current job state. Poll with exponential backoff (we use 2s → 4s → 8s → 15s cap in the web app). Stop polling on terminal states completed, failed, or cancelled.

json
{
  "status": "processing",
  "stage": "tts",
  "stageProgress": 0.42,
  "videoUrl": null,
  "error": null
}
json
{
  "status": "completed",
  "videoUrl": "/temp/job_01HK8Z9X2YBN5T7QM3R4S5T6.mp4",
  "error": null,
  "completedAt": "2026-05-10T14:23:11.842Z"
}

Download the MP4

GET/api/v1/generate/:jobId/download

Streams the rendered MP4 as Content-Disposition: attachment. Files are retained for VIDEO_RETENTION_HOURS (default 24h) - fetch within the window. Returns 404 VIDEO_NOT_FOUND after expiry.

curl
curl -L \
  -H "X-API-Key: ck_live_••••••••••••••••" \
  -o video.mp4 \
  https://cutline.cloud/api/v1/generate/$JOB_ID/download

Cancel a job

POST/api/v1/generate/:jobId/cancel

Sets a Redis cancellation flag. The orchestrator checks the flag between every pipeline stage, so cancellation is eventual - the current stage finishes before the job exits. Returns 409 JOB_CANNOT_CANCEL if the job is already in a terminal state.

List recent jobs

GET/api/v1/generate/jobs

Returns up to 50 most recent jobs for the authenticated key, ordered by creation time descending. Pass ?limit=20 to truncate.

Webhooks

Pass callbackUrl when creating a job. When the job reaches a terminal state we POST the following payload:

json
{
  "jobId": "job_01HK8Z9X2YBN5T7QM3R4S5T6",
  "status": "completed",
  "videoUrl": "/temp/job_01HK8Z9X2YBN5T7QM3R4S5T6.mp4",
  "completedAt": "2026-05-10T14:23:11.842Z",
  "qualityReport": {
    "scriptStage": "ok",
    "ttsStage": "ok",
    "imageStage": "fallback_used",
    "renderStage": "ok",
    "retries": 1
  }
}

Delivery is fire-and-forget. We do not retry. 5-second timeout. Localhost URLs are rejected in production unless ALLOW_LOCALHOST_WEBHOOK=true.

Idempotency

Pass X-Idempotency-Key (max 128 chars) on POST to safely retry network failures. The same key within a 24h window returns the same jobId - duplicate work is never enqueued. We recommend a UUID per logical user-action.

Error codes

Branch on code, never on error. The error field is human copy and may be rewritten without a version bump.

ParameterTypeDescription
VALIDATION_FAILED400Input validation failed. details.errors lists field-level issues.
INVALID_JSON400Request body isn't valid JSON.
BAD_REQUEST400Generic bad request.
AUTH_REQUIRED401Missing or invalid API key.
ANON_LIMIT_REACHED403Anonymous-tier quota exhausted.
JOB_NOT_FOUND404No job with that ID.
VIDEO_NOT_FOUND404Video has been cleaned up after retention window.
JOB_NOT_READY404Tried to download before job completed.
JOB_CANNOT_CANCEL409Job is already in a terminal state.
RATE_LIMITED429Too many requests. Check Retry-After header.
INTERNAL_ERROR500Unhandled error. Safe to retry with the same idempotency key.

Rate limits

Per-IP and per-key limits, enforced by Redis with sliding windows.

  • 5/hour - POST /api/v1/generate per IP (anonymous)
  • 60/min - GET /api/v1/generate/:jobId per IP
  • 20/hour - POST /api/assets/upload per IP
  • Authenticated quotas are determined by your plan - see pricing.

429 responses include a Retry-After header (seconds).

Need a higher rate limit, an enterprise SLA, or custom integration support? parbhat@parbhat.work