Bank & Credit-Union Financial Health API — FDIC/NCUA QoQ avatar

Bank & Credit-Union Financial Health API — FDIC/NCUA QoQ

Pricing

from $4.40 / 1,000 results

Go to Apify Store
Bank & Credit-Union Financial Health API — FDIC/NCUA QoQ

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

Kyle Maloney

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

1

Monthly active users

8 days ago

Last modified

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:

MetricHow it's derivedFlagged at
Uninsured deposit ratiouninsured ÷ total deposits> 50% (OFR cutoff; SVB was 92.5%)
AFS unrealized loss / equityfair 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 capitalnonfarm-nonresidential + multifamily + construction ÷ Tier 1. There is no single "CRE" field.≥ 300% — and ≥ 100% for construction alone (2006 interagency guidance)
QoQ deposit changecurrent 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:

peerBasisPeer group
cohortEverything you pulled (the v1.2 behaviour, still the default)
business_lineFDIC SPECGRP business-model group — the cut a bank examiner uses
asset_bandFFIEC-style asset-size band
community_bankThe 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 & coreinstitution_type, id, id_scheme, name, city, state, total_assets, total_deposits, equity, roa, roe, net_interest_margin, asset_quality_ratio, report_date

Quarter-over-quarterprior_report_date, prior_period_assets, prior_period_deposits, qoq_asset_change_pct, qoq_deposit_change_pct

Peer scoringpeer_asset_percentile, peer_roa_percentile

Capital adequacyleverage_ratio, cet1_ratio, tier1_rbc_ratio, total_rbc_ratio, tier1_capital, capital_framework, pca_capital_category

Deposit composition & fundinguninsured_deposits, insured_deposits, uninsured_deposit_ratio, core_deposits_ratio, brokered_deposits_ratio, loans_to_deposits_ratio

Securities & unrealized lossesafs_fair_value, afs_amortized_cost, afs_unrealized_gain_loss, unrealized_loss_to_equity_pct, htm_fair_value, total_securities

Loan concentrationcre_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 qualitynonperforming_assets_ratio, net_charge_off_ratio, loan_loss_reserve_ratio, provision_for_credit_losses, earnings_coverage_of_nco

Earnings & efficiencyefficiency_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

Tailhealth_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 seeIt means
fdic_financials_status: "ok" and net_interest_margin: nullFDIC answered and publishes no NIM for that institution.
fdic_financials_status: "unavailable" and net_interest_margin: nullThe join never ran. The value is unknown, not absent.
health_flags: [] with health_flags_complete: trueNothing 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: falseChecked and deliberately excluded — see ncua_status and coverage_note.
risk_based_ratios_reported: falseA 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 uses IDT1CER instead.
  • 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 creGrowth on. The official 300% test is measured against total risk-based capital, which is larger than Tier 1, so cre_to_tier1_pct runs 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 when creGrowth is on; with it off, cre_guidance_both_prongs can still fire on the construction prong, which needs no history, but the CRE-growth path cannot.
  • cre_growth_36m_pct is 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 as null rather than inventing a 0%. Those banks can trip the construction prong but never the growth prong.
  • uninsured_deposits is 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, never Infinity.
  • Credit unions aren't live yet, and every row says so.
    institutionType: "credit_union"
    fails the run immediately and bills nothing, rather than quietly handing back bank data. institutionType: "all" returns the bank half — and since v1.4 every row carries ncua_status: "not_available_in_this_build", credit_unions_included: false and a coverage_note saying 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: 0 on 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 as drift_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:

  1. 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.
  2. No source recorded its own outcome. A /financials outage nulled the NIM, capital, funding, securities, loan-concentration and quarter-over-quarter columns — indistinguishable from an institution that does not report them — and left health_flags near-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, plus data_complete, health_flags_complete and an explicit data_incomplete_flags_not_evaluated flag.
  3. 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:1 returns 347 institutions, the same query with and returns 6,719 — and the rows that come back are Wisconsin banks. On /financials it 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 as matched_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-monitor
  • malonestar/fdic-branch-network-churn-rollup
  • malonestar/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.

ActorWhat it adds
FDIC Deposit Market Share & HHI RollupBranch-level deposit share, county/MSA rollups, HHI concentration and the market-gap screen
SEC RIA Registration Delta MonitorInvestment-adviser registrations, AUM changes and terminations
Bank Enforcement Action TrackerFormal 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.