Receive real-time HTTP webhook notifications when Doc-Vision finishes processing documents with extracted data
DocVision sends HTTP webhooks to your server when documents are fully processed and indexed. This allows you to integrate document processing events into your own systems, workflows, or applications.
When a document completes processing:
Webhooks are only sent when documents reach INDEXED status, meaning extraction and indexing are complete. This ensures you receive complete, searchable document data.
Configure your webhook callback URL in Organization Settings > Webhooks section. Optionally configure a Webhook Signing Secret for enhanced security.
When a webhook signing secret is configured, DocVision includes signature headers (X-Webhook-Signature and X-Webhook-Timestamp) in all webhook requests. You can verify these signatures to ensure the webhook is authentic.
POST {your-endpoint-url}
When a webhook signing secret is configured:
Content-Type: application/jsonX-Webhook-Signature - HMAC-SHA256 signature of the payloadX-Webhook-Timestamp - Unix timestamp (milliseconds) when the webhook was sentUser-Agent: DocVision-Webhook/1.0{
"event": "document.ready",
"success": true,
"documentId": "doc_abc123xyz",
"status": {
"extractionStatus": "INDEXED",
"docType": "INVOICE",
...
},
"document": {
...
},
"extraction": {
"fields": {
...
},
"tables": {
"items": [
{
...
]
}
}
}
| Field | Type | Description |
|---|---|---|
event | string | Event type identifier. Currently always "document.ready" for document processing completion. Future events may be introduced. |
success | boolean | Always true for successful webhooks |
documentId | string | Unique identifier for the document |
| Field | Type | Description |
|---|---|---|
status.extractionStatus | string | Document extraction status (always "INDEXED" for webhooks) |
status.docType | string | null | Document type name (e.g., "INVOICE", "RECEIPT", "BANK_STATEMENT") |
status.createdAt | string | ISO 8601 timestamp when the document was created |
status.updatedAt | string | ISO 8601 timestamp when the document was last updated |
status.extractionErrors | array | null | Array of extraction errors (null if no errors) |
| Field | Type | Description |
|---|---|---|
document | object | null | Document summary information (null if extraction not complete) |
document.description | string | Document description/title |
document.totalAmount | number | Total amount extracted from the document |
document.documentDate | string | Document date (YYYY-MM-DD format) |
| Field | Type | Description |
|---|---|---|
extraction | object | null | Extracted document data (null if extraction failed or document has no data) |
extraction.fields | object | null | Header fields extracted from the document |
extraction.tables | object | null | Line items/tables extracted from the document |
The structure of extraction.fields and extraction.tables depends on your document type schema. Each document type defines its own header fields and line item collections. This format matches the Get API response format for consistency.
Your endpoint should return a 2xx status code (200, 201, 202, etc.) to indicate successful receipt.
Recommended Response:
{
"received": true,
"message": "Webhook processed successfully"
}
app.post('/webhook', express.json(), (req, res) => {
const { event, documentId, status, document, extraction } = req.body;
// Handle different event types
if (event === 'document.ready') {
console.log('Document ready:', documentId);
console.log('Status:', status.extractionStatus);
if (document) {
console.log('Document summary:', document.description);
console.log('Total amount:', document.totalAmount);
}
if (extraction) {
console.log('Extracted fields:', extraction.fields);
console.log('Extracted tables:', extraction.tables);
}
}
res.status(200).json({ received: true });
});When a webhook signing secret is configured, you should verify the signature to ensure the webhook is authentic and hasn't been tampered with.
import crypto from 'crypto';
function verifyWebhookSignature(
payload: string,
signature: string,
timestamp: string,
secret: string
): boolean {
const signaturePayload = `${timestamp}.${payload}`;
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(signaturePayload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
}
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
const signature = req.headers['x-webhook-signature'] as string;
const timestamp = req.headers['x-webhook-timestamp'] as string;
if (!verifyWebhookSignature(req.body.toString(), signature, timestamp, WEBHOOK_SECRET)) {
return res.status(401).json({ error: 'Invalid signature' });
}
const data = JSON.parse(req.body.toString());
// Process verified webhook...
res.status(200).json({ received: true });
});Use the Test Webhook button in Organization Settings > Webhooks section to send a test webhook to your configured endpoint URL.
The test webhook uses the same payload structure as production webhooks, allowing you to verify your endpoint is working correctly before processing real documents.
extraction may be null if extraction failed, document type doesn't have extractable fields, or document is still processingdocument may be null if extraction is not yet complete - check status.extractionStatus to see the current stateCurrently, webhooks are sent once. If your endpoint is unavailable, the webhook will not be retried. You can always use the Get API to retrieve document data that may have been missed.
Webhooks are sent for all documents that reach INDEXED status. Filter by status.docType in your webhook handler to process only specific document types.
Your endpoint must respond within 10 seconds. If processing takes longer, return a 200 response immediately and process the data asynchronously in the background.
Use webhooks for production integrations with high document volumes - they're more efficient and real-time. Use polling (see Upload + Polling Example) for simpler integrations, testing, or when you can't expose a public endpoint.
On This Page
OverviewHow It WorksSetupAPI ReferenceRequest MethodHeadersPayload FormatPayload FieldsTop-Level FieldsStatus ObjectDocument ObjectExtraction ObjectExpected ResponseCode ExamplesSignature VerificationTestingTroubleshootingWebhooks Not ReceivedInvalid Signature ErrorsTimeout ErrorsMissing Extracted DataFrequently Asked QuestionsDoes DocVision retry failed webhook deliveries?Can I receive webhooks for specific document types only?What is the webhook timeout?When should I use webhooks vs polling?Next Steps