Webhooks
Configure webhook endpoints, subscribe to events, verify signatures, and monitor delivery history.
Configure a Webhook
Set up your webhook endpoint URL, signing secret, and the events you want to receive. All payloads are HMAC-SHA256 signed for verification.
await client.webhooks.configure({
url: "https://your-app.com/webhooks/lendiq",
secret: "whsec_your_signing_secret",
events: [
"deal.created",
"deal.analysis_completed",
"document.extracted",
],
});client.webhooks.configure(
url="https://your-app.com/webhooks/lendiq",
secret="whsec_your_signing_secret",
events=[
"deal.created",
"deal.analysis_completed",
"document.extracted",
],
)Test Connectivity
const test = await client.webhooks.test();
console.log(test.success); // true
console.log(test.status_code); // 200
console.log(test.response_time_ms); // 142test = client.webhooks.test()
print(test.success) # True
print(test.status_code) # 200
print(test.response_time_ms) # 142Verify Signatures
Every webhook payload includes an X-LendIQ-Signature header containing an HMAC-SHA256 signature. Verify it against your signing secret to ensure the payload is authentic.
import { createHmac } from "crypto";
function verifyWebhook(payload: string, signature: string, secret: string): boolean {
const expected = createHmac("sha256", secret)
.update(payload)
.digest("hex");
return signature === `sha256=${expected}`;
}import hmac
import hashlib
def verify_webhook(payload: str, signature: str, secret: str) -> bool:
expected = hmac.new(
secret.encode(), payload.encode(), hashlib.sha256
).hexdigest()
return signature == f"sha256={expected}"Event Catalog
| Event | Category | Description |
|---|---|---|
deal.created | Deals | A new deal has been created and is queued for processing |
deal.analysis_completed | Deals | The full pipeline has completed. Decision and terms are available |
deal.decision_changed | Deals | The underwriting decision has been updated (e.g., after a re-run) |
document.classified | Documents | A document has been classified (bank statement, tax return, P&L) |
document.extracted | Documents | OCR extraction is complete. Transactions are ready for analysis |
document.failed | Documents | Document processing failed. Error details in payload |
pipeline.stage_completed | Pipeline | A single pipeline stage has finished |
pipeline.completed | Pipeline | All stages have completed successfully |
pipeline.failed | Pipeline | The pipeline encountered an unrecoverable error |
ruleset.triggered | Rules | A hard or soft decline rule was triggered during evaluation |
webhook.test | System | A test event dispatched from developer settings |
Example Payloads
Every webhook delivery includes the event type, a unique event ID, and the full resource data. Here are example payloads for the most common events.
deal.analysis_completed
{
"event": "deal.analysis_completed",
"event_id": "evt_abc123",
"created_at": "2026-03-29T14:32:00Z",
"data": {
"deal_id": 12345,
"business_name": "Acme Trucking LLC",
"health_score": 78.5,
"health_grade": "B",
"decision": "approved",
"confidence": 0.87,
"risk_tier": "tier_2",
"advance_amount": 50000,
"factor_rate": 1.35,
"mca_positions_detected": 2,
"processing_time_ms": 4200
}
}document.extracted
{
"event": "document.extracted",
"event_id": "evt_def456",
"created_at": "2026-03-29T14:31:55Z",
"data": {
"deal_id": 12345,
"document_id": 67890,
"document_type": "bank_statement",
"pages": 12,
"transactions_extracted": 347,
"date_range": { "start": "2026-01-01", "end": "2026-01-31" },
"extraction_method": "pdfplumber",
"tampering_status": "clean",
"quality_score": 94
}
}pipeline.failed
{
"event": "pipeline.failed",
"event_id": "evt_ghi789",
"created_at": "2026-03-29T14:31:50Z",
"data": {
"deal_id": 12345,
"stage": "extraction",
"error_code": "EXTRACTION_FAILED",
"error_message": "Unable to extract text from document — file may be image-only or corrupted",
"document_id": 67890,
"retry_eligible": true
}
}Info: All payloads are signed with HMAC-SHA256. Verify the
X-LendIQ-Signatureheader before processing — see the Verify Signatures section above.
Delivery History
const deliveries = await client.webhooks.deliveries({
page: 1,
per_page: 25,
success: true,
});
for (const d of deliveries.data) {
console.log(d.event, d.status_code, d.response_time_ms);
}deliveries = client.webhooks.deliveries(page=1, per_page=25, success=True)
for d in deliveries.data:
print(d.event, d.status_code, d.response_time_ms)