Skip to main content

How renders work

  1. Upload or import media (if needed) — local files: POST /v1/uploads; remote URLs (share links, YouTube): POST /v1/imports. Skip if files are already on a CDN you control. See Uploading media and Importing remote media.
  2. Submit a POST /v1/renders request with your composition — dimensions, elements, transitions, and output settings.
  3. Job enqueued — the API returns 202 Accepted with a render_* job ID and status: queued.
  4. GPU engine processes — the Framelane Renderer runs on dedicated GPU hardware.
  5. Wait for completion — poll GET /v1/renders/{id} until status is terminal, or receive a render.completed / render.failed webhook.
  6. Download — use output.url from the job response, or GET /v1/renders/{id}/download for a fresh signed redirect.

Job lifecycle

queued  →  processing  →  completed
                       ↘  failed
                       ↘  cancelled
StatusDescription
queuedWaiting in the render queue
processingGPU engine is compositing
completedArtifact available at output.url
failedSee error.code for cause
cancelledStopped via DELETE /v1/renders/{id}

Idempotency

Every render submission should include an Idempotency-Key header to safely retry without double-submitting:
Idempotency-Key: my-project-render-v3
If you resubmit the same key within 24 hours:
  • Same body200 OK with the existing job (no new charge)
  • Different body409 Conflict

Endpoints

MethodPathDescription
POST/v1/rendersSubmit a render job
GET/v1/rendersList renders (cursor-paginated)
GET/v1/renders/{id}Get a single render
DELETE/v1/renders/{id}Cancel a queued render
GET/v1/renders/{id}/downloadRedirect to signed artifact URL

Minimal example

{
  "width": 1920,
  "height": 1080,
  "duration": 10.0,
  "frame_rate": 30,
  "output_format": "mp4",
  "elements": [
    {
      "type": "video",
      "id": "clip1",
      "source_url": "https://cdn.example.com/input.mp4",
      "time": 0,
      "in_point": 0,
      "out_point": 10
    },
    {
      "type": "text",
      "id": "title",
      "text": "Hello World",
      "time": 0,
      "duration": 5,
      "x": "50%",
      "y": "50%",
      "font_size": 72,
      "text_color": "#ffffff"
    }
  ]
}
The correct field names are time (start on the output timeline), duration (how long the element is visible), and text_color (not color). Using wrong field names results in a 422 validation error.