Bank Statements — Docs Intelligence
Docs Intelligence — Bank Statement Analysis
Upload bank statements to get a comprehensive Financial Health Profile and Fraud Risk Profile. The system produces scored, reasoned, and explained assessments calibrated specifically for African financial markets.
Two Profiles, One Call: Every analysis produces both a Financial Health Profile (creditworthiness) and a Fraud Risk Profile (fraud detection), each with LLM-generated narratives that explain what the patterns mean and what to do about them.
What You Get
Financial Health Profile
- 4 Dimension Scores (0-100): Revenue, Cash Flow, Expense and Liability, Balance Behaviour — each rated Strong / Adequate / Weak / Insufficient
- 6 African Market Signals: Tontine Intelligence, Mobile Money Shadow Balance, Bancarization Quality, Calendar-Adjusted Stress, Social Capital, Diaspora Income
- Credit Readiness Score (0-100) with credit limit band
- LLM Narrative (3-5 paragraphs) explaining the financial picture
- Recommendations: Additional documents, conditions, monitoring
Fraud Risk Profile
- Fraud Score (0-100) with verdict: Proceed / Proceed with conditions / Refer / Decline
- Individual flags with dimension, pattern, confidence, cross-dimensional corroboration
- Named anomaly clusters: Pre-Application Staging, Circular Flow, Ghost Business, Debt-Driven Distress, Dangerous Payer Concentration
- LLM Fraud Narrative explaining each significant signal
API Endpoints
| Method | Endpoint | Description |
|---|---|---|
POST | /api/v1/bank-statements/upload | Upload and analyze |
GET | /api/v1/bank-statements | List with pagination |
GET | /api/v1/bank-statements/{id} | Full analysis detail |
GET | /api/v1/bank-statements/{id}/report | Download PDF report |
DELETE | /api/v1/bank-statements/{id} | Delete statement and report |
GET | /api/v1/bank-statements/preferences | Get analysis defaults |
PUT | /api/v1/bank-statements/preferences | Update analysis defaults |
Upload and Analyze
POST https://api.tryenvoyx.com/api/v1/bank-statements/uploadRequest Fields
| Field | Type | Required | Description |
|---|---|---|---|
file | File | Yes | PDF, JPEG, or PNG (max 20MB) |
business_type | string | No | e.g. healthcare_provider, retail, agriculture |
sector | string | No | e.g. healthcare, commerce, services |
account_holder_name | string | No | Expected name for comparison matching |
Parameter Priority: request param, then saved preference, then system default. Set defaults via the Preferences API.
Streaming
Add X-Stream-Response: true header for real-time Server-Sent Events through all 14 processing steps.
Code Examples
curl -X POST https://api.tryenvoyx.com/api/v1/bank-statements/upload \
-H "X-API-Key: YOUR_API_KEY" \
-F "file=@bank_statement.pdf" \
-F "business_type=healthcare_provider" \
-F "sector=healthcare"const formData = new FormData()
formData.append('file', fs.createReadStream('bank_statement.pdf'))
formData.append('business_type', 'healthcare_provider')
const response = await fetch('https://api.tryenvoyx.com/api/v1/bank-statements/upload', {
method: 'POST',
headers: { 'X-API-Key': 'YOUR_API_KEY' },
body: formData,
})
const { data } = await response.json()
console.log('Credit Readiness:', data.bank_statement.fh_credit_readiness_score)
console.log('Fraud Verdict:', data.bank_statement.fraud_risk_verdict)import requests
with open('bank_statement.pdf', 'rb') as f:
response = requests.post(
'https://api.tryenvoyx.com/api/v1/bank-statements/upload',
headers={'X-API-Key': 'YOUR_API_KEY'},
files={'file': f},
data={'business_type': 'healthcare_provider'},
)
stmt = response.json()['data']['bank_statement']
print(f"Credit Readiness: {stmt['fh_credit_readiness_score']}/100")
print(f"Fraud Verdict: {stmt['fraud_risk_verdict']}")The Four Dimensions (0-100 each)
Each dimension is scored 0-100 and rated:
| Score | Rating |
|---|---|
| 80-100 | Strong |
| 60-79 | Adequate |
| 40-59 | Weak |
| 0-39 | Insufficient |
Revenue Analysis
Classifies every inflow by source: institutional payments, mobile money sweeps, cash deposits, tontine receipts, related-party transfers, diaspora transfers. Evaluates consistency against what this business type actually earns and on what cycle.
Cash Flow Health
Measures how the business manages gaps between major inflows. In markets where institutional payers clear every 60-90 days, the inter-cycle floor is the real stress test. Identifies mobile money and tontine liquidity bridges.
Expense and Liability Patterns
Identifies what a real operating business should be spending on and whether those expenses are present. Separates tontine from debt service, personal from operational. Assesses total visible debt load including mobile credit apps.
Balance Behaviour
Analyses balance patterns for timing manipulation (pre-application conditioning), survival behaviour between inflows, and trend over the full period.
African Market Signals
Six proprietary signals calibrated for how money actually moves in West Africa:
| Signal | Output | What It Measures |
|---|---|---|
| Tontine Intelligence | 0-100 score + rating | Tontine participation consistency as credit character evidence |
| Mobile Money Shadow Balance | Range estimate (e.g. 400K-900K XOF) | Inferred off-statement wealth from sweep patterns |
| Bancarization Quality Index | 0-100 score + confidence | What proportion of real financial activity the statement captures |
| Calendar-Adjusted Stress | Raw + adjusted scores + delta | Normalizes stress against WAEMU calendar (Ramadan, Tabaski, harvest) |
| Social Capital Signal | Present / Weak / Absent | Social consequences for default from reciprocal networks |
| Diaspora Income Share | Percentage + stability rating | Concentration risk from cross-border family inflows |
Credit Readiness Score
The composite score (0-100) is a weighted combination:
| Dimension | Weight |
|---|---|
| Revenue | 30% |
| Cash Flow | 25% |
| Expense and Liability | 25% |
| Balance Behaviour | 20% |
Adjusted by: African market signal bonus/penalty (up to 5 points), legitimacy gate (cap at 20 if document not legitimate).
The score maps to a credit limit band calibrated to the currency (e.g. "500K-2M XOF").
Fraud Risk Score and Verdict
| Score Range | Verdict |
|---|---|
| 0-25 | Proceed — no material fraud signals |
| 26-50 | Proceed with conditions — signals detected but likely explainable |
| 51-75 | Refer — significant signals warrant human investigation |
| 76-100 | Decline — high-confidence cross-dimensional fraud pattern |
Named Anomaly Clusters
When flags from multiple dimensions point to the same pattern, they are grouped into named clusters:
- Pre-Application Staging — fabricated activity near application date
- Circular Flow / Manufactured Inflow — coordinated deposit rings
- Ghost Business — missing expected operating expenses
- Debt-Driven Distress — loan stacking across multiple lenders
- Dangerous Payer Concentration — over-reliance on single income source
Processing Pipeline (14 Steps)
| Step | Description |
|---|---|
| 1 | Starting analysis |
| 2 | Downloading from storage |
| 3 | Validating document format |
| 4 | Running AI analysis (longest step) |
| 5 | Evaluating revenue patterns |
| 6 | Assessing cash flow health |
| 7 | Evaluating expense and liability |
| 8 | Analyzing balance behaviour |
| 9 | Computing African market signals |
| 10 | Generating financial health profile |
| 11 | Running fraud detection |
| 12 | Computing fraud risk score |
| 13 | Generating reasoning narratives |
| 14 | Finalizing (PDF generation, name comparison, duplicate check) |
PDF Report
Every analyzed statement generates a PDF report accessible via:
GET https://api.tryenvoyx.com/api/v1/bank-statements/{id}/reportReturns a presigned URL for the PDF. The report includes both profiles, all scores, narratives, flags, anomaly clusters, and recommendations — formatted for credit committee review.
Webhook Events
| Event | Description |
|---|---|
bank_statement.uploaded | Statement uploaded (async mode) |
bank_statement.processing | Analysis in progress (14 steps) |
bank_statement.analyzed | Analysis complete, no critical issues |
bank_statement.flagged | Analysis complete, fraud flags detected |
bank_statement.failed | Analysis error |
See Webhooks for setup and WebSockets for real-time streaming.
Preferences API
Set defaults so you do not pass business_type and sector with every upload.
curl -X PUT https://api.tryenvoyx.com/api/v1/bank-statements/preferences \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"default_business_type": "healthcare_provider", "default_sector": "healthcare"}'await fetch('https://api.tryenvoyx.com/api/v1/bank-statements/preferences', {
method: 'PUT',
headers: { 'X-API-Key': 'YOUR_API_KEY', 'Content-Type': 'application/json' },
body: JSON.stringify({ default_business_type: 'healthcare_provider', default_sector: 'healthcare' }),
})Tip: For production, use webhooks instead of polling. Subscribe to bank_statement.analyzed and bank_statement.flagged to receive results when ready.