Skip to main content
Ssnap Docs
API Reference

Async callbacks

Queue a capture and receive the result as a signed webhook.

Slow pages, batch jobs and anything you do not want to block on should use the async mode: pass callback_url and the API returns 202 immediately, then POSTs the result to your endpoint when the render finishes.

curl -X POST https://ssnap.cc/api/v1/screenshot \
  -H "Authorization: Bearer $SSNAP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/heavy-report",
    "format": "pdf",
    "network_idle": true,
    "callback_url": "https://your-app.com/hooks/ssnap"
  }'
Immediate response (202)
{
  "status": "queued",
  "message": "Screenshot queued; the result will be delivered to the callback URL."
}

202 only means the job was accepted. Subscription, quota and url checks run when the job executes, so failures arrive at your webhook, never as the HTTP response.

Callback requirements

callback_url passes the same public-host checks as url: http/https only, no loopback, private, link-local or reserved targets. See URL restrictions.

The host is re-checked a second time at delivery, immediately before the POST, because a job may run long after it was validated and DNS can be repointed in between.

Payloads

Delivered as POST with Content-Type: application/json.

Success
{
  "status": "success",
  "url": "https://ssnap.cc/screenshots/0193ab…/file?expires=…&signature=…",
  "cached": false
}
Failure
{
  "status": "error",
  "error": "Monthly screenshot limit reached",
  "code": "quota_exceeded"
}

The url is signed and valid for 24 hours, so download the file promptly if you need to keep it. code values are the same set listed in API error codes.

Signature headers

HeaderValue
X-Ssnap-TimestampUnix timestamp of the delivery attempt.
X-Ssnap-Signaturesha256= + HMAC-SHA256 of "<timestamp>.<raw body>", keyed with your webhook secret.

Verify against the raw request body, before any JSON parsing, and reject deliveries whose timestamp is far from now to blunt replays. Worked examples in Verify webhook signatures.

Retries and delivery guarantees

  • The capture job itself retries up to 3 times, backing off 10s then 30s, with a 120-second timeout per attempt.
  • The webhook POST is retried up to 3 times, 500 ms apart, with a 10-second timeout.
  • A delivery that still fails is logged and dropped. It does not re-run the capture, because a retry would consume a second quota slot for an image that already exists.

Design your handler to be idempotent and to return 2xx quickly; do the heavy work after acknowledging.

Async vs sync

AspectSyncAsync
ResponseBytes or signed url202 acknowledgement
Good forInteractive requests, small pagesHeavy pages, PDFs, batch jobs
Failure reaches you asHTTP status + codeWebhook with "status": "error"
Needs a public endpointNoYes

Next