Bank & Credit-Union Financial Health API — FDIC/NCUA QoQ
Pricing
from $4.40 / 1,000 results
Bank & Credit-Union Financial Health API — FDIC/NCUA QoQ
Bank & credit-union financial-health API on keyless FDIC data (NCUA v1.1): unified per-institution assets, deposits, equity, ROA, ROE, NIM and asset quality, with quarter-over-quarter deltas, peer-percentile scoring, and derived health flags (deposit outflow, low ROA, rising NPL).
Pricing
from $4.40 / 1,000 results
Rating
0.0
(0)
Developer
Kyle Maloney
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
1
Monthly active users
8 days ago
Last modified
Categories
Share
Bank & Credit-Union Financial Health API — FDIC Capital, Uninsured Deposits & CRE
A bank financial-health API that turns raw regulatory call-report data into a decision-ready screen. It pulls US FDIC-insured banks into one normalized schema and ships the analytics layer on top: regulatory capital ratios with a PCA category, the post-2023 stress screen (uninsured deposit ratio, AFS unrealized losses, CRE concentration), credit quality, efficiency, quarter-over-quarter deltas, peer-percentile scoring, and derived health flags at the supervisory thresholds.
The underlying numbers are free and public. What they are not is joined, derived, or screened — and three of the four metrics regulators and rating agencies actually used in 2023 don't exist as fields at all. This actor computes them.
Who it's for
- Corporate treasury & commercial lenders running bank counterparty risk. CDS spreads and share prices don't exist for ~4,300 private community banks; call-report data is the only signal there is.
- Bank & credit-union strategy / correspondent teams benchmarking against a peer band.
- Fintech & BaaS partnership teams screening sponsor-bank health before signing.
- Bank M&A advisors, investors and analysts building peer comps by state or asset band.
- Deposit brokers & treasury desks watching quarter-over-quarter deposit flows.
- AI agents needing a clean, chainable "bank financial health" lookup and scoring tool.
The stress screen
After SVB, Signature and First Republic, four metrics became the standard screen. Three of them are not published fields — they have to be derived from the call report:
| Metric | How it's derived | Flagged at |
|---|---|---|
| Uninsured deposit ratio | uninsured ÷ total deposits | > 50% (OFR cutoff; SVB was 92.5%) |
| AFS unrealized loss / equity | fair value − amortized cost, against equity. The FDIC publishes no AOCI or unrealized-loss field. | > 100% of equity (the OFR cutoff that identified 185 banks) |
| CRE / Tier 1 capital | nonfarm-nonresidential + multifamily + construction ÷ Tier 1. There is no single "CRE" field. | ≥ 300% — and ≥ 100% for construction alone (2006 interagency guidance) |
| QoQ deposit change | current vs prior quarter | ≤ −2% |
Banks tripping both prongs of the 2006 CRE guidance historically failed at 22.9%, versus 0.5% for banks tripping neither.
Plus a PCA capital category (well_capitalized / adequately_capitalized /
undercapitalized / significantly_undercapitalized) derived from all four regulatory
ratios per 12 CFR 324.403. It returns null rather than guessing when any input ratio
is missing.
v1.3 evaluates the CRE guidance properly. The 2006 test is two prongs, and the second needs 12 quarters of history that no single call-report row carries:
Construction ≥ 100% of capital — OR — CRE ≥ 300% of capital AND CRE grew ≥ 50% over 36 months.
Through v1.2 only the level halves were checked, which over-flagged banks holding a
large but static CRE book. v1.3 pulls the quarter from 12 quarters back and emits
cre_growth_36m_pct and cre_guidance_prong, so cre_guidance_both_prongs marks the
cohort that actually failed at 22.9%.
Real peer groups, not "whatever you pulled"
A state cohort mixes a $27M agricultural bank with a $200B trust bank. Ranking them
against each other produces a number, not an insight. peerBasis picks the cohort:
peerBasis | Peer group |
|---|---|
cohort | Everything you pulled (the v1.2 behaviour, still the default) |
business_line | FDIC SPECGRP business-model group — the cut a bank examiner uses |
asset_band | FFIEC-style asset-size band |
community_bank | The FDIC community-bank research flag |
Every percentile — assets, ROA, CRE concentration, uninsured deposits — is then computed within that group. A group with fewer than 5 institutions falls back to the full cohort instead of ranking a bank against two neighbours.
Set benchmark to national or state and each row also carries the cohort's
asset-weighted ratios and this bank's distance from them in percentage points
(uninsured_vs_benchmark_pts, cre_vs_benchmark_pts, unrealized_vs_benchmark_pts).
Asset-weighted, not an average of per-bank ratios, so a $27M bank can't outvote a $200B
one. It costs one extra request — the FDIC API aggregates server-side, so the
national benchmark across all ~4,350 banks arrives in a single call rather than a
4,350-row download.
Modes
Every mode returns the same full field set. Mode changes the ordering only.
- snapshot — largest institutions first.
- delta — biggest quarter-over-quarter deposit move first (the run-risk view).
- score — highest peer asset percentile first (the peer-comp view).
- stress — most health flags first (the triage view).
Example input
{"state": "CA","institutionType": "bank","mode": "stress","minAssets": 250000,"maxAssets": 0,"maxResults": 500}
FDIC reports assets in $000s, so minAssets: 250000 = $250M. Set state for a
focused run and state-level peer scoring.
Output (per institution)
Identity & core — institution_type, id, id_scheme, name, city, state,
total_assets, total_deposits, equity, roa, roe, net_interest_margin,
asset_quality_ratio, report_date
Quarter-over-quarter — prior_report_date, prior_period_assets,
prior_period_deposits, qoq_asset_change_pct, qoq_deposit_change_pct
Peer scoring — peer_asset_percentile, peer_roa_percentile
Capital adequacy — leverage_ratio, cet1_ratio, tier1_rbc_ratio,
total_rbc_ratio, tier1_capital, capital_framework, pca_capital_category
Deposit composition & funding — uninsured_deposits, insured_deposits,
uninsured_deposit_ratio, core_deposits_ratio, brokered_deposits_ratio,
loans_to_deposits_ratio
Securities & unrealized losses — afs_fair_value, afs_amortized_cost,
afs_unrealized_gain_loss, unrealized_loss_to_equity_pct, htm_fair_value,
total_securities
Loan concentration — cre_total_loans, cre_to_tier1_pct, construction_loans,
nonfarm_nonres_loans, multifamily_loans, ci_loans, construction_to_tier1_pct,
re_loans_to_tier1_pct
Credit quality — nonperforming_assets_ratio, net_charge_off_ratio,
loan_loss_reserve_ratio, provision_for_credit_losses, earnings_coverage_of_nco
Earnings & efficiency — efficiency_ratio, cost_of_funds_pct, pretax_roa
Peer cohort & holding company (v1.3) — business_line, business_line_code,
is_community_bank, charter_class, holding_company, holding_company_rssd,
peer_basis, peer_group, peer_group_label, peer_group_size,
peer_cre_percentile, peer_uninsured_percentile
CRE 36-month growth (v1.3) — cre_total_loans_36m_ago, cre_growth_36m_pct,
cre_baseline_date, cre_guidance_prong
Peer benchmark (v1.3) — benchmark_scope, benchmark_peer_count,
benchmark_uninsured_deposit_ratio, benchmark_cre_to_tier1_pct,
benchmark_unrealized_loss_to_equity_pct, uninsured_vs_benchmark_pts,
cre_vs_benchmark_pts, unrealized_vs_benchmark_pts
Provenance & completeness (v1.4) — fdic_institutions_status,
fdic_institutions_error, fdic_financials_status, fdic_financials_error,
fdic_benchmark_status, fdic_benchmark_error, fdic_cre_history_status,
fdic_cre_history_error, ncua_status, credit_unions_included, sources_ok,
sources_failed, data_complete, health_flags_complete, health_flags_basis,
matched_institutions_total, results_truncated, drift_gate_status,
drift_probes_verified, drift_probes_unavailable, drift_gate_note,
filters_echo_verified, coverage_note, data_as_of, cre_components_reported,
risk_based_ratios_reported
Tail — health_flags[], source_url, retrieved_at
Dollar figures are in thousands (FDIC convention). Ratio fields are already percentages.
Reading a null correctly
Every upstream this actor federates records its own outcome on every row, so a
null is never ambiguous:
| You see | It means |
|---|---|
fdic_financials_status: "ok" and net_interest_margin: null | FDIC answered and publishes no NIM for that institution. |
fdic_financials_status: "unavailable" and net_interest_margin: null | The join never ran. The value is unknown, not absent. |
health_flags: [] with health_flags_complete: true | Nothing was flagged. A genuine clean bill of health. |
health_flags: ["data_incomplete_flags_not_evaluated"] | The stress screen could not run. Do not read this as clear. |
credit_unions_included: false | Checked and deliberately excluded — see ncua_status and coverage_note. |
risk_based_ratios_reported: false | A CBLR filer. It files no CET1 / tier 1 / total RBC at all. |
If every source fails, the run fails and emits nothing rather than returning an empty dataset that reads like "no banks matched".
Health flags
Fundamentals: deposit_outflow, asset_decline, low_roa, negative_roa,
negative_roe, elevated_npl, rising_npl, thin_capital.
Stress screen: uninsured_over_50pct, unrealized_loss_over_100pct_equity,
cre_over_300pct_capital, construction_over_100pct_capital, below_well_capitalized.
2006 CRE guidance (v1.3): cre_growth_over_50pct_36m, cre_guidance_both_prongs.
The second one is the real test — construction ≥ 100% of capital, or CRE ≥ 300% and
+50% growth over 36 months — and marks the cohort that historically failed at 22.9%.
Completeness (v1.4): data_incomplete_flags_not_evaluated. Present whenever
health_flags_complete is false. It exists so an empty flag list can never be
mistaken for a clean screen on a run where the screen never happened.
Honest notes
- Field coverage was verified on the smallest banks, not just the big ones. Every
field here returns non-null across the 40 smallest Texas banks (assets from $17.4M).
That matters: the obvious-looking CET1 code (
RBCT1CER) is null for 63% of community banks, so this actor usesIDT1CERinstead. - CBLR filers report no risk-based ratios, and the FDIC returns them as zero, not null. Banks that elect the Community Bank Leverage Ratio framework (12 CFR 324.12, leverage >= 9%) are exempt from reporting CET1 / tier 1 / total RBC. In a live 300-bank Texas cohort, 115 were CBLR filers. This actor detects them, emits
capital_framework: "cblr", nulls the ratios rather than passing zeros through, and treats the election itself as well capitalized — which is what it regulatorily means. - The CRE denominator is Tier 1, and the growth prong needs
creGrowthon. The official 300% test is measured against total risk-based capital, which is larger than Tier 1, socre_to_tier1_pctruns slightly high and the level flag is deliberately conservative: it catches every bank the official test would, plus a few sitting near the line. The 36-month growth prong (v1.3) is evaluated only whencreGrowthis on; with it off,cre_guidance_both_prongscan still fire on the construction prong, which needs no history, but the CRE-growth path cannot. cre_growth_36m_pctis null for banks that did not exist 12 quarters ago. A de-novo or recently-chartered bank has no baseline quarter, and this actor reports that asnullrather than inventing a 0%. Those banks can trip the construction prong but never the growth prong.uninsured_depositsis an FDIC estimate. Banks under $1B in assets don't report the underlying schedule item directly, and there was a wave of restatements after the FDIC's July 2023 guidance, so pre- and post-restatement ratios aren't comparable.- Trust banks report zero deposits. Ratios with a zero denominator return
null, neverInfinity. - Credit unions aren't live yet, and every row says so. fails the run immediately and bills nothing, rather than quietly handing back bank data.institutionType: "credit_union"
institutionType: "all"returns the bank half — and since v1.4 every row carriesncua_status: "not_available_in_this_build",credit_unions_included: falseand acoverage_notesaying in words that credit unions in scope are absent, so a state-wide "all institutions" pull can never be mistaken for a complete institution census. The NCUA bulk 5300 feed is verified and the column mapping is wired; only the parser remains. - A zero is only reported as an answer once the filter has been proved to work.
An unknown filter field does not error at FDIC — it returns HTTP 200, echoes the
filter verbatim and reports
meta.total: 0on both endpoints. A column rename upstream would therefore look exactly like "no banks matched". Before any row is built, this actor runs three live probes (a known-population canary, a filter that must match nothing, and an unfiltered count the filtered count must be strictly less than) and fails the run if they disagree. The outcome ships on every row asdrift_gate_status.
Changelog
v1.4 — Provenance, and a run that fails instead of lying.
Three defect classes, all confirmed against live FDIC data on 2026-08-18:
- A total upstream failure used to end as a SUCCEEDED run with an empty dataset — which a buyer reads as "no banks matched", not "we could not reach FDIC". It now fails loudly and bills nothing.
- No source recorded its own outcome. A
/financialsoutage nulled the NIM, capital, funding, securities, loan-concentration and quarter-over-quarter columns — indistinguishable from an institution that does not report them — and lefthealth_flagsnear-empty, which reads as a clean bill of health for a bank nothing was ever screened against. Every row now carries a status per source, plusdata_complete,health_flags_completeand an explicitdata_incomplete_flags_not_evaluatedflag. - The FDIC filter was never verified. FDIC accepts a lowercase conjunction,
echoes it back byte-for-byte, answers HTTP 200 and never applies the clause:
STALP:TX AND ACTIVE:1returns 347 institutions, the same query withandreturns 6,719 — and the rows that come back are Wisconsin banks. On/financialsit is 352 against 152,473. Every request now asserts the echoed filter and post-validates every returned row against the constraint it asked for, and a live drift gate proves the filter mechanism still works before any billable row exists.meta.total— a free exact match count that was being ignored — now ships on the row asmatched_institutions_total.
Also: the credit-union half of this rollup is now disclosed on every row
(ncua_status, credit_unions_included, coverage_note) instead of silently
missing; CBLR filers are explicitly marked with risk_based_ratios_reported;
cre_components_reported makes it impossible for a future partial null to be
summed as a zero; and a simulateOutage input lets every failure path be
re-proved on demand rather than only during a real outage.
No field was removed or renamed, and no price, tier, title, description or category changed.
v1.3 — Real peer cohorts, peer benchmarks, and the missing half of the CRE test.
Percentiles can now be computed within an FDIC business-line peer group, an asset-size
band, or the community-bank split, instead of against "whatever you pulled"; groups
under 5 institutions fall back to the cohort rather than ranking a bank against two
neighbours. Added asset-weighted national/state benchmarks and per-row distance from
them in percentage points, using the FDIC's server-side aggregation so the benchmark
across all ~4,350 banks costs one request, not a 4,350-row download. Added the 2006
guidance's 36-month CRE growth prong (cre_growth_36m_pct, cre_guidance_prong,
cre_guidance_both_prongs) — the level-only test in v1.2 over-flagged banks with a
large but static CRE book. Added business line, community-bank flag, charter class and
holding company (via the Fed RSSD; the FDIC's ULTCERT turned out to be
self-referential, not a parent pointer, on all 347 Texas banks). 24 new fields, all
appended — every v1.2 field keeps its name and position, and the default peerBasis
reproduces v1.2 scoring exactly.
v1.2.6 — Fixed a silent-substitution defect: institutionType: "credit_union" fell
through to "bank", so the run succeeded and billed while returning FDIC banks
tagged institution_type: "bank". An unavailable institution type is now a hard,
zero-cost failure with an explicit message. Wrong data that looks right is worse than
no data, and it should never cost you anything. Type resolution moved into a pure,
unit-tested function with 12 regression assertions covering casing, whitespace, unknown
types, and the "all" partial-coverage path.
v1.2 — /financials is now joined in every mode. Through v1.1, the default
snapshot mode returned seven permanently-null columns (NIM, asset quality, and all
five QoQ fields) because it only called /institutions, which doesn't carry them.
Added ~30 capital / funding / securities / loan-concentration / credit-quality fields
and the stress screen. Dropped NPTLA, which is not a real FDIC field and was silently
discarded by the API on every request. Detects CBLR filers so their unreported (zero) risk-based ratios are never read as real values. Switched to the canonical api.fdic.gov host
(the old one 301-redirected on every call) and added retry with backoff. All v1.1
field names and positions are unchanged — v1.2 is strictly additive.
Use as an MCP tool
This Actor is callable directly by any MCP-compatible AI agent through Apify's hosted MCP server. There is no server to run and no integration code to write - the tool schema an agent sees is generated from this Actor's own input and dataset schemas.
Endpoint
https://mcp.apify.com?tools=malonestar/fdic-ncua-health-rollup
Claude Desktop, Claude Code or Cursor - add to claude_desktop_config.json,
.mcp.json or .cursor/mcp.json respectively:
{"mcpServers": {"apify": {"url": "https://mcp.apify.com?tools=malonestar/fdic-ncua-health-rollup","headers": { "Authorization": "Bearer YOUR_APIFY_TOKEN" }}}}
Get a token at https://console.apify.com/settings/integrations. Claude Desktop can
also authenticate interactively via OAuth against https://mcp.apify.com with no
headers block. Full reference: https://docs.apify.com/platform/integrations/mcp
Try asking your agent
Pull capital and asset-quality ratios for every bank headquartered in Texas and flag any that fail the 2006 CRE concentration guidance.
Chains well with - expose these alongside it by comma-separating the tools
parameter, and the agent can carry results from one into the next:
malonestar/fdic-structure-change-delta-monitormalonestar/fdic-branch-network-churn-rollupmalonestar/fdic-sod-deposit-market-share-rollup
https://mcp.apify.com?tools=malonestar/fdic-ncua-health-rollup,malonestar/fdic-structure-change-delta-monitor,malonestar/fdic-branch-network-churn-rollup,malonestar/fdic-sod-deposit-market-share-rollup
Billing is unchanged when called as an MCP tool: this Actor is Pay-Per-Event and an agent pays the same per-result price a human does. A run that cannot answer fails without billing rather than returning an unverified negative.
FAQ
Is it keyless? Yes — the FDIC BankFind API needs no key. Note that passing an invalid key returns 403, so this actor never sends one.
Where does the data come from? Official FDIC institution and quarterly financial
call-report data, via api.fdic.gov/banks/institutions and api.fdic.gov/banks/financials.
How current is it? As of the latest published FDIC quarter-end — see report_date
on every row.
How do I find banks with high uninsured deposits? Run mode: "stress" and filter on
the uninsured_over_50pct flag, or sort by uninsured_deposit_ratio.
How do I check CRE concentration against the regulatory threshold? cre_to_tier1_pct
against 300%, and construction_to_tier1_pct against 100%.
Why are the asset figures so large? FDIC reports assets and deposits in thousands of dollars.
Can I diff two arbitrary runs? Yes — pass a prior run's rows as priorItems.
Are credit unions included? Not yet — see the honest notes above.
Related actors
| Actor | What it adds |
|---|---|
| FDIC Deposit Market Share & HHI Rollup | Branch-level deposit share, county/MSA rollups, HHI concentration and the market-gap screen |
| SEC RIA Registration Delta Monitor | Investment-adviser registrations, AUM changes and terminations |
| Bank Enforcement Action Tracker | Formal regulatory enforcement actions against banks |
Pricing
Pay per result: you are billed only for the institution-health records actually emitted
(cap with maxResults). Empty cohorts cost only the actor start.