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=).
Recommended patterns
| Client | Pattern |
|---|---|
| Backend with a public URL | Webhooks |
| Scripts / CLIs | GET /api/v1/renders/{id}/wait |
| Browser UIs | GET /api/v1/renders/{id}/events (SSE) |
| Last resort | Poll 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 (
doneorfailed), same body as get status - 202 — still in progress; response includes
retryAfterMs— open another wait timeoutdefaults to 30s and is capped at 60s (unlikePOST /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-streamStreams 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}/assetStreams 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.