Webhook Setup
Configure webhooks to receive real-time notifications when documents are processed.
Subscribe to real-time events from document processing workflows. Get notified instantly when documents are extracted or reviewed with secure, reliable webhook delivery.
Setting Up Webhooks
- Navigate to Events Page -- Go to your deployment and click "Events" in the left sidebar
- Add Webhook Subscription -- Click "Add Webhook" and enter your HTTPS endpoint URL
- Select Event Types -- Choose which events you want to receive:
DOCUMENT_EXTRACTED,DOCUMENT_REVIEWED, or both - Verify Your Endpoint -- Click "Verify URL" to confirm you control the endpoint and activate the subscription
URL Verification
Before activating your webhook subscription, LimAI verifies that you control the endpoint by sending a verification challenge.
- You click "Verify URL" for your webhook subscription
- LimAI sends a
VERIFICATIONevent to your endpoint with achallengevalue - Your endpoint must respond with the challenge value in the response body
- The subscription is marked as verified and activated
HMAC Signature Verification
All webhook events are signed with HMAC-SHA256 for authenticity verification. Each webhook subscription gets a unique secret key, and every request includes an X-Webhook-Signature header with the format sha256=<hex_digest>.
Always verify the signature before processing events.
const crypto = require("crypto")
const express = require("express")
function verifyWebhookSignature(payload, signature, secretKey) {
const expectedSignature = crypto
.createHmac("sha256", secretKey)
.update(payload)
.digest("hex")
const receivedSignature = signature.replace("sha256=", "")
return crypto.timingSafeEqual(
Buffer.from(expectedSignature, "hex"),
Buffer.from(receivedSignature, "hex")
)
}
app.post("/webhook", express.raw({ type: "application/json" }), (req, res) => {
const signature = req.headers["x-webhook-signature"]
const payload = req.body.toString()
if (!verifyWebhookSignature(payload, signature, process.env.WEBHOOK_SECRET)) {
return res.status(401).send("Invalid signature")
}
const event = JSON.parse(payload)
if (event.eventType === "VERIFICATION") {
return res.json({ challenge: event.challenge })
}
switch (event.eventType) {
case "DOCUMENT_EXTRACTED":
handleDocumentExtracted(event)
break
case "DOCUMENT_REVIEWED":
handleDocumentReviewed(event)
break
}
res.status(200).send("OK")
})Retry Policy
Failed webhook deliveries are retried with exponential backoff:
- Maximum retries: 5 attempts
- Backoff: Exponential, starting at 1 second
- Success criteria: Your endpoint must respond with a 2xx status code
Event Types
| Event | Description |
|---|---|
DOCUMENT_EXTRACTED | Fires when document processing completes (success or failure) |
DOCUMENT_REVIEWED | Fires when all rows in a document are accepted |
Retrieving Data from Webhooks
Webhook payloads contain metadata (file ID, schema ID, status) but not the actual extracted data. Use the get-file-data endpoint with the fileId from the webhook payload to retrieve the processed content.
Best Practices
- Always verify HMAC signatures before processing events
- Respond with 2xx status codes quickly to avoid timeouts
- Implement idempotency using the unique
eventIdto prevent duplicate processing - Process events asynchronously to avoid blocking the response
- Use HTTPS endpoints to protect data in transit
- Store webhook secret keys in environment variables