API Reference

Base URL: https://api.html2reel.com

Authentication

Render endpoints use the X-API-Key header with a key from your dashboard. Account endpoints (/me, /me/keys) use a Bearer JWT from Kinde — intended for the dashboard, not for API clients.

POST /v1/reels

Submit a reel render job. Returns a job ID immediately (status 202).

Body

  • html (string, required) — the self-contained HTML template to render. Inline all CSS, JS, and asset URLs.
  • duration_seconds (float, required) — reel length. Hard cap is set per deployment (default 60).
  • width (int, optional) — viewport width in px. Defaults to the template's CSS body width.
  • height (int, optional) — viewport height in px. Defaults to the template's CSS body height.
  • fps (24 | 30 | 60, default 30).
  • audio_url (string, optional) — background audio. Muxed with auto fade-out over the last 1.5 s (clamped to one quarter of the reel length on very short clips).
  • callback_url (string, optional) — webhook target for async delivery. SSRF-validated.

Response (202)

{"job_id":"abc-123","status":"queued"}

GET /v1/reels/{id}

Status + result for a render job (scoped to your API key). Whilequeued or processing the response carries a Retry-After: 10 header — honour it instead of tight-looping.

# queued / processing  (Retry-After: 10)
{"status":"queued","url":null,"error":null}

# done — url is the rendered mp4 on R2
{"status":"done","url":"https://.../result.mp4","error":null}

# failed
{"status":"failed","url":null,"error":"..."}

Webhook payload

When callback_url is set, html2reel POSTs the final state (with retries: immediate, +30 s, +5 min) when the job reaches done or failed:

{"job_id":"abc-123","status":"done","url":"https://.../result.mp4","error":null}

GET /me

(Bearer JWT) Current user + list of active (non-revoked) API keys.

POST /me/keys

(Bearer JWT) Create a new API key.

# Request
{"label":"Production"}

# Response (201) — raw key shown ONCE
{"id":"...","label":"Production","key_prefix":"h2r_a1b2c3d4","key":"h2r_a1b2c3d4...","created_at":"..."}

DELETE /me/keys/{id}

(Bearer JWT) Soft-delete a key. Subsequent requests with it return 401.

Errors

  • 400 — invalid callback_url (not http(s) or resolves to a private address).
  • 401 — missing/invalid/revoked key, or bad JWT.
  • 403 — account pending approval (key creation gated during beta).
  • 404 — unknown job ID (or owned by another key).
  • 422 — malformed request body (e.g. missing html).