Webhooks Integration Guide
Receive real-time notifications when events occur in DocLD.
Overview
Webhooks let your application receive HTTP callbacks when:
- Documents finish processing
- Extractions complete
- Workflows execute
- Other events occur
Setting Up Webhooks
1. Create a Webhook Endpoint
Set up an endpoint in your application to receive webhooks:
// Express.js example
app.post('/webhooks/docld', (req, res) => {
const event = req.body;
switch (event.event) {
case 'document.completed':
handleDocumentCompleted(event.data);
break;
case 'extraction.completed':
handleExtractionCompleted(event.data);
break;
}
// Respond quickly
res.status(200).send('OK');
});2. Register the Webhook
Configure your webhook URL in DocLD:
Dashboard:
- Go to Settings → Webhooks
- Click Add Webhook
- Enter your endpoint URL
- Select events to receive
- Save
API:
curl -X POST "/api/webhooks" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"url": "https://your-app.com/webhooks/docld",
"events": ["document.completed", "extraction.completed"]
}'Webhook Events
Document Events
| Event | When |
|---|---|
document.uploaded | Document uploaded |
document.processing | Processing started |
document.completed | Processing finished |
document.failed | Processing failed |
Extraction Events
| Event | When |
|---|---|
extraction.started | Extraction began |
extraction.completed | Extraction finished |
extraction.failed | Extraction failed |
Workflow Events
| Event | When |
|---|---|
workflow.started | Workflow execution began |
workflow.completed | Workflow finished |
workflow.failed | Workflow failed |
Webhook Payload
All webhooks follow this structure:
{
"event": "document.completed",
"timestamp": "2024-01-15T10:30:00Z",
"webhook_id": "webhook-uuid",
"data": {
// Event-specific data
}
}Document Completed
{
"event": "document.completed",
"timestamp": "2024-01-15T10:30:00Z",
"data": {
"id": "doc-uuid",
"name": "invoice.pdf",
"status": "completed",
"file_type": "pdf",
"pages": 5,
"processing_time_ms": 3500
}
}Extraction Completed
{
"event": "extraction.completed",
"timestamp": "2024-01-15T10:30:00Z",
"data": {
"extraction_id": "ext-uuid",
"document_id": "doc-uuid",
"schema_id": "schema-uuid",
"overall_confidence": 0.95,
"data": {
"invoice_number": "INV-001",
"total_amount": 1250.00
}
}
}Verifying Webhooks
Signature Verification
Webhooks include a signature for verification:
X-DocLD-Signature: sha256=abc123...Verify the signature:
const crypto = require('crypto');
function verifyWebhook(payload, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(JSON.stringify(payload))
.digest('hex');
return `sha256=${expected}` === signature;
}
// In your endpoint
app.post('/webhooks/docld', (req, res) => {
const signature = req.headers['x-docld-signature'];
const secret = process.env.WEBHOOK_SECRET;
if (!verifyWebhook(req.body, signature, secret)) {
return res.status(401).send('Invalid signature');
}
// Process webhook...
});Async Parsing Webhooks
When using /api/parse/async, specify a webhook URL:
curl -X POST "/api/parse/async" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"input": "https://example.com/document.pdf",
"webhook_url": "https://your-app.com/webhooks/parse"
}'When parsing completes, you’ll receive:
{
"job_id": "job-uuid",
"status": "completed",
"result": {
"chunks": [...],
"metadata": {...}
},
"usage": {
"num_pages": 5,
"credits": 7.5
}
}Split completion webhooks
For POST /api/split/run (when the job runs asynchronously) and POST /api/split/batch, you can pass a webhook_url. DocLD will POST to that URL when each split job completes or fails. You can also configure a per-organization webhook in Settings → Webhooks (or org integrations); it is used when no per-request URL is provided.
Payload fields: event (split.completed or split.failed), job_id, document_id, status, sections_summary (array of section_id, name, page_start, page_end, type), results_url (link to the dashboard), error (if failed), and timestamp.
Example for a completed split:
{
"event": "split.completed",
"job_id": "split-job-uuid",
"document_id": "doc-uuid",
"status": "completed",
"sections_summary": [
{ "section_id": "sec-1", "name": "Introduction", "page_start": 1, "page_end": 5, "type": "section" }
],
"results_url": "https://app.docld.com/split?job=split-job-uuid",
"timestamp": "2024-01-15T10:30:00Z"
}See the Split API reference for the full payload shape.
Handling Webhooks
Best Practices
- Respond quickly - Return 200 within 30 seconds
- Process async - Queue work, don’t block
- Verify signatures - Always validate authenticity
- Handle duplicates - Webhooks may be sent multiple times
- Log payloads - Keep records for debugging
Async Processing
Queue webhook handling for reliability:
const Queue = require('bull');
const webhookQueue = new Queue('webhooks');
app.post('/webhooks/docld', async (req, res) => {
// Verify signature first
if (!verifyWebhook(req.body, req.headers['x-docld-signature'])) {
return res.status(401).send('Invalid');
}
// Queue for async processing
await webhookQueue.add(req.body);
// Respond immediately
res.status(200).send('OK');
});
// Process in background
webhookQueue.process(async (job) => {
const event = job.data;
// Handle the event...
});Idempotency
Handle duplicate webhooks:
const processedEvents = new Set();
async function handleWebhook(event) {
const eventKey = `${event.event}-${event.timestamp}-${event.data.id}`;
if (processedEvents.has(eventKey)) {
console.log('Duplicate event, skipping');
return;
}
processedEvents.add(eventKey);
// Process event...
}Retry Policy
Failed deliveries are retried:
| Attempt | Delay |
|---|---|
| 1 | Immediate |
| 2 | 1 minute |
| 3 | 5 minutes |
| 4 | 30 minutes |
| 5 | 2 hours |
After 5 failures, the webhook is marked as failed.
Testing Webhooks
Local Development
Use ngrok for local testing:
ngrok http 3000
# Use the ngrok URL as your webhook endpointTest Events
Send test events from the dashboard:
- Go to Settings → Webhooks
- Select your webhook
- Click Test
- Choose an event type
Troubleshooting
Webhook Not Received
- Verify URL is accessible from internet
- Check firewall/security rules
- Confirm HTTPS is working
- Review webhook logs in dashboard
Invalid Signature
- Ensure secret matches configuration
- Verify payload is not modified
- Check signature header is present
Timeouts
- Respond within 30 seconds
- Process work asynchronously
- Use queuing for heavy work