FDIC Bank M&A, Charter & Structure-Change Monitor
Pricing
from $8.25 / 1,000 results
FDIC Bank M&A, Charter & Structure-Change Monitor
Typed delta feed of FDIC bank structure changes: mergers paired acquirer-to-target and sized on both sides (assets, deposits, holding company), de-novo charters, failures, regulator and class conversions. Live filter-drift assertions. Keyless FDIC source, no login.
Pricing
from $8.25 / 1,000 results
Rating
0.0
(0)
Developer
Kyle Maloney
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
Share
A typed delta feed of every structure change in the US banking system, straight from the FDIC's own institution-history record: mergers paired acquirer-to-target and sized on both sides, de-novo charters, failures and assisted resolutions, branch openings and sales, relocations, regulator and class conversions, legal name changes.
Keyless, no login, no scraping. One mode, one date window, optionally a state list.
v1.1 adds deal-size financials — total assets, deposits, offices, holding company and RSSD for the acquirer, target, survivor and subject on every row — plus three live drift assertions that fail the run rather than hand you a plausible wrong answer.
Why this exists
api.fdic.gov/banks/history is public and free, and also close to unusable raw: 150
columns per record, 41 undocumented numeric change codes, acquirer/target linkage smeared
across ACQ_*/OUT_*/SUR_* triples plus an underscore-packed ID, no financials at
all, and an aggregation endpoint (agg_by) that returns HTTP 500.
Worse, it fails quietly. Two requests, verified live on 2026-07-28:
| Request | meta.total | What FDIC did |
|---|---|---|
PSTALP:TX AND CHANGECODE:223 | 1,457 | applied both clauses |
PSTALP:TX and CHANGECODE:223 | 52,138 | echoed the filter back byte-for-byte, HTTP 200, and never applied the CHANGECODE clause |
52,138 is exactly 35,239 (all TX) + 18,356 (all code 223) − 1,457 (the overlap). A filter FDIC declines to honour is not an error; it is a different, larger answer, and you would be billed for it. This actor asserts at runtime both that the echoed filter matches what was sent and that every returned row satisfies the constraints you asked for, and fails the run outright if either does not hold. Nothing is emitted and nothing is billed.
Who it is for
| Persona | What they run |
|---|---|
| Bank M&A / corp-dev analyst | mode: "mergers", 365-day window, enrichFinancials: true — a deal book with both balance sheets, relative deal size, intrastate/interstate, and both holding companies. |
| Community-bank strategist | mode: "mergers" + states — who is consolidating your footprint, and how big the targets are. |
| Bank vendor / fintech BD team | mode: "denovo" — every new charter the moment FDIC records it. New banks buy core, compliance and card platforms. |
| Risk / credit analyst | mode: "failures" — failures, payoffs, conservatorships, open-bank assistance and assisted mergers, back to the 1930s if you widen the window. |
| Branch-network / site-selection analyst | mode: "branches" — openings, closings, purchases and sales with coordinates. |
| Compliance / KYB pipeline | mode: "events" — legal name changes, cert changes, charter-agency and primary-regulator moves. A bank that changed its name is not a new counterparty. |
| Market researcher / journalist | mode: "rollup" — consolidation counts by state, event type, quarter and acquirer. |
| AI agent | Any mode over MCP. Every field is described in the output schema, and every field says whether it was actually checked. |
Example input
{"mode": "mergers","sinceDays": 365,"dateField": "processed","states": ["TX", "OK"],"maxResults": 500,"enrichFinancials": true}
Every input carries a working prefill and a default. Running with the defaults returns a full year of US bank mergers, sized.
| Input | Type | Notes |
|---|---|---|
mode | string | events · mergers · denovo · failures · branches · rollup. Defaults to mergers. |
sinceDays | integer | Delta anchor. Ignored when sinceDate is set. Default 365. |
sinceDate / untilDate | YYYY-MM-DD | Explicit window. sinceDate overrides sinceDays. |
dateField | processed | effective | processed = FDIC's PROCDATE, the right anchor for delta monitoring. effective = EFFDATE, the legal effective date. |
states | array | Two-letter USPS codes. Empty = all states and territories. |
changeCodes | array | Explicit FDIC CHANGECODE list. Overrides the set implied by mode. |
maxResults | integer | Hard row cap. Billing is per result, so this is also your cost ceiling. |
resolveMissingNames | boolean | Backfill a counterparty name from /banks/institutions when the history row omits it. |
enrichFinancials | boolean | Deal-size lookup (below). Default on. Costs about one extra request per 250 certificates. |
What comes back
One row per structure-change event, or one row per aggregate bucket in rollup mode.
184 declared fields; a mergers run populates 162 of them.
Identity and classification
| Field | Notes |
|---|---|
eventId | FDIC ID. On institution rows it decodes as TRANSNUM_CHANGECODE_UNINUM_ACQUNINUM_OUTUNINUM. Branch rows carry an opaque hash instead; the parser refuses to invent linkage from one. |
transactionNumber | Shared by every record belonging to the same deal. |
changeCode, changeCodeDescription | Raw FDIC code plus FDIC's own text. |
eventType, eventCategory | Normalized snake_case type and coarse category, decoded from all 41 change codes present in the live index. |
unmappedChangeCode | true if FDIC publishes a code this build does not decode. Also raises a run-level warning. It is never silently bucketed as "other". |
effectiveDate, processedDate, eventQuarter, eventYear, processYear | |
isMerger · isFailure · isAssisted · isDeNovoCharter · isNewCharter · isRelocation · isRegulatorChange · isClassChange · isNameChange · isVoluntaryLiquidation · isBranchEvent · isParticipantMirror | Booleans, null-safe: false means FDIC published a 0; null means FDIC did not publish the flag at all. |
The institution the event happened to
institutionName · cert · uninum · city · state · county · institutionClass ·
institutionClassDescription · charterAgency · regulator · organizationType ·
organizationTypeNumber · serviceType · trustPowers · insuranceFund ·
establishedDate · institutionEndDate · bankInsured · fdicRegion · latitude ·
longitude · reportType · fdicBankFindUrl
Counterparties
Flat columns for CSV and Sheets, plus the full nested acquirer / target / survivor
objects for JSON consumers.
acquirerName · acquirerCert · acquirerUninum · acquirerCity · acquirerState ·
acquirerCounty · acquirerClass · acquirerClassDescription · acquirerCharterAgency ·
acquirerRegulator · acquirerAddress · acquirerZip · acquirerLatitude ·
acquirerLongitude · acquirerFdicRegion · acquirerBranchesAcquired
— the same set for target* and survivor*, plus survivorChangeCode and
survivorChangeCodeDescription (the mirror record on the surviving charter's timeline).
| Field | Notes |
|---|---|
linkageMethod | How we looked: acq_out_fields, id_uninum, institutions_lookup, none. |
linkageStatus | Whether we found anything: resolved · partial · unresolved · not_applicable. A merger with no named side reports unresolved — deliberately not the same value as a de-novo charter, which genuinely has no counterparty. |
survivorUninumSource | FDIC does not publish SUR_UNINUM on this endpoint. When SUR_CERT matches ACQ_CERT the survivor's UNINUM is taken from ACQ_UNINUM and this field says so; otherwise survivorUninum stays null rather than being guessed. |
Deal size (enrichFinancials, new in v1.1)
/banks/history carries no financials. /banks/institutions retains the final call
report of a bank that has already merged away — Stellar Bank, CERT 58629, charter ended
2026-07-01, still reports $10.89 B assets and $9.04 B deposits as of 2026-03-31 — so a
completed deal can be sized on both sides.
For each of institution, acquirer, target, survivor:
*AssetsUsdThousands · *DepositsUsdThousands · *Offices · *HoldingCompany ·
*HoldingCompanyRssd · *Specialization · *IsCommunityBank · *IsActive ·
*FinancialsAsOf · *CharterEndDate
Plus targetToAcquirerAssetsPct, combinedAssetsUsdThousands and dealGeography
(intrastate / interstate).
Assets and deposits are US dollar THOUSANDS. *HoldingCompanyRssd is FDIC's
RSSDHCR, the regulatory high-holder pointer — note that ULTCERT is not a parent
pointer and is deliberately not used. A null financial figure means not retrieved,
never zero; enrichmentStatus on the same row tells you which.
Before / after
former and current objects, plus changedAttributes — an explicit list of only the
attributes that actually moved, e.g. [{"attribute":"regulator","from":"FED","to":"FDIC"}]
— and activeFlags, the FDIC boolean event flags set to 1 on the record.
Provenance — every row says what was and was not checked
| Field | Meaning |
|---|---|
historySourceStatus | ok, or partial when a page failed after retries. |
nameLookupStatus | not_needed · ok · unavailable · disabled. When unavailable, a blank acquirerName means "not resolved", not "no acquirer". |
enrichmentStatus | ok · partial · unavailable · disabled · not_applicable. |
resultCompleteness / partialResult | complete · capped_by_maxresults · partial_upstream_error. A partial run says so on the row, not only in the log. |
filterEchoVerified | Always true on emitted rows — the run fails if it is not. |
queryFilters | The exact FDIC filter expression sent, for audit against the echo. |
fdicIndexName | The FDIC search index that served the run, e.g. history_20260724090007. |
fdicIndexMaxProcessedDate | Newest PROCDATE anywhere in the index, from an unfiltered probe. |
pagesRequested / pagesFailed / rowsAvailableUpstream | Fetch accounting. rowsAvailableUpstream is FDIC's meta.total for your query, before maxResults capping. |
queryMode, windowStart, windowEnd, retrievedAt, sourceUrl |
rollup mode
Buckets by state, eventType, quarter and acquirer (dimension + key), each with
eventCount, distinctInstitutions, distinctAcquirers, distinctStates,
firstEventDate, lastEventDate, and summed targetAssetsUsdThousands /
acquirerAssetsUsdThousands when enrichment ran.
mergerCount, failureCount, deNovoCount, relocationCount, regulatorChangeCount,
classChangeCount and otherCount are a single exclusive chain — each event lands in
exactly one, in that order — and always sum to eventCount. assistedCount,
branchCount, nameChangeCount, unmappedCodeCount and linkageUnresolvedCount are
independent, non-exclusive counters that deliberately overlap the chain. Every bucket
also carries the provenance fields above.
FDIC's agg_by returns HTTP 500 on this endpoint, so rollups are computed client-side
from the rows actually fetched. eventsAnalyzed tells you how many that was, and
rowsAvailableUpstream how many existed — if the second is larger, widen maxResults.
Note that firstEventDate / lastEventDate use the effective date while the default
window filters on the processed date, so a bucket can legitimately reach back years: a
relocation processed in 2026 may have taken effect in 2023.
Reliability: what fails the run instead of billing you
Three assertions run live, against the actual response, on every execution. An offline fixture cannot see a degraded upstream, because the fixture was shaped from it.
- Upstream health probe. One unfiltered request. The national row count must sit
inside a sane band (583,491 on 2026-07-28) and the newest
PROCDATEmust be within 60 days. A truncated or frozen index fails the run. - Echoed-filter assertion, on every page.
meta.parameters.filtersmust equal what was sent, byte for byte — including the enrichment requests to/banks/institutions. - Row-level constraint check. Every returned row must carry a
CHANGECODEin the requested set, aPSTALPin the requested states, and a date inside the window (1-day tolerance). This is the gate that catches the lowercase-andcase above, where the echo matched and the query still had not been applied. A row with noPSTALPat all is counted as unverifiable and logged, not treated as a violation.
Beyond that: an invalid mode is rejected at run creation (HTTP 400, nothing consumed);
an unreachable FDIC endpoint fails with the request URL and the last error; and if every
page fails, the run fails rather than emitting an empty success. Zero rows is reported as
a genuine empty result only when the health probe passed, the filter was echoed
intact, and FDIC honestly returned nothing.
An entirely empty input is not an error — the schema defaults apply (mergers, 365 days),
so {} returns a year of US bank mergers.
Use as an MCP tool
Available to AI agents through mcp.apify.com. Every input and output field carries a
description, so an agent can pick a mode and read the result without extra prompting. The
provenance fields matter here in particular: an agent can distinguish a verified negative
(false) from an unchecked one (null), and will not report "no acquirer" when the
lookup merely failed.
Useful agent phrasings: "which banks were acquired in Texas this year, and how big were they", "list new bank charters recorded since January", "has this bank changed its legal name or primary regulator", "summarise US bank consolidation by state for the last four quarters".
Pricing
$15 per 1,000 results, billed as the standard Apify Result event
(apify-default-dataset-item) — one event per dataset item, which is one structure-change
event in the event modes and one bucket in rollup. Graduated Apify plan discounts apply
(Bronze −20 % through Diamond −70 %).
maxResults caps rows fetched and emitted, so it is also your cost ceiling. A failed run
emits nothing and bills nothing. The health probe and the enrichment lookups are requests,
not results — they are never billed.
FAQ
Where does the data come from?
https://api.fdic.gov/banks/history for events and https://api.fdic.gov/banks/institutions
for the deal-size enrichment. Both are public and keyless. Do not use
banks.data.fdic.gov/api/* — it 302-redirects.
How far back does it go?
To the 1930s. Set sinceDays large, or use sinceDate. failures with a wide window
returns the full historical record of US bank failures.
Why does a merger row show the acquired bank as institutionName?
Because that is what the FDIC record is about: the change happened to the institution
that went away. The acquirer is in acquirerName, the surviving charter in survivorName.
FRM_INSTNAME / FRM_CERT are missing on merger rows — is that a bug?
It is FDIC. Those columns are absent on 100 % of sampled merger-family rows, not merely
null. The actor reconstructs the before-state from the OUT_* side and never zero-fills
the gap.
Why are organizationType, serviceType, institutionOffices and targetOffices empty
on my merger run?
Because FDIC does not publish them for those rows. ORGTYPE and SERVTYPE_DESC are absent
from merger-family history records — run mode: "events", or changeCodes: [360], and
they populate. OFFICES is omitted for closed charters, and in a merger the target is the
closed charter. Null means "FDIC does not have it here", not zero.
Why does the same deal appear twice if I pass changeCodes by hand?
FDIC writes an 8xx "Participated in…" mirror on the acquirer's timeline sharing the deal's
TRANSNUM. The institution-level modes exclude 810/811/812 for exactly this reason. If you
request them explicitly they are returned and flagged isParticipantMirror: true.
Can I get quarterly totals without pulling every row?
Not from FDIC — agg_by returns HTTP 500 on this endpoint. Use mode: "rollup", which
aggregates client-side over the rows it fetched.
Is the run charged if FDIC is down, or answers with the wrong universe?
No. Every failure path calls Actor.fail() before anything reaches the dataset, and the
message ends with "Nothing was emitted and nothing was billed."
Related actors
| Actor | Use it for |
|---|---|
| FDIC Branch Network Churn Rollup | Office-level entry and exit by bank and state, from a full chronological replay of state history — the branch-footprint counterpart to this actor's institution-level feed. |
| FDIC Deposit Market Share Rollup (SOD) | County and MSA deposit share and HHI. Run it after a merger found here to see what the combined entity's concentration looks like. |
| FDIC & NCUA Bank Health Rollup | Capital, asset quality and CRE-concentration screening on the banks in this feed — peer cohorts, the 2006 CRE guidance two-prong test, and credit unions. |
A typical chain: this actor to find the deal → health rollup to underwrite both sides → SOD rollup to check the deposit overlap → branch churn to see which offices actually close.