Wait and SSE

Long-poll or stream status instead of tight polling loops.

POST /api/v1/render returns 202 with status: "queued" immediately (unless you pass ?wait=).

ClientPattern
Backend with a public URLWebhooks
Scripts / CLIsGET /api/v1/renders/{id}/wait
Browser UIsGET /api/v1/renders/{id}/events (SSE)
Last resortPoll GET /api/v1/renders/{id} with backoff

Avoid tight polling on status — those checks are rate-limited.

Long-poll wait

GET /api/v1/renders/{id}/wait?timeout=30
Authorization: Bearer sk_...
  • 200 — terminal (done or failed), same body as get status
  • 202 — still in progress; response includes retryAfterMs — open another wait
  • timeout defaults to 30s and is capped at 60s (unlike POST /render?wait=, which allows up to 120s)

You can also block on create: POST /api/v1/render?wait=60 (max 120 seconds).

Server-Sent Events

GET /api/v1/renders/{id}/events
Accept: text/event-stream

Streams event: status until the job is terminal, then closes. Works well with a session cookie on the app origin.

Download the asset

When status is done, fetch:

GET /api/v1/renders/{id}/asset

Streams the file bytes (HTTP 200). assetUrl on the job includes ?sig= so <img> / og:image can fetch without an API key. A Bearer token still works on the unsigned path.

On this page