Skip to main content

Webhooks

Webhooks let Parselyze notify your application when an async job completes or fails.

How It Works

  1. Configure a webhook URL in the dashboard
  2. Optionally configure a webhook secret
  3. Submit async jobs as usual
  4. Receive document.completed or document.failed events

Configuration

Set your webhook URL and optional secret in your account settings in the Parselyze dashboard.

Recommended

Always configure a webhook secret in production so you can verify the request signature.

Request Headers

Parselyze sends:

Content-Type: application/json
User-Agent: Parselyze-Webhook/1.0

If a secret is configured, Parselyze also sends:

X-Webhook-Signature: <hex_hmac_sha256_signature>

Payload

Successful job example:

{
"eventId": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"eventType": "document.completed",
"jobId": "550e8400-e29b-41d4-a716-446655440000",
"status": "completed",
"result": {
"invoice": {
"number": "INV-2025-001",
"total": 1250.75
}
},
"pageCount": 3,
"pageUsed": 3,
"pageRemaining": 1497,
"timestamp": "2026-03-31T10:30:45.123Z"
}

Failed job example:

{
"eventId": "8d0f7780-8536-51f6-c938-668877662222",
"eventType": "document.failed",
"jobId": "660f9511-f3ac-52e5-b827-557766551111",
"status": "failed",
"result": null,
"error": "Document could not be read.",
"timestamp": "2026-03-31T10:32:15.456Z"
}

Field Reference

FieldTypeDescription
eventIdstringUnique identifier for this webhook event
eventTypestringdocument.completed or document.failed
jobIdstringAsync job identifier
statusstringcompleted or failed
resultobject|nullParsed JSON when successful
errorstringError message when failed
pageCountnumberTotal page count, when available
pageUsednumberPages consumed for the job, on success
pageRemainingnumberRemaining quota after the job, on success
timestampstringISO timestamp for the event

Retry Semantics

  • Delivery timeout: 10 seconds
  • Max delivery attempts: 3
  • Retries happen on network errors, timeouts, 429, and 5xx
  • 4xx responses other than 429 are not retried

Important:

  • The same webhook event is retried if delivery fails
  • eventId stays the same across retries for that event
  • Your handler should therefore be idempotent

Signature Verification

If you configured a webhook secret, compute:

  1. the raw request body as a string or bytes
  2. an HMAC-SHA256 digest using your secret
  3. compare it to X-Webhook-Signature

Node.js Example

import crypto from 'crypto';
import express from 'express';

const app = express();

app.use(express.raw({ type: 'application/json' }));

app.post('/webhook', (req, res) => {
const signature = req.header('X-Webhook-Signature');
const secret = process.env.PARSELYZE_WEBHOOK_SECRET;

if (!signature || !secret) {
return res.status(401).send('Missing signature configuration');
}

const expected = crypto.createHmac('sha256', secret).update(req.body).digest('hex');

if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) {
return res.status(401).send('Invalid signature');
}

const event = JSON.parse(req.body.toString('utf8'));
console.log(event.eventType, event.jobId);

return res.status(200).send('OK');
});

Best Practices

  • Verify the signature when a secret is configured
  • Return 200 quickly and do heavy work asynchronously
  • Store processed eventId or jobId + eventType to avoid duplicate handling
  • Log failures and monitor retry patterns