Veridact API Reference
Complete external API call inventory — function names, parameters, return types, timeouts, error shapes, and execution order. Extracted from source code · Updated 2026-05-07
Authentication
Two authentication schemes coexist — one for the portal (JWT cookies) and one for the Enterprise API (API key header).
| Scheme | Header / Mechanism | Used by |
|---|---|---|
| JWT (Portal) | Authorization: Bearer <token> or token cookie (7-day TTL) | All /api/* portal routes |
| API Key (Enterprise) | X-API-Key: vdc_live_<40-hex> | All /api/v1/* routes |
vdc_live_ + 40-character hex string. Legacy vrd_ prefix also accepted for backwards compatibility. Max 5 active keys per user.
Enterprise API — Key Management
| Endpoint | Method | Description |
|---|---|---|
POST /api/v1/keys | POST | Create a new API key (name required). Returns full key value once only. |
GET /api/v1/keys | GET | List all keys (masked). Returns id, name, key_prefix, created_at, last_used_at |
DELETE /api/v1/keys/:id | DEL | Revoke a key by ID. |
GET /api/v1/usage | GET | Returns per-key today/month stats from api_usage table. |
Rate Limits: Enterprise — 1,000 req/mo · Professional — 250 req/mo · Starter Screening — no API access. Headers: ratelimit-limit, ratelimit-remaining, ratelimit-reset, x-request-id
Standard Response Envelope
// All /api/v1/* responses follow this shape { "data": /* payload */, "meta": { "request_id": "uuid", "timestamp": "2026-05-07T18:00:00.000Z" } }
Environment Variables
pepchecker_usage. Results cached 30 days in pepchecker_cache.NODE_ENV !== 'production'. Falls back to PEPCHECKER_API_KEY if absent.POST /api/webhooks/stripe.Timeout Configuration
| Agent / Source | Per-Call Timeout | Global / Pipeline | Retry |
|---|---|---|---|
| Default fetchUrl (HTTP utility) | 10,000ms | — | 3× exponential backoff: 1.5s → 3s → 6s cap 8s. On 5xx, 429, 403, ECONNRESET, ETIMEDOUT. |
| PEPChecker.com API | 12,000ms | 30-day cache hit = no call | None (non-blocking failure) |
| OFAC API (api.ofac-api.com) | 8,000ms | — | None (non-blocking) |
| OpenSanctions API | 10,000ms | 5-min in-memory cache | None |
| NameScan PEP + Adverse Media | 10,000ms each | — | None (non-blocking) |
| Dilisense AML | 8,000ms | — | None |
| UN SC XML Feed | 12,000ms | 24-hour in-memory cache | None |
| EU FSF XML Feed | 12,000ms | 24-hour in-memory cache | None |
| UK HMT XML Feed | 12,000ms | 24-hour in-memory cache | None |
| OpenCorporates | 8,000ms | — | None |
| GLEIF LEI API | 12,000ms | — | None |
| UK Companies House API | 8,000ms per call | — | None |
| CourtListener (federal dockets) | 8,000ms → 12,000ms | — | 3× via fetchUrl |
| CourtListener (opinion search) | 12,000ms | — | 3× via fetchUrl |
| Offshore Leaks (ICIJ API) | 5,000ms | Local curated DB fallback | None |
| Litigation (all 14 sources) | 10,000ms each | runRealLitigationSearch: 20,000ms total | None (parallel via Promise.allSettled) |
| Wayback Machine CDX API | 10,000ms | — | None |
| Browser Deep Verification | 60,000ms | — | None (non-blocking) |
| Standard CDD Agent Pool (Parallel Dispatcher) | 30,000ms per agent | Total pipeline ≈ slowest agent | — |
Error Shapes
Agent-Level Error (all screening agents)
{
"matches": [], // or pep_matches / results — empty array
"queried": false,
"error": "agent_failed" // or the actual error message
}
API v1 HTTP Errors
| Status | Body | Cause |
|---|---|---|
400 | { "error": "...", "details": "..." } | Missing required params or invalid input |
401 | { "error": "Unauthorized" } | Missing or invalid X-API-Key |
403 | { "error": "Feature not available..." } | Subscription tier does not include feature |
404 | { "error": "Screening not found" } | ID does not belong to the API key owner |
429 | { "message": "Too many attempts..." } | Rate limit exceeded (monthly quota or 15-min auth window) |
500 | { "error": "Internal server error" } | Unhandled server exception |
Enterprise API — CDD Screening
Enterprise API — EDD Screening
Enterprise API — SOW Screening
Enterprise API — M&A Screening
Runs the full CDD pipeline with M&A-specific depth: entity enrichment + Yahoo Finance financial data + SEC EDGAR filings + litigation search + ESG screening. Uses generateMASummary() for AI summary.
Request Parameters
| Field | Type | Required | Notes |
|---|---|---|---|
query | string | required | Target company name |
entity_type | string | optional | Default: "company" |
jurisdiction | string | optional | Country / state code |
Enterprise API — Retrieve & List
| Endpoint | Method | Returns |
|---|---|---|
/api/v1/screening/:id | GET | Full screening result by ID (auth-scoped — only own records) |
/api/v1/screening/:id/report | GET | Full structured report JSON (same shape as portal report view) |
/api/v1/screenings | GET | Paginated list of own screenings. Query: ?page=1&limit=20&type=CDD |
Person Background Check — 7-Phase Pipeline
Implemented in person-check-orchestrator.js. Entry point: runPersonCheck(subject, pool). Results stored in person_checks, person_check_sources, person_check_findings tables.
-
1Input StandardizationFunction:
standardizeInputs(subject)→buildSearchUniverse(). Generates name variants (spelling map + nickname expansion), normalizes DOB toYYYY-MM-DD, extracts SSN-4 and location context. Outputs:nameVariants[],states[],dobYear,industryKey. No external calls.local only no API -
2Identity VerificationFunction:
runIdentityVerification(pool, personCheckId, subject, standardized). Queries OpenCorporates Officers API to cross-reference corporate registrations. Timeout: 10s viafetchUrl().OpenCorporates Officers GET api.opencorporates.com/v0.4/officers/search -
3Criminal & Court RecordsFunction:
runCriminalPhase(pool, personCheckId, subject, standardized, universe). Runs all aliases through CourtListener. Also checks OFAC SDN via public API fallback. State court portals generated for all states in subject's location history.CourtListener v3 Dockets (PACER) CourtListener v4 Opinion Search OFAC SDN (public fallback) State Court Portals (10 states — manual URLs) County Court URLs (name pre-filled) -
4RegistrySex offender registry (NSOPW + state portals), professional license databases (NPI, FINRA BrokerCheck, State Bar, FAA Airmen), Secretary of State corporate registries (30 states with direct officer-search URLs). All state-specific based on subject's location history.NSOPW (National Sex Offender Public Website) NPI Registry (healthcare) FINRA BrokerCheck State Bar Directories FAA Airmen Registry Secretary of State portals (30 states) PEPChecker.com
-
5Civil / PropertyBankruptcy records (PACER/CourtListener bankruptcy search), civil judgment liens, property records via county assessor links. Generates manual search URLs for each state in subject's history.CourtListener Bankruptcy County Assessor Links (state-scoped)
-
6Media / SocialGoogle News adverse media, Wikipedia cross-reference (disambiguation filter: requires both first AND last name in title/snippet, excludes disambiguation/sports pages), social media presence check. Also runs PEP/sanctions checks via PEPChecker and NameScan.Wikipedia API Google News RSS NameScan PEP+RCA+Adverse
-
7Corroboration + Confidence ScoringFunction:
calculateRiskScore(). Aggregates all findings with corroboration tags (name+DOB, name+location, name only). Generates final confidence level based on disambiguation context. Outputsrisk_score(0–100),risk_level,confidence_level, and source audit trail in DB.local scoring no external calls
Person Check API Endpoints
| Endpoint | Method | Notes |
|---|---|---|
/api/person-checks | POST | Trigger person check. Body: { first_name, last_name, middle_name?, dob?, aliases[], locations[], identifiers?, additional_identifiers? } |
/api/person-checks | GET | List own person checks |
/api/person-checks/:id | GET | Full result + findings list |
/api/person-checks/:id/pdf | GET | Download PDF report |
CDD Pipeline — Execution Phases
Implemented in orchestrator.js as runCDDPipeline(query, entityType, jurisdiction, options). All agents run via Promise.all() — total time ≈ slowest agent.
Phase 0 — Entity Enrichment
Function: enrichEntity(query, { entityType, jurisdiction }). Companies only. Resolves canonical legal name, ticker, CIK, jurisdiction before any screening. Feeds improved entity identity to all downstream agents.
Phase 1 — Base Agents (all run in parallel)
| Agent Function | Source | Tier | Timeout |
|---|---|---|---|
checkOFACApi() | api.ofac-api.com/v4/screen (POST) | All | 8s |
checkUNSanctions() | UN SC XML (24h cache) | All | 12s |
checkEUSanctions() | EU FSF XML (24h cache) | All | 12s |
checkUKHMTSanctions() | UK OFSI XML (24h cache) | All | 12s |
checkDilisense() | Dilisense AML API (GET) | All | 8s |
checkNameScan() | namescan.io PEP + Adverse Media (POST) | All | 10s × 2 |
checkPEPChecker() | pepchecker.com/api/v1/check (GET) | All | 12s (30d cache) |
fullSanctionsScreen() | OpenSanctions + OFAC + EU + UN + UK HMT (parallel) | All | 10s |
checkSanctions() | Curated local database (sync) | All | 0ms |
checkPEP() | Curated local database (sync) | All | 0ms |
checkAdverseMedia() | Curated database (sync) | All | 0ms |
checkOffshoreLeaks() | ICIJ API + curated DB (5s timeout) | All | 5s |
checkDebarment() | Curated database: WBG, AfDB, ADB, EBRD, IDB, SAM.gov, EU EDES, UN GC (sync) | All | 0ms |
runSearchEngineDueDiligence() | Google News RSS + Bing News + DuckDuckGo (OSINT) | All | 30s |
checkPublicCompanyStatus() | DuckDuckGo + SEC EDGAR + Yahoo Finance (companies) | All | 30s |
Phase 1b — Essentials+ Additional Agents (parallel)
| Agent Function | Source | Tier |
|---|---|---|
runGoogleSearchRegistry() | DuckDuckGo → registry page extraction (companies) | Essentials+ |
checkOpenCorporates() | api.opencorporates.com (free, 145+ jurisdictions) | Essentials+ |
checkCompaniesHouse() | api.company-information.service.gov.uk (UK) | Essentials+ |
checkGLEIF() | api.gleif.org/api/v1 (free, no key) | Essentials+ |
enrichFromYahooFinance() | Yahoo Finance quoteSummary API | Essentials+ |
Phase 2 — Financial DD (all tiers, companies — runs after Phase 1)
| Agent Function | Source | Notes |
|---|---|---|
runFinancialDueDiligence() | Search-engine-driven: SEC EDGAR, balance sheet, P&L (5 search categories in parallel) | Uses publicCompanyData from Phase 1 |
fetchPublicCompanyFinancials(ticker, cik) | FMP + SEC EDGAR XBRL + Alpha Vantage + Polygon + Yahoo Finance | Public companies only (ticker required) |
fetchPrivateCompanyFinancials(name) | D&B + Crunchbase | Private companies only |
runBrowserDeepVerification() | Headless browser → free corporate registries worldwide | Essentials+ only |
Phase 3 — Professional+ Tier (parallel)
| Agent Function | Sources | Tier |
|---|---|---|
runRealLitigationSearch() → searchLitigation() | 14 public sources (see Litigation Sources below). 20s total timeout. | Professional+ |
checkBankruptcy() | Curated + CourtListener bankruptcy dockets (sync) | Professional+ |
checkConsumerComplaints() | CFPB consumer complaint database (sync) | Professional+ |
checkESG() | Static curated ESG data (sync) | Professional+ |
fullESGScreen() | EPA ECHO + OSHA + World Bank (live) + UNGC + GRI + MAS + CSSF + WikiRate | Professional+ |
fullAdverseMediaScreen() | NewsAPI + GDELT + OCCRP + EventRegistry + MediaStack + TV (Enterprise) | Professional+ |
Phase 4 — Enterprise Only (parallel after Phase 3)
| Agent Function | Source | Tier |
|---|---|---|
checkArbitration() | Curated arbitration database (sync) | Enterprise |
checkWaybackMachine() | Wayback CDX API: archive.org/cdx/search/cdx | Enterprise |
fullBeneficialOwnershipCheck() | UK PSC (Companies House) + OpenOwnership API + GLEIF Ownership Tree + ICIJ Offshore Leaks | Enterprise |
Phase 5 — Finalization (sequential, after all parallel phases)
Country risk assessment → assessCountryRisk(), risk scoring → calculateRiskScore(), adverse media consolidation (NameScan + OSINT + Adverse Media Engine merged into single array), data gap detection, AI summary generation → generateSummary(), verification → runVerificationAgent().
Agent: PEPChecker.com
Agent: OFAC SDN
Function: checkOFACApi(query, entityType) in agents/ofac-api-agent.js. Primary: commercial API. Fallback: manual check URL when key absent.
Request Body (with key)
{
"apiKey": "...",
"minScore": 80,
"sources": ["SDN", "SSI", "NS-ISA", "FSE", "MBS", "CMIC", "GLOMAG", "NS-PLC", "UKRAINE-EO13662"],
"cases": [{ "name": "...", "type": "individual"|"entity" }]
}
Return Type
{
"matches": [{ matched_name, match_score, lists, list_name, program, severity, reason, entity_type, uid, risk_pts: 15 }],
"api_configured": true, "queried": true, "error": null
}
Timeout: 8s. Risk contribution: +15 pts per confirmed SDN hit. Severity: confirmed (score ≥95), potential (score 80–94).
Agent: OpenSanctions
Function: checkOpenSanctions(query, entityType, hints) in agents/opensanctions-api-agent.js. Covers OFAC, EU, UN, UK, FATF lists. 5-minute in-memory cache.
Request Body
POST https://api.opensanctions.org/match/sanctions { "queries": { "q0": { "schema": "Person"|"LegalEntity", "properties": { "name": ["..."] } } } }
Normalized Output
{
"matches": [{ matched_name, score, category: "SANCTIONS"|"PEP"|"WATCHLIST",
datasets, programs, reason, risk_pts, source_url }],
"pep_hits": 0, "sanction_hits": 0
}
Agent: NameScan
Function: checkNameScan(query, entityType). Runs two POST requests in parallel. Auth: api-key header. Env: NAMESCAN_API_KEY. Timeout: 10s each.
Request Body (both endpoints)
{ "name": "John Smith" }
Return Type
{
"pep_matches": [{ matched_name, match_score, category, role, country, active, severity }],
"adverse_media_hits": [{ title, url, published_date, source_label, category, sentiment, severity }],
"pep_queried": true, "media_queried": true
}
Agent: Dilisense AML
Function: checkDilisense(query, entityType) in agents/dilisense-agent.js. Env: DILISENSE_API_KEY. Timeout: 8s. GET request with name as query param. Covers global sanctions + PEP + criminal watchlists.
Agent: UN Security Council Consolidated List
Function: checkUNSanctions(query) in agents/un-sanctions-agent.js. Downloads full XML, parses in-memory with 24-hour TTL cache. No API key. Timeout: 12s. Risk: +15 pts per confirmed hit.
Agent: EU Financial Sanctions Files
Function: checkEUSanctions(query) in agents/eu-sanctions-agent.js. Daily-updated XML. In-memory 24h cache. No key. Fallback: data.europa.eu/api/hub/store/data/eu-consolidated-list-of-sanctions.xml. Risk: +12 pts per hit.
Agent: UK HMT / OFSI Sanctions
Function: checkUKHMTSanctions(query, minScore) in agents/uk-hmt-sanctions-agent.js. Two URL fallbacks. 24h in-memory cache. No key. Timeout: 12s. Schema: FinancialSanctionsTarget[].Names[].Name1–Name6. Risk: +12 pts per hit.
Agent: OpenCorporates
Function: checkOpenCorporates(query, entityType, jurisdiction). Also used in Phase 2 (identity) via /officers/search. No key required (free tier). Timeout: 8s.
Endpoints Used
| Endpoint | Purpose |
|---|---|
/v0.4/companies/search?q=...&jurisdiction_code=...&per_page=10 | Entity verification (Essentials+) |
/v0.4/officers/search?q=...&per_page=5 | Person identity (Phase 2 — all tiers) |
Return Type
{
"companies": [{ name, company_number, jurisdiction_code, company_type, current_status, incorporation_date, registered_address }],
"officers": [{ name, position, company.name, company.jurisdiction_code, opencorporates_url }],
"risk_pts": 0
}
Agent: GLEIF LEI Registry
Function: checkGLEIF(query, jurisdiction) in agents/gleif-agent.js. No API key required. Timeout: 12s. Essentials+ tier, companies only. Fetches LEI entity + relationship tree (parent / subsidiaries).
Endpoints Used
| Endpoint | Purpose |
|---|---|
/lei-records?filter[entity.names]=...&page[size]=5 | LEI lookup by name |
/lei-records/:lei/ultimate-parent-relationship | Ultimate parent (EDD beneficial ownership) |
/lei-records/:lei/direct-children | Subsidiary chain |
Return Type
{
"lei": "20-char-code", "entityName": "...",
"status": "ACTIVE|INACTIVE", "jurisdiction": "US",
"legalAddress": "...", "issuer": "...",
"directChildren": [], "ultimateParent": null,
"queried": true, "ran": true
}
Agent: UK Companies House
Function: checkCompaniesHouse(query, entityType, jurisdiction) in agents/companies-house-agent.js. Auth: Basic Auth (API key as username, empty password). Env: COMPANIES_HOUSE_API_KEY. Timeout: 8s per call.
Endpoints Used
| Endpoint | Purpose |
|---|---|
/search/companies?q=...&items_per_page=5 | Search by company name |
/company/:company_number | Company profile |
/company/:company_number/officers | Directors + officers |
/company/:company_number/persons-with-significant-control | PSC list (beneficial ownership) |
Return Type
{
"companies": [{ company_number, company_name, company_status, company_type, date_of_creation, registered_office_address }],
"officers": [{ name, officer_role, appointed_on, resigned_on, nationality }],
"psc_list": [{ name, kind, natures_of_control[], nationality, country_of_residence }],
"risk_pts": 0
}
Risk pts: +3 dissolved/struck off · +5 PSC not registered / exemption · +3 PSC in high-risk jurisdiction.
Agent: CourtListener / PACER
Used in both Person Check (Phase 3) and Litigation Search. Auth: optional Authorization: Token <COURTLISTENER_API_TOKEN>. Anonymous: 100 req/day. Authenticated: 5,000 req/hr.
Endpoints Used
| Endpoint | Purpose | Timeout |
|---|---|---|
/api/rest/v4/dockets/?q=...&order_by=score+desc&page_size=5 | Federal docket search (PACER) | 8s |
/api/rest/v4/search/?q=...&type=o&order_by=score+desc&page_size=5 | Full-text opinion search | 12s |
/api/rest/v3/dockets/ | Person check criminal phase (v3, legacy) | 10s |
Return Fields
{ "results": [{ case_name, docket_number, court, date_filed, nature_of_suit, absolute_url }] }
Litigation Sources (14 total)
Implemented in veridact-litigation.js as searchLitigation(params). All 14 sources run in parallel via Promise.allSettled(). Total timeout: 20,000ms. Professional+ tier.
| # | Source | URL / Endpoint | Notes |
|---|---|---|---|
| 1 | CourtListener / RECAP | courtlistener.com/api/rest/v4/dockets/ | Federal dockets, party-name match |
| 2 | Caselaw Access Project | api.case.law | Full-text published US decisions (Harvard Law) |
| 3 | SEC EDGAR Enforcement | efts.sec.gov/LATEST/search-index | Litigation releases + admin proceedings + stop orders |
| 4 | FINRA BrokerCheck | brokercheck.finra.org/search/firm | Broker/dealer disclosures, regulatory events, criminal |
| 5 | CFPB Complaints | api.consumerfinance.gov/data-research/consumer-complaints | Consumer financial violations + complaint database |
| 6 | FTC Actions | www.ftc.gov/api/v0/case-activities | Antitrust, consumer protection, privacy |
| 7 | DOJ Prosecutions | www.justice.gov/api/v1/press-releases.json | Criminal prosecutions, civil settlements + penalty extraction |
| 8 | EPA ECHO | echo.epa.gov/api/echo_facility_search | Clean Air, Clean Water, RCRA, Superfund violations |
| 9 | Violation Tracker | violationtracker.goodjobsfirst.org | 600k+ corporate violations, 100+ agencies |
| 10 | OCC Enforcement | apps.occ.gov/ead/api/cases | National bank enforcement actions + civil money penalties |
| 11 | FDIC Enforcement | banks.data.fdic.gov/api/enforcement | FDIC-insured institution enforcement decisions |
| 12 | BAILII | www.bailii.org/cgi-bin/markup.cgi | UK + Irish courts (search URL generation) |
| 13 | EUR-Lex | publications.europa.eu/webapi/rdf/sparql | EU Court of Justice via SPARQL endpoint |
| 14 | State Court Portals | 16 states with pre-built search URLs | Direct court portal links with name pre-filled |
Normalized Record Schema (all 14 sources)
{
source, type: "criminal"|"civil"|"regulatory"|"administrative"|"enforcement",
caseName, caseNumber, court, dateFiled, dateResolved,
status: "active"|"closed", outcome, penalty: 0,
description, url, jurisdiction, parties: [], charges: []
}
Agent: Offshore Leaks (ICIJ)
Function: checkOffshoreLeaks(query) in agents/offshore-leaks-agent.js. Tries live ICIJ API first (5s timeout), falls back to curated local database. No API key required. Enterprise API: 100 req/mo limit.
Agent: OSINT Search Engine Intelligence
Function: runSearchEngineDueDiligence(query, entityType, jurisdiction, options) in agents/search-engine-agent.js. Runs structured Boolean searches across 10 DD categories. Fallback/supplemental to API agents — primary source when API keys absent. Results labelled "Open Source Intelligence (OSINT)".
Categories Searched
sanctions · adverse_media · pep · litigation · regulatory · bankruptcy · esg · beneficial_ownership · financial · general
Agent: Financial Data Sources
Functions: fetchPublicCompanyFinancials(ticker, cik) and fetchPrivateCompanyFinancials(name) in agents/financial-data-sources.js. All tiers, companies only. Normalizes to ReportSchema financials section. Supplements runFinancialDueDiligence().
| Source | API Endpoint | Used for |
|---|---|---|
| FMP | financialmodelingprep.com/api/v3 | Income statement, balance sheet, cash flow |
| SEC EDGAR XBRL | data.sec.gov/api/xbrl/companyfacts/:cik.json | SEC-reported financials (public companies) |
| Alpha Vantage | alphavantage.co/query | Key statistics, overview |
| Polygon.io | api.polygon.io/v2/reference/financials | Financial statements |
| Yahoo Finance | quoteSummary API (via enrichFromYahooFinance()) | Company profile, officers, ownership, key stats |
| D&B / Crunchbase | Private endpoints | Private company financials |
Agent: Wayback Machine
Function: checkWaybackMachine(query, websiteHint) in agents/wayback-agent.js. Enterprise only. Queries Internet Archive CDX API. Timeout: 10s. No API key. Returns snapshot history, domain registration timeline, and content change indicators.
GET https://archive.org/cdx/search/cdx?url={domain}&output=json&limit=10&fl=timestamp,statuscode,mimetype
Source of Wealth — 9-Source Verification Framework
Implemented in agents/sow-agent.js. Functions: runVerificationWorkflow(), assessRiskTier(), evaluateRedFlags(), validateAttestation(), getJurisdictionalRequirements(). PDF ID format: VDC-XXXXXXXX-SOW. Corroboration gauge: 0–100.
| Step | Function | Description |
|---|---|---|
| 1 | assessRiskTier() | Classify LOW/MEDIUM/HIGH/CRITICAL based on risk score, PEP hits, sanctions, offshore hits, high-risk jurisdiction, high-value transaction flag, claimed wealth sources |
| 2 | evaluateRedFlags() | Detect red flags: PEP/sanctions in CDD results, offshore jurisdiction, unexplained wealth gap, multiple complex wealth structures, short-notice documentation |
| 3 | getJurisdictionalRequirements() | Return FATF / local regulatory requirements for stated jurisdiction |
| 4 | validateAttestation() | Validate subject-provided attestation for completeness and consistency |
| 5–9 | runVerificationWorkflow() | Employment / salary corroboration, business ownership verification, inheritance documentation review, investment portfolio cross-reference, property/asset registry search |
Webhooks
Delivered on screening completion. HMAC-SHA256 signed. Auto-disabled after ≥10 consecutive failures. 3-attempt backoff on delivery failure.
| Field | Value |
|---|---|
| Signature Header | X-Veridact-Signature: sha256=<hex> |
| Algorithm | HMAC-SHA256 over raw request body |
| Retry Policy | 3 attempts, exponential backoff |
| Auto-disable | After 10 consecutive delivery failures |
Webhook Payload Shape
{
"event": "screening.completed",
"screening_id": "uuid",
"screening_type": "CDD"|"EDD"|"SOW"|"MA",
"risk_score": 42,
"risk_level": "medium",
"sow_screening_id": "uuid-or-null",
"completed_at": "2026-05-07T18:00:00.000Z"
}