Core API
Webhooks
Get notified the moment a document finishes parsing — no polling required.
Register a webhook
curl -X POST https://api.lumiparser.com/v1/webhooks \
-H "Authorization: Bearer inv_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-app.com/webhooks/invoices",
"events": ["invoice.completed", "invoice.failed"]
}'Response:
{
"id": "wh_abc123",
"url": "https://your-app.com/webhooks/invoices",
"events": ["invoice.completed", "invoice.failed"],
"active": true,
"created_at": "2024-01-20T10:00:00Z",
"secret": "3f9a…c21e"
}The secret is returned only once, at creation. Store it as WEBHOOK_SECRET to verify signatures. Webhook URLs must be public https:// addresses.
Events
| Event | When it fires |
|---|---|
| invoice.completed | Parse finished successfully — parsed and confidence are populated |
| invoice.failed | Parse failed — check the error field on the invoice |
Webhook payload
{
"event": "invoice.completed",
"invoice_id": "inv_a1b2c3d4e5f6g7h8",
"timestamp": "2024-01-20T10:30:05Z"
}Fetch the full parsed result with GET /v1/invoices/:id using the invoice_id from the payload.
Verifying signatures
Every webhook request includes an X-Signature-256 header. Verify it to confirm the request came from us and hasn't been tampered with.
const crypto = require('crypto');
function verifyWebhook(rawBody, signature, secret) {
const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(rawBody)
.digest('hex');
if (typeof signature !== 'string' || signature.length !== expected.length) return false;
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
// Express example
app.post('/webhooks/invoices', express.raw({ type: '*/*' }), async (req, res) => {
const sig = req.headers['x-signature-256'];
const secret = process.env.WEBHOOK_SECRET;
if (!verifyWebhook(req.body, sig, secret)) {
return res.status(401).send('Invalid signature');
}
const event = JSON.parse(req.body.toString());
if (event.event === 'invoice.completed') {
// Fetch full result and process
const invoice = await fetchInvoice(event.invoice_id);
await processInvoice(invoice);
}
res.send({ received: true });
});Retries
If your endpoint returns a non-2xx status, we make up to 3 attempts, waiting 1s and then 2s between them (each attempt times out after 10s). After the third failure the delivery is abandoned. Make your webhook handler idempotent — the same event may be delivered more than once.
Manage webhooks
# List all webhooks
GET /v1/webhooks
# Remove a webhook
DELETE /v1/webhooks/:id