Webhooks
Webhooks let you receive real-time HTTP notifications when async conversions and batch jobs complete. No polling required.
Creating Webhook Endpoints
There are two ways to use webhooks with pdfRelay:
1. Per-request webhooks
Include a webhook_url in your async or batch request:
{
"html": "<h1>Report</h1>...",
"webhook_url": "https://your-app.com/webhooks/pdfrelay"
}2. Account-level webhooks
Configure a default webhook endpoint in your dashboard under Settings → Webhooks. This endpoint receives notifications for all async and batch jobs that do not specify their own webhook_url.
Event Types
| Event | Description |
|---|---|
job.completed | An async conversion job completed successfully |
job.failed | An async conversion job failed |
batch.completed | All items in a batch have finished processing |
batch.item.completed | An individual item in a batch completed (opt-in) |
Webhook Payload
pdfRelay sends a POST request to your webhook URL with a JSON body:
{
"event": "job.completed",
"timestamp": "2025-01-15T10:30:02Z",
"data": {
"job_id": "job_abc123def456",
"status": "completed",
"download_url": "https://api.pdfrelay.com/v1/jobs/job_abc123def456/download",
"pages": 3,
"size_bytes": 45678,
"conversion_ms": 1250
}
}HMAC Signature Verification
Every webhook request includes an HMAC-SHA256 signature in the X-PdfRelay-Signature header. Verify this signature to ensure the request came from pdfRelay.
Your webhook signing secret is available in your dashboard under Settings → Webhooks.
Verification Example (Node.js)
import crypto from 'crypto';
function verifyWebhookSignature(
payload: string,
signature: string,
secret: string
): boolean {
const expected = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
// In your webhook handler:
app.post('/webhooks/pdfrelay', (req, res) => {
const signature = req.headers['x-pdfrelay-signature'];
const isValid = verifyWebhookSignature(
JSON.stringify(req.body),
signature,
process.env.PDFRELAY_WEBHOOK_SECRET
);
if (!isValid) {
return res.status(401).json({ error: 'Invalid signature' });
}
// Process the webhook event
const { event, data } = req.body;
console.log(`Received ${event} for job ${data.job_id}`);
res.status(200).json({ received: true });
});Retry Behavior
If your webhook endpoint returns a non-2xx status code or times out (30-second timeout), pdfRelay will retry the delivery with exponential backoff:
| Attempt | Delay |
|---|---|
| 1st retry | 1 minute |
| 2nd retry | 5 minutes |
| 3rd retry | 30 minutes |
| 4th retry | 2 hours |
| 5th retry (final) | 24 hours |
After 5 failed attempts, the webhook delivery is marked as failed. You can view failed deliveries and trigger manual retries from the dashboard.
Important
Your webhook endpoint must respond within 30 seconds and return a 2xx status code. Always return a response quickly and process the webhook payload asynchronously if needed.