Async Jobs and Webhooks
Queue longer renders, poll job status, and receive webhook callbacks.
Synchronous captures are convenient for interactive use. Async jobs are better for long pages, full-page captures, authenticated dashboards, and batch pipelines.
Queue a job
json{ "url": "https://example.com/dashboard", "async": true, "webhook_url": "https://example.com/webhooks/screenframed", "device": "browser-macos", "background_preset": "midnight"}
Response:
json{ "job_id": "job_01K...", "status": "pending"}
Poll status
bashcurl "https://screenframed.com/v1/jobs/job_01K..." \ -H "Authorization: Bearer $SCREENFRAMED_API_KEY"
Completed jobs include the same render payload shape used by synchronous captures:
json{ "id": "job_01K...", "status": "completed", "result": { "id": "cap_01K...", "url": "https://cdn.screenframed.com/r/cap_01K....png", "width": 1600, "height": 900, "format": "png", "credits_used": 3 }, "error": null, "webhook_url": "https://example.com/webhooks/screenframed", "webhook_status": "delivered", "created_at": "2026-04-27 15:00:00", "completed_at": "2026-04-27 15:00:04"}
CLI polling
bashscreenframed capture https://example.com --asyncscreenframed jobs status job_01K... --watch
Webhook payloads
Success:
json{ "job_id": "job_01K...", "status": "completed", "result": { "id": "cap_01K...", "url": "https://cdn.screenframed.com/r/cap_01K....png" }}
Failure:
json{ "job_id": "job_01K...", "status": "failed", "error": "Render failed: target page did not finish loading"}
Operational guidance
Async capture readiness
Use stable input payloads
Keep the same URL and styling payload for retryable jobs so cached renders can be reused.
Store the job id
Persist job_id before returning from your own request handler.
Make webhooks idempotent
Treat duplicate webhook deliveries as possible and upsert by job_id.
All steps complete