Async jobs & webhooks

Synchronous requests (the default) hold the connection until the render finishes — perfect for interactive use. For batch workloads, add async: true:

POST /v1/pdf
{ "url": "https://example.com/report", "async": true, "webhook_url": "https://yourapp.com/hooks/renders" }

→ 202 Accepted
{ "id": "0d4f…", "status": "queued", "status_url": "/v1/jobs/0d4f…" }

Polling

GET /v1/jobs/:id          → { "status": "queued|processing|succeeded|failed", "result_url": …, "error": … }
GET /v1/jobs/:id/result   → the binary (also linked from result_url)

Results stay retrievable for 24 hours (or your cache_ttl, if longer).

Webhooks

If you pass webhook_url, we POST when the job finishes:

{
  "id": "0d4f…",
  "status": "succeeded",
  "product": "pdf",
  "content_type": "application/pdf",
  "bytes": 81235,
  "result_url": "https://rasterkit.com/v1/jobs/0d4f…/result"
}

Deliveries are signed like Stripe's: X-RasterKit-Signature: t=<unix>,v1=<hmac> where v1 = HMAC-SHA256(signing_secret, t + "." + raw_body). Verify both the signature and that t is recent. Failed deliveries retry 3 times (5 s, 30 s backoff).

Webhook URLs are SSRF-checked like render targets — private/internal addresses are refused.