Explainable MSME Financial Health Card for IDBI Innovate 2026 PS3. Saakh (साख) is a trader's earned creditworthiness — SaakhScore proves it for businesses the bureau can't see.
Live demo | Submission deck | Demo video | Animated walkthrough | Model card | Pilot runbook
Built for IDBI Innovate 2026 - Problem Statement 3: Financial Health Score - Team Looper
- Overview
- Demo
- Backend Proof
- Features
- Architecture
- Setup
- Evidence
- Screenshots
- Judging Proof
- Limitations
- License
SaakhScore turns consented alternate-data signals into a bank-reviewable credit decision for thin-file MSMEs. The public prototype uses a synthetic cohort and sandbox-ready API contracts; it does not claim private IDBI data access.
The core demo moment is a New-to-Credit case traditional underwriting rejects because there is no bureau file. SaakhScore approves the same business with a defensible Grade A health score, reason codes, Shapley attribution, policy guardrails, and an underwriter memo.
| Case | Traditional bureau-only | SaakhScore alternate data |
|---|---|---|
| Shree Ganesh Textiles, no bureau file | Rejected | Approved - Grade A, Score 86/100 |
| Indicative credit limit | Rs 0 | Rs 27,00,000 |
| Explanation | No credit bureau history | Ranked reason codes, Shapley attribution, policy guardrails |
- Live app: https://id-ysm9.onrender.com
- Live API proof: https://id-ysm9.onrender.com/submission/proof
- OpenAPI docs: https://id-ysm9.onrender.com/docs
- Runtime readiness: https://id-ysm9.onrender.com/health/ready
- Demo video (narrated walkthrough): https://youtu.be/0I5BY6DKB1E
- Animated walkthrough (browser-automation capture of the live app, current build): docs/demo.gif
- Submission deck (official IDBI Innovate template): docs/deck/SaakhScore-IDBI-Submission-Deck.pdf
- Extended deck (13-slide detail edition): docs/deck/SaakhScore-Extended-Deck.pdf
- Pilot promotion runbook: docs/PILOT_RUNBOOK.md
- Threat model: docs/THREAT_MODEL.md
What to verify in under three minutes:
- Open the live app and keep the default Shree Ganesh Textiles case selected.
- Compare
Traditional bureau-only: RejectedwithSaakhScore alternate data: Approved. - In the review packet alongside, inspect the pillars, English/Hindi reason codes, the EMI limit-sizing ledger, model attribution, decision path, and policy guardrails.
- Still in
Decision, run the sensitivity lab (up to three signals, one joint re-score), the three-scenario stress battery, and a side-by-side borrower comparison -- then click around the portfolio risk map under the impact strip. - Switch to
Model,Governance, andProofto confirm the real-outcome benchmark, audit, validation, pilot gates, fairness, rubric, and competitor-gap proof -- then try the live underwriter console underSources.
The backend is not a mock response behind a polished screen. The judge can verify the product through live API surfaces:
| Proof surface | What it proves |
|---|---|
GET /health/ready |
Release version, serving provider, runtime permission and verified artifact integrity used by container/Render readiness checks. |
GET /submission/proof |
One payload summarizing the NTC reversal, truth boundary, backend capability map, judge runbook, rubric scorecard, competitor gap map, API catalog, validation metrics, controls, and Stage 2 swap points. |
GET /msmes/ntc_hero/score |
Full decision packet: score, grade, limit, reason codes, exact Shapley attribution, memo, guardrails, source map, and decision path. |
GET /model/evaluation |
Untouched proxy holdout AUC/Gini/KS/PR-AUC/Brier/ECE, bootstrap intervals, fairness slices, PSI, candidate comparison, and artifact hashes. |
GET /model/sme-benchmark |
Real SBA small-business charge-off outcomes at natural base rates: v2 champion validated on a true later-in-time OOT window (114,770 loans) and a recession stress cohort (257,465 loans), plus the v1 case-sample baseline with its out-of-distribution test -- selective monotonicity, native exact TreeSHAP, per-artifact hashes, and committed honesty caveats. |
POST /sandbox/score |
Underwriter-authenticated, purpose/scoped/expiry-checked AA/GST/UPI/EPFO/Bureau payloads normalize into the cockpit contract. |
POST /sandbox/recalibration/report |
Underwriter-authenticated sandbox distribution, coverage, labels, and retraining readiness evidence. |
GET /sandbox/outcome-contract |
Machine-readable dated 12-month outcome schema, maturity rule, chronological split policy, and privacy boundary. |
POST /sandbox/pilot-readiness |
Underwriter-authenticated maturity, volume, temporal/OOT, source-coverage, NTC/NTB, and fairness-slice gates without record persistence. |
GET /deployment/readiness |
Fail-closed model and infrastructure promotion gates for pilot/production mode. |
POST /validation/report |
Underwriter-authenticated AUC, Gini, KS, PSI, and reason-code stability for caller-supplied dated cohorts. |
GET /governance |
Audit count, model status, live controls, fairness slices, pilot KPIs, and deployment caveats are inspectable. |
Quick backend checks:
curl https://id-ysm9.onrender.com/submission/proof
curl https://id-ysm9.onrender.com/health/ready
curl https://id-ysm9.onrender.com/msmes/ntc_hero/score
curl https://id-ysm9.onrender.com/governance
curl https://id-ysm9.onrender.com/deployment/readinessRubric coverage is implemented as backend data, not only README copy:
| Judge lens | Verifiable proof |
|---|---|
| Innovation | NTC bureau rejection becomes an explainable alternate-data approval with memo, reasons, guardrails, and audit. |
| Feasibility | One FastAPI service, zero-build static cockpit, non-root container, readiness probe, Render Blueprint, GitHub Actions, and no mandatory paid API dependency. |
| Scalability | Separate ingestion, scoring, attribution, O(n log n) validation, audit, temporal readiness, bounded payloads, and fail-closed promotion gates. |
| Business impact | Portfolio impact, NTC rescues, credit unlocked, pilot KPIs, early-risk guardrail, and diversification measures. |
| Technical implementation | Calibrated monotonic XGBoost, native exact TreeSHAP, logistic fallback, score/PD/policy separation, scoped APIs, and artifact-backed evidence. |
| Governance readiness | Honest random-holdout boundary, dated outcome contract, true-OOT readiness gates, model-disagreement review, pseudonymised audit, and fail-closed pilot promotion. |
- Deep-linkable, keyboard-accessible two-rail underwriter workspace: decision stage beside a permanent review packet (Decision, Evidence, Model, Governance, Proof, Sources) with borrower queue, score, grade, risk band, credit-line recommendation, and decision comparison. Fonts are self-hosted; the app makes zero external requests.
- In-product model evidence: the
Modeltab rendersGET /model/sme-benchmark(v2 real-outcome splits with bootstrap intervals, DeLong-tested baselines, artifact integrity) plus the consumer-proxy evaluation with candidate comparison and outcome-linked fairness slices. - Live underwriter console under
Sources: send a real editable payload toPOST /sandbox/scorewith the documented demo key -- loading, 401, and validation errors render honestly; nothing is mocked. - Sensitivity, stress, and compare labs in the decision packet: move up to three whitelisted signals in one joint re-score (
GET /msmes/{id}/whatif/multi-- interactions are real, not summed single-lever deltas); run a fixed three-scenario adverse stress battery with shocks clamped to the input schema (GET /msmes/{id}/stress); and put any two borrower files side by side, pillar by pillar. All are views over the identical live pipeline -- no audit events, no mocks. - Portfolio risk map: a clickable score-vs-PD scatter of the live cohort (bubble area = indicative limit) rendered from
GET /portfolio, so concentration of risk is visible at a glance. - Five-pillar financial health card: Liquidity, Discipline, Momentum, Leverage, and Digital Footprint.
- Calibrated monotonic XGBoost champion with native exact TreeSHAP, a calibrated logistic fallback, and an untouched 4,500-row public-proxy holdout -- not a regressor fit against a synthetic score. See MODEL_CARD.md.
- Deterministic underwriter memo and borrower improvement plan; optional AWS Bedrock memo generation is a Stage 2 configuration path.
- EWS-style monitoring signals (bank-recognisable categories for the same five pillars) and a deterministic, rule-based underwriter next-best-action recommendation, both derived from the already-computed score -- not generative output.
- Underwriter/auditor role gates, source-scoped consent, strict app CSP, request IDs, body/array bounds, quota headers, and fsync-backed genesis-anchored pseudonymised audit events.
- Sandbox-ready ingestion via
POST /sandbox/scorefor AA/GST/UPI/EPFO/Bureau-style payloads, with enforced purpose/scope/expiry consent. A source the caller never connects always routes to mandatory review instead of being silently scored as worst-case, and a counterparty-concentration guardrail flags heavy single-buyer dependency. - GST-vs-bank turnover reconciliation: when both feeds are present, declared turnover is compared against bank-observed inflow; a divergence beyond +/-25% routes to review and becomes the underwriter's top next action -- the "looks-fine-on-paper" red flag, detected in both directions.
- EMI-capacity indicative limit: the limit is sized from spare debt-service capacity (existing-debt service estimated, policy rate/tenor annuity) and only capped by the grade multiple, with the full
limit_basisbreakdown in every response -- not a bare score-times-constant number. - Favorable-only conduct prior: strong GST momentum and UPI footprint reduce the routed PD through a capped, disclosed expert prior (never inflating PD for thin digital visibility -- absence of signal is not evidence of risk); the coefficients become trainable the moment dated sandbox outcomes arrive.
- Bilingual reason codes: borrower-facing reasons, improvement actions, and the underwriter next-best-action ship in English and Hindi -- and render in-product behind an English/हिन्दी toggle, in a committed Devanagari face.
- Recalibration and monitoring APIs for holdout AUC/Gini/KS/PR-AUC/Brier/ECE, bootstrap intervals, PSI, reason stability, pilot targets, and proxy fairness slices -- see
GET /model/evaluation. - Dated
bad_12moutcome contract with 365-day maturity checks and automatic chronological development/calibration/OOT cohorts -- seeGET /sandbox/outcome-contractandPOST /sandbox/pilot-readiness. - Explicit
public_demo,pilot, andproductionmodes. Pilot/production startup fails closed until private credentials, IDBI-scoped artifacts, true OOT evidence, and durable audit storage pass -- seeGET /deployment/readiness.
Mermaid source (renders live on GitHub too; the image above is a committed fallback so the diagram never depends on a client-side renderer)
flowchart LR
Reviewer["Judge / underwriter"] --> Cockpit["Deep-linkable credit cockpit"]
Cockpit --> Guard["Request trace | CSP | limits | RBAC"]
Guard --> Intake["Consent + AA/GST/UPI/EPFO normalisation"]
Intake --> Score["Five-pillar health score"]
Score --> Model["Calibrated monotonic XGBoost"]
Model --> Explain["Exact TreeSHAP"]
Explain --> Policy["Versioned lending policy"]
Policy --> Memo["Memo + proposed limit"]
Memo --> Audit["Genesis-anchored audit chain"]
Model --> Monitor["Holdout + drift + fairness evidence"]
Audit --> Gate["Fail-closed promotion gate"]
Monitor --> Gate
Outcomes["Dated IDBI outcomes - pending"] -.-> Temporal["365-day maturity + true OOT"]
Temporal -.-> Gate
Gate -->|"all pass"| Pilot["Approved pilot runtime"]
Gate -->|"any block"| Refuse["Startup refused"]
Regenerate the image after editing the source: save the block above to a .mmd file and run mmdc -i file.mmd -o docs/diagrams/readme-architecture.svg.
Important endpoints:
| Endpoint | Purpose |
|---|---|
GET /health/live, GET /health/ready |
Process liveness and release/model/artifact readiness |
GET /msmes and GET /msmes/{id}/score |
Demo cohort and score packets |
GET /submission/proof |
Judge-facing capability, architecture, rubric, runbook, competitor-gap, and truth-boundary proof |
POST /score |
Underwriter-authenticated custom MSME scoring |
POST /sandbox/score |
Normalize and score sandbox-style AA/GST/UPI/EPFO/Bureau payloads |
POST /sandbox/recalibration/report |
Profile sandbox distributions and readiness for GBM/SHAP |
GET /sandbox/outcome-contract, POST /sandbox/pilot-readiness |
Validate dated 12-month labels, maturity, chronological splits, NTC volume, and monitoring support |
GET /deployment/readiness |
Show and enforce model/identity/OOT/audit promotion blockers |
GET /portfolio, /governance, /pilot-metrics |
Portfolio impact and control evidence |
GET /model/evaluation |
Champion/challenger selection, holdout metrics, uncertainty, fairness and artifact integrity |
GET /validation/demo, POST /validation/report |
Explicit fixture contract and authenticated caller-supplied cohort validation |
GET /audit-log, GET /model/status |
Auditor-gated pseudonymised trail and active champion metadata |
cd backend
pip install -r requirements.txt
uvicorn main:app --reloadOpen http://localhost:8000.
Demo-scoped credentials for protected write/audit routes (public by design for judging): saakhscore-demo-underwriter-key (underwriter role — scoring/sandbox/validation writes) and saakhscore-demo-auditor-key (auditor role — audit log). Real deployments override SAAKHSCORE_API_KEYS and SAAKHSCORE_AUDIT_HMAC_KEY (legacy UDYAMPULSE_* names are honored as a fallback).
Run tests:
python -m pytest backend -qContainer deploy:
docker build -t saakhscore .
docker run -d --name saakhscore -p 8000:8000 saakhscore
docker inspect --format='{{json .State.Health}}' saakhscoreThe image runs as a non-root user and probes /health/ready. Dockerfile and render.yaml define the same single-service deployment used by Render.
- Test suite: 140 backend tests (167 total with the 9 frontend-unit and 18 Playwright e2e tests) covering scoring/policy routes, NTC reversal, model monotonicity, exact TreeSHAP reconstruction, runtime artifact hashes, honest holdout evidence, consent-at-decision scope, temporal leakage/maturity/split gates, production-scale validation, resource ceilings, request traces, fail-closed runtime modes, writable non-root audit persistence, genesis-anchored audit chaining, missing-source review routing, counterparty-concentration limit sizing, GST-vs-bank divergence detection, EMI-capacity limit sizing, favorable-only conduct-prior bounds, bilingual reason codes, v2 benchmark integrity and leakage exclusions, side-effect-free public reads, separated underwriter/auditor duties, chunked-body limits, doc-figure consistency, generative-memo fact-checking, OCEN offer determinism with recomputed EMI pricing, consent-contract self-validation against the enforcement model, bounded what-if hypotheticals, multi-lever sensitivity recomputed against direct pipeline runs, schema-clamped adverse stress batteries, governed screening routing, and API proof.
- Model evidence:
GET /model/evaluationreports random-holdout ROC-AUC 0.7497 (bootstrap 95% interval 0.7314-0.7678), Gini 0.4993, KS 0.4225, PR-AUC 0.4948, Brier 0.1415, and ECE 0.0122. It is reproducible withpython backend/model_training/train_pd_model.pyand explicitly not called OOT. - Real small-business outcome benchmark:
GET /model/sme-benchmarkserves thesba_sme_pd_v2champion -- selected across 418,947 resolved real SBA 7(a) loans at natural base rates (197,716-loan train split) and validated on a true later-in-time out-of-time window (FY2017-19: 114,770 loans, ROC-AUC 0.9623, KS 0.82) and a recession stress cohort (257k loans, ROC-AUC 0.9255), with selective monotonicity, exact TreeSHAP, bootstrap intervals, and a pre-registered significance+materiality selection gate. The earlier case-sample benchmark stays committed as the baseline. Reproduce viabackend/model_training/experiments/+train_sme_pd_model_v2.py; the full experiment registry and analysis are in docs/research/BENCHMARK_REPORT.md. Real outcomes, real time axis -- still a US proxy domain, complementary to the alternate-data conduct pillars, and explicitly not an IDBI production calibration. - Public cohort impact: 2 NTC rescues and Rs 30,23,000 credit unlocked in the synthetic demo cohort (pilot targets, not measured lift -- these figures are computed by
GET /portfolio, so the prose matches the live backend rather than drifting from it). - Governance evidence: policy guardrails with real consent-verification detail, source map, hash-chained audit count, real validation metrics, pilot KPI targets, and fairness slices are visible in the app.
- Backend evidence:
/submission/proofexposes the capability map, judge runbook, route catalog, rubric scorecard, competitor gap map, architecture flow, real held-out validation metrics, controls, and Stage 2 swap points directly from backend functions. - Security: custom/sandbox/validation writes require
underwriter;/audit-logrequiresauditor; logs retain HMAC subject references rather than borrower names; CSP, CORS, consent, payload ceilings and rate budgets are enforced. See docs/SECURITY_COMPLIANCE.md and docs/THREAT_MODEL.md. - Promotion safety: the live public proxy is explicitly blocked from pilot use.
SAAKHSCORE_MODE=pilotorproduction(legacyUDYAMPULSE_MODE) refuses startup until all machine-readable deployment gates pass. - Model transparency: MODEL_CARD.md documents the real training data/label, domain bridge, explainability, intended use and limitations. docs/ARCHITECTURE.md documents implementation boundaries; docs/PILOT_RUNBOOK.md defines promotion, sign-off and rollback.
Full-resolution images remain in docs/deck/assets for detailed inspection.
- Track fit: IDBI's public MSME Inclusion track asks for a Financial Health Card using alternate data for faster credit decisions and finance access for underserved MSMEs.
- Public event surface: the official public event venue found during review is IDBI Innovate 2026 on Hack2skill; no official IDBI Devpost page was found.
- Sandbox interpretation: sandbox APIs and datasets are granted to shortlisted teams after the first round. This repo therefore ships synthetic proof plus a ready feed contract, dated outcome schema, automatic temporal/OOT readiness analysis, and fail-closed promotion controls without claiming early access.
- Differentiation: many PS3 demos stop at a score; SaakhScore shows the bank decision pack around that score - rejection reversal, reasons, attribution, memo, source map, guardrails, audit, validation, pilot metrics, fairness checks, and a backend-verifiable judge proof endpoint.
- Model roadmap (real-outcome benchmark + two-tower plan): docs/MSME_MODEL_ROADMAP.md
- Submission checklist: docs/SUBMISSION_CHECKLIST.md
- Public data is synthetic and illustrative; it is not IDBI customer, sandbox, or repayment-outcome data.
- The calibrated XGBoost champion is trained on a real default label from a public consumer-credit proxy, not Indian MSME outcomes. Its 4,500-row holdout is random and cross-sectional, not OOT; dated IDBI outcomes are still required.
- Gender and age monitoring is real on the untouched proxy holdout, but is not a production fairness certification. NTC/NTB, sector, geography and vintage outcome slices remain unavailable pending sandbox data.
- API authentication is a real, enforced bearer-token/role scheme sized for a public demo (no login flow or per-underwriter identity), not full IDBI SSO -- see docs/SECURITY_COMPLIANCE.md.
- Pilot mode is intentionally not ready today:
/deployment/readinessblocks it on public-proxy model scope, absent true OOT evidence, demo credentials/HMAC, and local JSONL audit storage. - AWS Bedrock memo generation is optional and requires configured credentials and a model ID; deterministic memo generation remains the default fallback.
- SaakhScore is decision support for underwriters, not a fully automated approve/decline system without human review.
MIT - see LICENSE. The public synthetic cohort, model artifacts, and documentation in this repository are covered by the same terms; this does not extend to any IDBI, AA, GST, UPI, or EPFO data or credentials, which are never present in this codebase.





