Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallSome links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
Receive a PDF-generation webhook with a dedicated POST route, preserve the provider’s raw request body, verify its signature before parsing or acting on the event, validate the documented event fields, and acknowledge the request according to that provider’s delivery rules. The exact header, signature format, event names, retry policy and PDF-download workflow are provider-specific; there is no universal PDF webhook standard.
What a PDF webhook receiver does
An asynchronous PDF service accepts a conversion or generation job, works on it after your initial request, and later sends an HTTP POST to a callback URL. Your Node.js application must expose a publicly reachable HTTPS route, authenticate the callback, identify the job event, update your own job state, and usually queue any slow follow-up work such as downloading or storing the file.
- Use a separate route such as
POST /webhooks/pdf. - Keep the signing secret in server-side configuration, never in browser code or source control.
- Verify the exact raw body required by the provider before trusting its contents.
- Accept only documented event types and required fields.
- Return the status code and within the time window specified by the provider.
Build an Express receiver that preserves the raw body
JSON middleware parses and re-serializes a request. Even semantically identical JSON can have different bytes, so parsing first can invalidate a signature. Attach express.raw() to the webhook route before any global JSON parser handles it.
import express from 'express';
const app = express();
const port = process.env.PORT || 3000;
// Other application routes may use express.json(), but this route needs raw bytes.
app.post('/webhooks/pdf',
express.raw({ type: 'application/json', limit: '1mb' }),
async (req, res) => {
try {
// Replace this function with the selected provider's official verifier.
const event = await verifyAndParseProviderEvent(req.body, req.headers);
if (!event || typeof event.type !== 'string') {
return res.sendStatus(400);
}
switch (event.type) {
case 'provider.documented.success-event': {
// Validate the provider's required identifiers and output details.
// Persist the state or enqueue a download; do not trust unchecked fields.
console.log('PDF completed', event);
break;
}
case 'provider.documented.failure-event': {
console.error('PDF failed', event);
break;
}
default:
// Acknowledge or reject unknown events exactly as the provider documents.
console.warn('Unhandled PDF event', event.type);
}
return res.sendStatus(200);
} catch (error) {
console.error('Webhook rejected', error);
return res.sendStatus(400);
}
}
);
app.listen(port, () => console.log(`Listening on ${port}`));
async function verifyAndParseProviderEvent(rawBody, headers) {
throw new Error('Implement the selected provider's documented verification');
}
The placeholder is deliberate: substituting an HMAC recipe from another vendor is unsafe. Configure the provider to call your deployed HTTPS URL, for example https://api.example.com/webhooks/pdf, and set the route’s body-size and accepted-content-type limits to values appropriate for that provider.
#1 Best Overall
Verify signatures before using the payload
Use the provider’s official method
Signature conventions differ in header name, timestamp encoding, signed-message construction, digest representation, supported versions and clock tolerance. Follow the selected provider’s current documentation and SDK. Reject a failed verification rather than processing the event.
OpenAI’s Webhooks API guide states: “While you can receive webhook events from OpenAI and process the results without any verification, you should verify that incoming requests are coming from OpenAI, especially if your webhook will take any kind of action on the backend.” Its Node SDK provides client.webhooks.unwrap(rawBody, headers), which verifies and parses the event. It expects the raw JSON string and must be awaited; do not call JSON.parse first.
Provider-specific examples
- PDFGate documents an
x-pdfgate-signatureheader containing a timestamp and one or morev1signatures, with a default five-minute maximum age and a verifier helper. - UsePDFMaker documents an asynchronous signed callback and shows raw-body handling; parsing JSON first changes the signed bytes.
- RelayPDF documents timestamp-plus-raw-body HMAC verification and the event names
job.completedandjob.failed. Those names are not a universal contract.
These formats are not interchangeable. Confirm the package version, header spelling, timestamp tolerance and secret configuration in the provider’s current documentation before deploying.
Recommended Free Tools
Rank #2
Parse, validate and dispatch documented events
Authenticity only tells you who signed the message. It does not guarantee that the event has the fields your application expects or that the job is still in a usable state.
- Verify the raw body and headers.
- Check that the parsed value is an object and that its event type is a string.
- Validate the documented event or delivery identifier, job identifier, status, error details and output reference before storing them.
- Use an allowlist of event types. Handle completion and failure separately when the provider documents both.
- Persist the verified event or enqueue follow-up work, then acknowledge promptly if the provider permits asynchronous processing.
Keep a durable record keyed by the provider’s documented event or delivery ID when available. This makes duplicate deliveries harmless. Do not invent retry or deduplication assumptions: providers differ in whether they retry, how long they wait, and which response codes trigger delivery again.
OpenAI Node example
For an OpenAI webhook, the raw body must remain a string. Because Express raw middleware supplies a Buffer, convert it without parsing and pass the original headers to the SDK’s verifier.
Rank #3
import express from 'express';
import OpenAI from 'openai';
const app = express();
const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
app.post('/webhooks/openai', express.raw({ type: 'application/json' }), async (req, res) => {
try {
const rawBody = req.body.toString('utf8');
const event = await client.webhooks.unwrap(rawBody, req.headers);
switch (event.type) {
case 'your.documented.success-event':
// Validate IDs and enqueue PDF follow-up work.
break;
case 'your.documented.failure-event':
// Record the documented failure fields.
break;
default:
console.log('Ignoring documented-but-unhandled event:', event.type);
}
res.sendStatus(200);
} catch (error) {
console.error('Invalid OpenAI webhook:', error);
res.sendStatus(400);
}
});
Use the signing secret supplied by the provider’s webhook settings. Never expose it to a client-side application.
Test the route locally and in deployment
Send an unsigned smoke test
This checks routing and content-type handling only; it does not prove signature verification.
curl -i -X POST http://localhost:3000/webhooks/pdf
-H 'content-type: application/json'
--data '{"type":"provider.documented.success-event","job_id":"test-job"}'
Your verifier should reject this request if the selected provider requires a signature. Use the provider’s official CLI, test helper or a genuinely signed fixture for an end-to-end test.
Rank #4
Check the deployed callback
- Use HTTPS and ensure your reverse proxy forwards the request body unchanged.
- Confirm the route is reachable without a login page or CSRF token intended for browser forms.
- Check that the proxy, framework and serverless platform accept the provider’s body size and content type.
- Log request IDs, verification outcomes and event IDs, but never log secrets or complete sensitive PDF payloads.
Failure modes and fixes
| Symptom | Likely cause | Fix |
|---|---|---|
| Every signature fails | JSON middleware ran first, the wrong secret is configured, or the wrong header/algorithm is used. | Put route-specific raw middleware first and copy the selected provider’s current verifier exactly. |
req.body is an object instead of bytes |
A global express.json() parser consumed the request. |
Exclude the webhook path from the global parser or register the raw route before it. |
| Valid callbacks time out | The handler downloads or processes a large PDF inline. | Persist the verified event, enqueue work and return according to the provider’s acknowledgment rules. |
| Events are processed twice | The provider retried or the endpoint delivered a duplicate. | Store and check the documented delivery/event identifier before applying state changes. |
| Unknown event causes errors | The provider added an event your switch does not recognize. | Use an explicit default branch and follow the provider’s policy for acknowledging unknown events. |
| Callback works locally but not remotely | Private address, missing TLS, proxy routing or firewall issue. | Deploy a public HTTPS route and inspect proxy access logs and provider delivery logs. |
Choose a PDF provider on the dimensions that matter
Compare services on four concrete questions: does the provider offer an official Node verifier; which completion, failure and job identifiers are documented; what retry, timeout and deduplication behavior is specified; and how is the finished PDF retrieved or stored? The available provider documentation establishes differences in signatures and event coverage, but not a universal timeout or retry guarantee.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Or skip the browser setup
If your goal is a clean image or PDF capture rather than operating a browser yourself, ScreenshotNeo provides a one-call website screenshot API and MCP server. It accepts cookie and consent banners before capture and removes more than 60 known consent platforms, newsletter popups and chat widgets. Bot checks, blank pages, timeouts, failed loads and cache hits are not billed, and response headers identify the page verdict and billing result.
For a screenshot request, see the ScreenshotNeo API documentation:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
The service also offers an MCP server with take_screenshot, get_page_info and capture_pdf for Claude, Cursor and other MCP clients. The Free plan includes 1,000 shots per month without a card; paid plans start at $5 for 3,000 shots. Sign up for the free plan.
Operational checklist
- Public HTTPS callback configured at the exact path.
- Raw-body middleware registered before JSON parsing.
- Secret stored in server-side configuration.
- Official signature verifier, timestamp rules and header names implemented.
- Event type and required fields validated.
- Completion and failure states persisted separately where documented.
- Slow PDF retrieval moved to a queue or background worker.
- Duplicate handling based on a documented identifier.
- Logs exclude secrets and unnecessary document content.
- Provider-specific retry and acknowledgment behavior tested with signed fixtures.
FAQ
Can I use one generic HMAC function for every PDF API?
No. Header names, signed bytes, timestamp rules and digest formats vary, so use the selected provider’s official SDK or documented algorithm.
Should the webhook endpoint return 200 for an unknown event?
Only if that provider’s delivery contract says unknown events should be acknowledged. Otherwise follow its documented rejection behavior.
Is a verified webhook safe to execute blindly?
No. Verification establishes authenticity, while schema and state validation protect your application from malformed or unexpected data.
Frequently Asked Questions
Can I use one generic HMAC function for every PDF API?
No. Header names, signed bytes, timestamp rules and digest formats vary, so use the selected provider’s official SDK or documented algorithm.
Should the webhook endpoint return 200 for an unknown event?
Only if that provider’s delivery contract says unknown events should be acknowledged. Otherwise follow its documented rejection behavior.
Is a verified webhook safe to execute blindly?
No. Verification establishes authenticity, while schema and state validation protect your application from malformed or unexpected data.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

