Bank Account Statement Analysis (Kenya)
Authorization
ApiKeyAuth X-API-Key<token>
In: header
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Request payload for Bank Account Statement Analysis (Kenya). Fields vary by channel type.
Response Body
application/json
curl -X POST "https://example.com/api/v1/verification/api/bank_statement_analysis/" \ -H "Content-Type: application/json" \ -d '{}'{ "data": { "meta": { "source_format": "json", "engine_version": "1.0.0", "timings_seconds": { "risk": 0.0001, "total": 0.0218, "anomaly": 0, "scoring": 0.0003, "signals": 0.0005, "advisory": 0.0003, "behavior": 0.0008, "cashflow": 0.0009, "grouping": 0.0002, "forensics": 0.0021, "ingestion": 0.0133, "affordability": 0.001, "categorization": 0.0017 }, "transaction_count": 1 }, "risk": { "findings": [ null ], "available": true, "red_flags": [ null ], "risk_band": "minimal", "indicators": { "gambling": { "present": false, "total_won": 0, "active_days": 0, "stake_count": 0, "net_position": 0, "total_staked": 0, "monthly_stake": 0, "recovery_ratio": 0, "share_of_income": 0, "share_of_outflow": 0 }, "liquidity": { "available": true, "min_balance": 233250, "average_balance": 233250, "balance_trend_pct": 0, "liquidity_buffer_days": "", "negative_balance_share": 0, "ends_higher_than_starts": false }, "income_risk": { "source_count": 1, "income_trend_pct": 0, "income_volatility": 0, "has_regular_salary": true, "income_stability_score": 60 }, "concentration": { "top_payees": [ null ], "unique_payees": 0, "payee_concentration_gini": 0, "income_concentration_gini": 0 }, "credit_stress": { "digital_lenders": [ null ], "repayment_count": 0, "penalty_fee_count": 0, "penalty_fee_total": 0, "debt_service_ratio": 0, "digital_lender_count": 0, "monthly_debt_service": 0, "borrow_to_repay_ratio": 0, "loan_disbursement_count": 0, "loan_disbursement_total": 0, "fixed_obligations_monthly": 0 }, "account_conduct": { "fee_share": 0, "fees_total": 0, "dormant_days": 0, "activity_rate": 1, "digital_share": 0, "reversal_count": 0, "cash_dependency": 0 }, "spending_pressure": { "savings_rate": 1, "discretionary_share": 0, "post_payday_burn_rate": "", "expense_to_income_ratio": 0, "lifestyle_inflation_pct": 0 } }, "risk_score": 0 }, "source": { "md5": "6d28629ecec9c93f8d82647249830ddc", "sha256": "91e6d909fe17edb9350130ab89d946d8912853928f00fd753af4057f2012b6b7", "filename": "api-payload.json", "file_size": 506, "is_scanned": false, "page_count": 0, "text_density": 0, "source_format": "json", "extraction_method": "direct-json" }, "status": "completed", "account": { "email": "", "branch": "", "currency": "KES", "bank_code": "", "bank_name": "Equity Bank Kenya", "period_end": "2026-08-31", "customer_id": "", "account_name": "GRACE ATIENO", "account_type": "", "generated_at": "", "period_start": "2026-08-01", "phone_number": "", "account_number": 170294851632, "statement_type": "bank", "closing_balance": 149736.65, "opening_balance": 48250, "masked_account_number": "*********1632" }, "scoring": { "grade": "E", "verdict": { "grade": "E", "score": 35.7, "persona": { "label": "Balanced spender", "traits": [ "salaried" ] }, "summary": [ "Regular salary of about 185,000 per month." ], "headline": "Poor financial health (grade E, 36/100). Profile: Balanced spender.", "risk_band": "minimal", "authenticity_status": "tampered" }, "decision": { "outcome": "reject", "reasons": [ "Statement authenticity failed verification." ] }, "penalties": [ { "points": 45, "reason": "Document shows conclusive evidence of tampering" } ], "scorecard": [ { "band": "none", "code": "BEH_SAVINGS_BEHAVIOUR", "name": "Savings and investment share", "unit": "ratio", "value": 0, "domain": "behaviour", "impact": -1, "points": 0, "weight": 1 } ], "confidence": { "band": "low", "level": 43.4, "limitations": [ "Less than 3 months of history; seasonality and recurrence cannot be verified." ], "history_months": 0.03, "signal_coverage": 0.889, "transaction_count": 1 }, "grade_label": "Poor", "domain_scores": { "credit": { "score": 100, "coverage": 1, "available": 5, "signal_count": 5 }, "income": { "score": 82.7, "coverage": 1, "available": 7, "signal_count": 7 }, "cashflow": { "score": 88.9, "coverage": 1, "available": 6, "signal_count": 6 }, "behaviour": { "score": 71.4, "coverage": 0.875, "available": 7, "signal_count": 8 }, "integrity": { "score": 67.4, "coverage": 0.6, "available": 3, "signal_count": 5 }, "liquidity": { "score": 88.5, "coverage": 0.8, "available": 4, "signal_count": 5 } }, "raw_composite": 86.7, "domain_contributions": [ { "score": 100, "domain": "credit", "weight": 0.2, "contribution": 20 } ], "financial_health_score": 35.7 }, "signals": { "signals": [ { "band": "strong", "code": "INC_MONTHLY", "name": "Median monthly earned income", "unit": "currency", "value": 185000, "domain": "income", "weight": 1, "polarity": "higher_better", "band_index": 4, "normalized": 100, "description": "Median of monthly income excluding loans, refunds and internal transfers." } ], "by_domain": { "credit": [ { "band": "minimal", "code": "CRD_DSR", "name": "Debt service ratio", "unit": "ratio", "value": 0, "domain": "credit", "weight": 1.5, "polarity": "lower_better", "band_index": 0, "normalized": 100, "description": "Monthly loan and card repayments divided by monthly income." } ], "income": [ { "band": "strong", "code": "INC_MONTHLY", "name": "Median monthly earned income", "unit": "currency", "value": 185000, "domain": "income", "weight": 1, "polarity": "higher_better", "band_index": 4, "normalized": 100, "description": "Median of monthly income excluding loans, refunds and internal transfers." } ], "cashflow": [ { "band": "strong", "code": "CF_SAVINGS_RATE", "name": "Savings rate", "unit": "ratio", "value": 1, "domain": "cashflow", "weight": 1.4, "polarity": "higher_better", "band_index": 4, "normalized": 100, "description": "(inflow - outflow) / inflow across the observed period." } ], "behaviour": [ { "band": "none", "code": "BEH_GAMBLING_INCOME", "name": "Gambling as share of income", "unit": "ratio", "value": 0, "domain": "behaviour", "weight": 1.6, "polarity": "lower_better", "band_index": 0, "normalized": 100, "description": "Monthly betting stakes divided by monthly income." } ], "integrity": [ { "band": "acceptable", "code": "INT_AUTHENTICITY", "name": "Document authenticity score", "unit": "score", "value": 87, "domain": "integrity", "weight": 2, "polarity": "higher_better", "band_index": 3, "normalized": 75, "description": "100 minus the weighted tamper and ledger-inconsistency score." } ], "liquidity": [ { "band": "strong", "code": "LIQ_AVG_BALANCE", "name": "Average balance", "unit": "currency", "value": 233250, "domain": "liquidity", "weight": 1, "polarity": "higher_better", "band_index": 4, "normalized": 100, "description": "Mean of the running balance across the period." } ] }, "strengths": [ { "band": "strong", "code": "INC_MONTHLY", "name": "Median monthly earned income", "unit": "currency", "value": 185000, "domain": "income", "weight": 1, "polarity": "higher_better", "band_index": 4, "normalized": 100, "description": "Median of monthly income excluding loans, refunds and internal transfers." } ], "weaknesses": [ { "band": "narrow", "code": "INC_SOURCES", "name": "Distinct income sources", "unit": "count", "value": 1, "domain": "income", "weight": 0.6, "polarity": "higher_better", "band_index": 1, "normalized": 25, "description": "Number of distinct counterparties contributing earned income." } ], "total_count": 36, "domain_scores": { "credit": { "score": 100, "coverage": 1, "available": 5, "signal_count": 5 }, "income": { "score": 82.7, "coverage": 1, "available": 7, "signal_count": 7 }, "cashflow": { "score": 88.9, "coverage": 1, "available": 6, "signal_count": 6 }, "behaviour": { "score": 71.4, "coverage": 0.875, "available": 7, "signal_count": 8 }, "integrity": { "score": 67.4, "coverage": 0.6, "available": 3, "signal_count": 5 }, "liquidity": { "score": 88.5, "coverage": 0.8, "available": 4, "signal_count": 5 } }, "available_count": 32 }, "advisory": { "llm": { "used": false, "reason": "disabled" }, "source": "rules", "confidence_note": "Confidence in this analysis is low (43/100), based on 0.03 month(s) and 1 transactions. Less than 3 months of history; seasonality and recurrence cannot be verified.", "lender_guidance": { "conditions": [ "Obtain additional statement history before disbursement." ], "recommended_action": "decline", "suggested_exposure_note": "Prudent instalment ceiling is 74,000 per month (74,000 under stress), implying a maximum principal of about 782,575 over 12 months." }, "recommendations": [ { "title": "Obtain a bank-verified statement", "action": "Reject this document and request a statement delivered directly by the issuing bank, or verify the account through an open-banking or direct-verification channel.", "origin": "rules", "category": "documentation", "priority": "critical", "rationale": "Document verdict is 'tampered' with 1 critical and 0 high-severity forensic findings.", "timeframe": "immediate", "estimated_monthly_impact": "" } ], "risk_commentary": { "watch_items": [ "Distinct income sources" ], "primary_risks": [ "No material risks detected." ], "mitigating_factors": [ "Median monthly earned income" ] }, "customer_message": "Your statement shows a mixed financial position (score 36 out of 100). You received about 1,850,000 KES a month and spent 0, keeping 100% of it. The single most useful change you can make is: Reject this document and request a statement delivered directly by the issuing bank, or verify the account through an open-banking or direct-verification channel. Small, consistent adjustments over the next three months will move this score more than any one-off action.", "spending_verdict": { "verdict": "excellent", "rationale": "Outflow is 0% of inflow with a 100% savings rate; risk band is minimal.", "key_drivers": [ "credit" ] }, "executive_summary": "Poor financial health (grade E, 36/100). Profile: Balanced spender. Monthly inflow averages 1,850,000 against outflow of 0, a savings rate of 100%. Risk is assessed as minimal with 0 red flag(s). Document authenticity: tampered.", "behavioural_insights": [ { "impact": "neutral", "insight": "Spending is back loaded within the month", "evidence": "0% of outflow occurs in the first 10 days." } ] }, "behavior": { "habits": { "dining_share": 0, "alcohol_share": 0, "savings_share": 0, "gambling_share": 0, "shopping_share": 0, "avg_ticket_size": 0, "cash_preference": 0, "essential_share": 0, "transport_share": 0, "debt_service_share": 0, "median_ticket_size": 0, "discretionary_share": 0, "transfers_out_share": 0, "counterparty_loyalty": { "repeat_rate": 0, "unique_counterparties": 0 }, "spend_to_income_ratio": 0, "large_transaction_count": 0, "large_transaction_share": 0, "micro_transaction_count": 0, "lifestyle_inflation_signal": { "slope": 0, "r_squared": 0, "slope_pct_per_period": 0 }, "large_transaction_threshold": 0 }, "timing": { "weekday_spend": {}, "busiest_weekday": "", "spending_rhythm": "back_loaded", "late_night_share": 0, "hour_distribution": {}, "weekday_distribution": {}, "has_intraday_timestamps": true, "front_loaded_spend_share": 0, "day_of_month_distribution": {}, "weekend_transaction_share": 0 }, "persona": { "label": "Balanced spender", "traits": [ "salaried" ] }, "available": true, "recurring": { "count": 0, "detected": [ null ], "obligations": [ null ], "subscriptions": [ null ], "incoming_count": 0, "outgoing_count": 0, "subscription_count": 0, "subscription_monthly": 0, "recurring_monthly_inflow": 0, "committed_monthly_outflow": 0, "fixed_obligations_monthly": 0 }, "income_profile": { "income_trend": { "slope": 0, "r_squared": 0, "slope_pct_per_period": 0 }, "primary_income": { "source": "narration_match", "employer": "ACME LTD", "consistency": 1, "occurrences": 1, "monthly_amount": 185000, "payday_day_of_month": 8 }, "months_observed": 1, "income_volatility": 0, "has_regular_salary": true, "min_monthly_income": 185000, "months_with_income": 1, "top_income_sources": [ { "share": 1, "total": 185000, "source": "ACME" } ], "income_source_count": 1, "mean_monthly_income": 185000, "income_concentration": 0, "median_monthly_income": 185000, "monthly_earned_series": [ { "month": "2026-01", "amount": 185000 } ], "verified_income_share": 1, "income_diversification": "single_source", "income_stability_score": 60 }, "paycheck_cycle": { "reason": "fewer than two pay events", "available": false } }, "cashflow": { "period": { "days": 1, "months": 0.03, "currency": "KES", "declared_end": "2026-08-31", "declared_start": "2026-08-01", "last_transaction": "2026-01-08", "first_transaction": "2026-01-08", "sufficient_history": false }, "totals": { "net_flow": 185000, "avg_debit": 0, "fee_count": 0, "avg_credit": 185000, "fees_total": 0, "debit_count": 0, "monthly_net": 1850000, "credit_count": 1, "median_debit": 0, "savings_rate": 1, "total_inflow": 185000, "largest_debit": 0, "median_credit": 185000, "total_outflow": 0, "largest_credit": 185000, "monthly_inflow": 1850000, "burn_rate_daily": 0, "essential_share": 0, "essential_spend": 0, "monthly_outflow": 0, "non_earned_inflow": 0, "transaction_count": 1, "discretionary_share": 0, "discretionary_spend": 0, "earned_income_total": 185000, "monthly_earned_income": 1850000, "verified_income_share": 1, "verified_income_total": 185000, "expense_to_income_ratio": 0, "monthly_verified_income": 1850000 }, "balance": { "source": "stated", "available": true, "max_balance": 233250, "min_balance": 233250, "p10_balance": 233250, "balance_trend": { "slope": 0, "r_squared": 0, "slope_pct_per_period": 0 }, "days_negative": 0, "median_balance": 233250, "average_balance": 233250, "closing_balance": 149736.65, "lowest_negative": 0, "opening_balance": 48250, "balance_volatility": 0, "negative_balance_share": 0, "ends_higher_than_starts": false }, "monthly": { "series": [ { "net": 185000, "month": "2026-01", "inflow": 185000, "outflow": 0, "savings_rate": 1, "transactions": 1, "earned_income": 185000, "essential_spend": 0, "discretionary_spend": 0 } ], "best_month": "2026-01", "worst_month": "2026-01", "inflow_trend": { "slope": 0, "r_squared": 0, "slope_pct_per_period": 0 }, "outflow_trend": { "slope": 0, "r_squared": 0, "slope_pct_per_period": 0 }, "months_observed": 1, "inflow_volatility": 0, "outflow_volatility": 0, "earned_income_trend": { "slope": 0, "r_squared": 0, "slope_pct_per_period": 0 }, "net_negative_months": 0, "net_positive_months": 1, "median_monthly_earned": 185000, "earned_income_volatility": 0 }, "velocity": { "transactions_per_month": 10, "avg_days_to_spend_inflow": "", "monthly_inflow_growth_pct": 0, "monthly_outflow_growth_pct": 0 }, "available": true, "by_channel": { "breakdown": [ { "count": 1, "label": "Unclassified channel", "share": 1, "inflow": 185000, "volume": 185000, "channel": "unknown", "outflow": 0 } ], "digital_share": 0, "cash_dependency": 0, "dominant_channel": "unknown", "channel_diversity": 0 }, "by_category": { "breakdown": [ { "kind": "income", "count": 1, "group": "Primary income", "label": "Salary & wages", "total": 185000, "largest": 185000, "category": "salary", "essentiality": 1, "median_amount": 185000, "share_of_side": 1, "average_amount": 185000, "monthly_average": 1850000 } ], "spend_by_group": [ null ], "category_diversity": 0, "top_income_categories": [ { "kind": "income", "count": 1, "group": "Primary income", "label": "Salary & wages", "total": 185000, "largest": 185000, "category": "salary", "essentiality": 1, "median_amount": 185000, "share_of_side": 1, "average_amount": 185000, "monthly_average": 1850000 } ], "category_concentration": 0, "top_expense_categories": [ null ] }, "daily_summary": { "idle_days": 0, "active_days": 1, "busiest_day": "2026-01-08", "days_covered": 1, "activity_rate": 1, "peak_daily_outflow": 0, "avg_transactions_per_active_day": 1 } }, "warnings": [ null ], "anomalies": { "reason": "insufficient transactions", "available": false }, "forensics": { "file": { "md5": "6d28629ecec9c93f8d82647249830ddc", "sha256": "91e6d909fe17edb9350130ab89d946d8912853928f00fd753af4057f2012b6b7", "filename": "api-payload.json", "page_count": 0, "size_bytes": 506, "extraction_method": "direct-json" }, "verdict": { "status": "tampered", "summary": "Conclusive evidence of alteration was detected. Do not rely on this document. Ledger arithmetic is minor issues.", "confidence": "high", "tamper_score": 0, "top_findings": [ { "code": "OPENING_CLOSING_MISMATCH", "title": "Declared closing balance does not match the transaction total", "detail": "Opening 48,250.00 + net movement 185,000.00 = 233,250.00, but the statement declares 149,736.65 (difference -83,513.35). Rows have been added, removed or altered.", "category": "ledger", "evidence": { "difference": -83513.35, "net_movement": 185000, "opening_balance": 48250, "declared_closing": 149736.65, "expected_closing": 233250 }, "severity": "critical" } ], "high_findings": 0, "total_findings": 1, "integrity_score": 25, "critical_findings": 1, "authenticity_score": 87 }, "metadata": { "note": "Document-level metadata forensics is only available for PDF uploads. This statement arrived as JSON, so authenticity rests on ledger consistency and, where possible, direct issuer verification." }, "source_format": "json", "ledger_analysis": { "checks": { "gaps": { "applicable": false }, "benford": { "reason": "only 1 amounts; need 60+", "applicable": false }, "precision": { "decimal_share": 0, "integer_share": 1 }, "chronology": { "inversions": 0, "future_dated": 0, "weekday_distribution": { "3": 1 } }, "duplicates": { "duplicate_groups": 0, "exact_duplicates": 0, "reused_references": 0 }, "round_numbers": { "applicable": false }, "opening_closing": { "passed": false, "applicable": true, "difference": -83513.35, "net_movement": 185000, "opening_balance": 48250, "declared_closing": 149736.65, "expected_closing": 233250 }, "balance_continuity": { "reason": "running balance column absent or sparse", "applicable": false }, "reference_sequence": { "applicable": false }, "description_uniformity": { "applicable": false } }, "findings": [ { "code": "OPENING_CLOSING_MISMATCH", "title": "Declared closing balance does not match the transaction total", "detail": "Opening 48,250.00 + net movement 185,000.00 = 233,250.00, but the statement declares 149,736.65 (difference -83,513.35). Rows have been added, removed or altered.", "category": "ledger", "evidence": { "difference": -83513.35, "net_movement": 185000, "opening_balance": 48250, "declared_closing": 149736.65, "expected_closing": 233250 }, "severity": "critical" } ], "integrity_band": "minor_issues", "integrity_score": 25 }, "document_analysis": { "edited": false, "findings": [ null ], "primary_tool": "n/a", "tamper_score": 0, "tools_detected": [ null ], "tamper_risk_band": "not_applicable" } }, "analysis_id": "9165ac45-4b2a-4efb-93f3-377b26415c75", "parse_notes": { "key_mapping": { "date": "date", "debit": "debit", "credit": "credit", "balance": "balance", "reference": "reference", "description": "description" } }, "transactions": { "available": true, "by_channel": [ { "key": "unknown", "net": 185000, "count": 1, "label": "Unclassified channel", "inflow": 185000, "outflow": 0, "last_seen": "2026-01-08", "first_seen": "2026-01-08", "active_days": 1, "total_volume": 185000, "transactions": [ { "date": "2026-01-08T09:12:04+01:00", "tags": [ null ], "amount": 185000, "balance": 233250, "channel": "unknown", "category": "salary", "direction": "credit", "reference": "SAL7QK2M91", "confidence": 0.96, "description": "SALARY PAYMENT FROM ACME TECHNOLOGIES LTD", "counterparty": "ACME LTD", "channel_label": "Unclassified channel", "category_label": "Salary & wages", "counterparty_id": "" } ], "median_amount": 185000, "average_amount": 185000, "largest_amount": 185000 } ], "money_sent": { "count": 0, "transactions": [ null ] }, "by_category": [ { "key": "salary", "net": 185000, "count": 1, "label": "Salary & wages", "inflow": 185000, "outflow": 0, "last_seen": "2026-01-08", "first_seen": "2026-01-08", "active_days": 1, "total_volume": 185000, "transactions": [ { "date": "2026-01-08T09:12:04+01:00", "tags": [ null ], "amount": 185000, "balance": 233250, "channel": "unknown", "category": "salary", "direction": "credit", "reference": "SAL7QK2M91", "confidence": 0.96, "description": "SALARY PAYMENT FROM ACME TECHNOLOGIES LTD", "counterparty": "ACME LTD", "channel_label": "Unclassified channel", "category_label": "Salary & wages", "counterparty_id": "" } ], "median_amount": 185000, "average_amount": 185000, "largest_amount": 185000 } ], "card_activity": { "count": 0, "transactions": [ null ] }, "cash_activity": { "count": 0, "transactions": [ null ] }, "till_payments": { "count": 0, "billers": [ null ], "transactions": [ null ] }, "uncategorized": [ null ], "largest_debits": [ null ], "money_received": { "count": 0, "transactions": [ null ] }, "by_counterparty": [ { "net": 185000, "count": 1, "inflow": 185000, "outflow": 0, "last_seen": "2026-01-08", "first_seen": "2026-01-08", "active_days": 1, "counterparty": "ACME", "relationship": "payer", "total_volume": 185000, "median_amount": 185000, "average_amount": 185000, "largest_amount": 185000, "counterparty_id": "", "dominant_channel": "unknown", "dominant_category": "salary" } ], "largest_credits": [ { "date": "2026-01-08T09:12:04+01:00", "tags": [ "income" ], "amount": 185000, "balance": 233250, "channel": "unknown", "category": "salary", "direction": "credit", "reference": "SAL7QK2M91", "confidence": 0.96, "description": "SALARY PAYMENT FROM ACME TECHNOLOGIES LTD", "counterparty": "ACME LTD", "channel_label": "Unclassified channel", "category_label": "Salary & wages", "counterparty_id": "" } ], "paybill_payments": { "count": 0, "billers": [ null ], "transactions": [ null ] } }, "affordability": { "request": { "decision": "approve", "headroom": 50360.1, "affordable": true, "projected_dsr": 0.1278, "requested_amount": 250000, "implied_instalment": 23639.9, "affordable_under_stress": true }, "available": true, "current_dsr": 0, "dsr_headroom": 0.4, "free_cashflow": 185000, "monthly_surplus": 185000, "prudence_factor": 0.55, "monthly_essentials": 0, "affordability_score": 100, "assumed_annual_rate": 0.24, "assumed_term_months": 12, "committed_recurring": 0, "gross_monthly_income": 185000, "existing_debt_service": 0, "income_stability_band": "very_stable", "monthly_discretionary": 0, "stressed_max_instalment": 74000, "max_affordable_principal": 782575.25, "recommended_max_instalment": 74000 }, "categorization": { "coverage": { "categorized": 1, "transactions": 1, "channel_coverage": 0, "categorization_rate": 1, "high_confidence_rate": 1 }, "backfilled": 0, "rules_applied": 57 } }, "status": true, "response_code": "00", "message": "string", "billing_info": { "was_charged": true, "amount": "string", "currency": "string" }}Response Codes & Statuses: Prembly API responses include custom
response_code values (e.g., 00 Success, 01 Not Found, 02 Unavailable).Prembly Slack Community
Join our developer Slack channel for real-time integration support, engineering updates, and direct Q&A with the Prembly team.
Join Slack Channel