Webhooks
Process screenshots asynchronously and receive notifications when they're ready.
How It Works
- Send a screenshot request with a webhook URL
- Receive immediate response with job ID
- Screenshot processes in the background
- Receive webhook POST when complete
Configuration
{ "url": "https://example.com", "webhook": { "url": "https://your-server.com/webhooks/screenshots", "events": ["completed", "failed"], "secret": "whsec_xxxxx" } }
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
url |
string | — | Webhook endpoint URL (required) |
events |
array | ["completed"] |
Events to receive |
secret |
string | account default | Webhook signing secret |
Events
| Event | Description |
|---|---|
completed |
Screenshot captured successfully |
failed |
Screenshot capture failed |
Initial Response
When webhook is configured, the request returns immediately:
{ "id": "job_abc123", "status": "processing", "webhook": "https://your-server.com/webhooks/screenshots" }
Webhook Payload
Completed Event
{ "event": "screenshot.completed", "id": "job_abc123", "timestamp": "2024-01-18T12:00:00Z", "data": { "url": "https://example.com", "image": { "url": "https://cdn.renderscreenshot.com/xyz789.png", "width": 1200, "height": 630, "size": 123456, "format": "png" }, "cache": { "key": "cache_xyz789", "url": "https://cdn.renderscreenshot.com/xyz789.png", "expires_at": "2024-01-19T12:00:00Z" }, "metadata": { "title": "Example Domain", "description": "Example description" }, "usage": { "credits": 1, "remaining": 9999 } } }
Failed Event
{ "event": "screenshot.failed", "id": "job_abc123", "timestamp": "2024-01-18T12:00:00Z", "data": { "url": "https://example.com", "error": { "type": "target_error", "code": "timeout", "message": "Page failed to load within 30 seconds", "retryable": true } } }
Webhook Headers
POST /webhooks/screenshots HTTP/1.1 Host: your-server.com Content-Type: application/json X-Webhook-ID: whk_abc123 X-Webhook-Timestamp: 1705579200 X-Webhook-Signature: sha256=a1b2c3d4e5f6... User-Agent: RenderScreenshot-Webhook/1.0
Verifying Signatures
Verify webhook authenticity using the signature:
Ruby
def verify_webhook(payload, signature, timestamp, secret) expected = OpenSSL::HMAC.hexdigest( 'SHA256', secret, "#{timestamp}.#{payload}" ) Rack::Utils.secure_compare("sha256=#{expected}", signature) end # In your controller signature = request.headers['X-Webhook-Signature'] timestamp = request.headers['X-Webhook-Timestamp'] payload = request.raw_post if verify_webhook(payload, signature, timestamp, ENV['WEBHOOK_SECRET']) # Process webhook else head :unauthorized end
Node.js
const crypto = require('crypto'); function verifyWebhook(payload, signature, timestamp, secret) { const expected = crypto .createHmac('sha256', secret) .update(`${timestamp}.${payload}`) .digest('hex'); return `sha256=${expected}` === signature; } // In your route handler const signature = req.headers['x-webhook-signature']; const timestamp = req.headers['x-webhook-timestamp']; const payload = JSON.stringify(req.body); if (verifyWebhook(payload, signature, timestamp, process.env.WEBHOOK_SECRET)) { // Process webhook } else { res.status(401).send('Invalid signature'); }
Python
import hmac import hashlib def verify_webhook(payload, signature, timestamp, secret): expected = hmac.new( secret.encode(), f"{timestamp}.{payload}".encode(), hashlib.sha256 ).hexdigest() return hmac.compare_digest(f"sha256={expected}", signature)
Retry Policy
Failed webhook deliveries are retried:
| Attempt | Delay |
|---|---|
| 1 | Immediate |
| 2 | 1 minute |
| 3 | 5 minutes |
| 4 | 30 minutes |
| 5 | 2 hours |
After 5 failed attempts, the webhook is marked as failed.
Responding to Webhooks
Return a 2xx status code to acknowledge receipt:
HTTP/1.1 200 OK
Any non-2xx response triggers a retry.
Batch Webhooks
For batch requests, receive a single webhook when all screenshots complete:
{ "event": "batch.completed", "id": "batch_abc123", "timestamp": "2024-01-18T12:00:00Z", "data": { "summary": { "total": 10, "completed": 9, "failed": 1 }, "results_url": "https://api.renderscreenshot.com/v1/batch/batch_abc123/results" } }
Common Patterns
Async Social Card Generation
{ "url": "https://myblog.com/post/123", "preset": "og_card", "webhook": { "url": "https://myblog.com/api/webhooks/og-image", "events": ["completed", "failed"] } }
Background Processing Pipeline
{ "url": "https://example.com", "webhook": { "url": "https://api.myservice.com/process-screenshot", "secret": "whsec_custom_secret" }, "storage": { "enabled": true } }
Examples
Request with Webhook
curl -X POST https://api.renderscreenshot.com/v1/screenshot \ -H "Authorization: Bearer rs_live_xxxxx" \ -H "Content-Type: application/json" \ -d '{ "url": "https://example.com", "preset": "og_card", "webhook": { "url": "https://myserver.com/webhooks/screenshots", "events": ["completed", "failed"] } }'
Response:
{ "id": "job_abc123", "status": "processing", "webhook": "https://myserver.com/webhooks/screenshots" }
Testing Webhooks
Use tools like webhook.site or ngrok to test webhooks locally.
See Also
- Batch Screenshots - Batch processing with webhooks
- Error Codes - Understanding error responses
- Storage Options - Combine with storage upload