webhookUrl (and webhookSecret) on POST .../generate-async, PDF Gorilla sends an HTTP POST to your URL when the job reaches a final state: completed, failed, or canceled.
Each delivery is signed so you can prove it came from PDF Gorilla and that the body was not changed.
Setup
Rules for webhookUrl
- Must use
https:// - Must be reachable from the public internet (no localhost)
- Your handler should return 2xx within about 5 seconds
Pick a strong secret
Generate one:Payload
Headers
| Header | Meaning |
|---|---|
Content-Type | application/json |
x-pdfg-event-id | Same as jobId (dedupe deliveries) |
x-pdfg-signature | HMAC-SHA256 of the raw body, hex encoded |
Completed job
Failed job
| Field | Notes |
|---|---|
downloadUrl | Only on completed. Short lifetime; fetch job status again if it expires. |
expiresAt | Present with downloadUrl on completed. |
error | { "code": "...", "message": "..." } on failure, else null. |
Verify the signature
Compute:x-pdfg-signature with a timing-safe compare. Use the raw request body string before parsing JSON. Re-serializing JSON breaks the signature.
Node.js
Python
Security checklist
Use timing-safe comparison, not plain
=== on strings.Verify the raw body, not a re-encoded copy of parsed JSON.
Use a unique secret per webhook endpoint.
Reply with 2xx quickly; slow handlers may time out.
Deduplicate using
x-pdfg-event-id / jobId in your handler.Only treat money-moving actions as done after you validate
status and signature.Download URL lifetime
Links in the webhook expire after a few minutes. If you need the file later, callGET /api/v1/jobs/{jobId} for a new URL. Stored files follow the retention rules in Limits.