NCUA Credit Union Enforcement Watch
Pricing
$10.00 / 1,000 new enforcement action detecteds
NCUA Credit Union Enforcement Watch
Tracks NCUA credit union enforcement orders (cease & desist, prohibition, civil money penalty) by state or institution name, and alerts only on genuinely new or changed administrative actions — built for compliance officers, vendor risk teams, and credit union consultants. Free when nothing changes.
Pricing
$10.00 / 1,000 new enforcement action detecteds
Rating
0.0
(0)
Developer
Radu Furtuna
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
Share
Durable monitor for the NCUA's public Administrative Orders registry — the National Credit Union Administration's list of enforcement actions against credit unions and their affiliated individuals. Watch by state and/or credit union name, and get notified only about actions genuinely new or changed since your last check. No API key needed, no login, no captcha.
Source
https://ncua.gov/sites/default/files/list_csv/administrative-orders.csv — a public CSV export of the
entire registry (1,443 rows spanning 1991–2026, confirmed live 13.09.2026), reachable directly from the
"Download CSV" button on https://ncua.gov/news/enforcement-actions/administrative-orders. One HTTP GET
returns the whole registry; there is no server-side filter by state or name for this export, so
state/creditUnionNameContains are applied on our side over one shared snapshot per run.
Each row names either a credit union itself (subjectType: "institution", e.g. a Cease and Desist
Order against the institution) or a named individual affiliated with one (subjectType: "individual",
e.g. a former employee or officer) — these are genuinely different kinds of record and are never merged.
How it works
- Each
watchis an optionalstate(2-letter code) and/orcreditUnionNameContains(case-insensitive substring match against institution/individual names) — or neither, to watch the entire registry. - Every run downloads the CSV once (cached for the whole run, regardless of how many watches you define) and filters it per watch.
- A stable identity is built per row from its docket number, its unique registry URL, and a content hash of its substantive fields (institution, name, city, state, year, relationship). If NCUA later corrects a published row (e.g. a city name), the content hash changes and it is honestly treated as an update, not silently ignored or double-billed for no reason; if the exact same row reappears unchanged, nothing is re-billed.
- Genuinely new or changed rows are pushed to the dataset and billed once each
(
new-enforcement-action-detected); a check that finds nothing new costs nothing beyond the fixed platform run cost.
Input
{"monitorId": "my-credit-union-watch","userAgentContact": "you@example.com","watches": [{ "watchId": "louisiana", "state": "LA" },{ "watchId": "acme-fcu", "creditUnionNameContains": "Acme Federal Credit Union" }],"notifyOn": "new_alerts","webhookUrl": "https://example.com/webhook"}
userAgentContact is sent as a descriptive User-Agent on every request (polite-scraping practice) —
ncua.gov does not require a key, but we still identify ourselves.
Add more watches later under the same monitorId — each watch keeps its own independent history. A
watchId is permanently bound to the filter it first saw; pointing the same watchId at a different
state/creditUnionNameContains later fails the run instead of silently mixing histories.
Output row (per action)
watchId, stableRowId, docketNumber, subjectType ("institution"|"individual"), institution, firstName, lastName, city, state, year, relationship, url, monitorId, runId, discoveredAt, eventId, billedBilling
Pay-per-event: new-enforcement-action-detected — charged only for a row genuinely new or changed since
the previous check of that watch. The first check of a new watch establishes a baseline (no charge).
Failed/blocked checks are never charged.
Delivery/billing guarantee: at-most-once, not exactly-once
The right to perform an irreversible action (dataset write + PPE charge) is granted by the only atomic
primitive Apify offers — RequestQueue.addRequest(uniqueKey) → wasAlreadyPresent — in a separate
named queue that acts as a permanent journal (<prefix>-<monitorId>-claims). The Apify Key-Value Store
has no CAS, no conditional write and no ETag, so it can only ever be a diagnostic state machine, never
the source of at-most-once.
Concretely: for one computed event, delivery and charging each happen no more than once. If the run
dies after taking the claim, the event may be lost (it stays dataset_unknown/charge_unknown
and is never re-delivered) — but you will never be billed twice. That is a deliberate trade: "never
overcharge" beats "never lose a row".
Boundaries of the guarantee, stated honestly:
- Between the internal lease check and the dataset write/charge there is an unavoidable TOCTOU gap; what actually protects your money is the claim gate, not the lease.
- The guarantee holds for as long as the named claims queue exists. Anyone with account access can delete or recreate it via Console/API, which starts the journal from zero. This is a boundary of any durable storage, not a defect of the protocol.
- The guarantee applies from the build in which the claim gate was introduced onward. Older builds must
not keep running against the same
monitorId.
Important — read before relying on this for compliance decisions
NCUA itself states that its administrative orders list is not guaranteed to be exhaustive, that names reflect the organization's name at the time the order was finalized (and may no longer match the organization's current name after a merger, rename, or liquidation), and that some prohibitions/orders may have already expired or been lifted. This actor is an informational monitor of NEW or CHANGED publications to the official registry — it is NOT a current compliance/risk status for any organization, and it is NOT legal advice. Always confirm directly with NCUA (or counsel) before acting on any single entry.
Honest limits
- The durable dataset is a delivery-attempt log, not a guaranteed mirror of the default dataset.
Each row is written to the durable dataset first, then mirrored to the run's default dataset before
billing proceeds for that row. If the durable write succeeds but the default-dataset mirror write
fails (e.g. transient Apify storage error), the item is marked
dataset_unknown, billing for it is permanently blocked (fail-closed — we never charge for a row we can't confirm was delivered), and the run is not retried into re-creating that exact row. The durable dataset can therefore end up with a small number of orphan rows that were never mirrored and never billed. The default dataset is the canonical log of rows successfully written to this run's output (see itsrun_summaryrow) — but a default-dataset row does not by itself prove the row was billed: the row is written beforeActor.charge()runs, so if charging then fails or comes backcharge_unknown, the row is present but not confirmably paid.run_summary.eventsBilledand Apify's own billing ledger are the source of truth for confirmed payment, not the presence of a row in either dataset. - No server-side filter exists for this CSV export (verified live) —
state/creditUnionNameContainsare always applied client-side over one shared snapshot per run; they never reduce the actual network cost, only the rows delivered to you. - Each watch's window is capped at
MAX_ROWS_PER_WATCH(500) matching rows, newest-first (the source itself returns newest-first).coverage.windowFullCountand each watch's row incoverage.watches(windowFull/matchedCount) flag when a watch's real match count exceeded that window — informational, not silently dropped data.coverage.sourceAccessLimitedCountis a separate, unrelated counter: it only counts watches where the CSV itself could not be trusted this run (malformed rows or rows missing a docket/URL — see below), never a watch that simply had more matches than the window. - Row-level identity depends on the registry always supplying a non-empty docket number and a unique URL
for every row — both true for all 1,443 rows verified live on 13.09.2026. If any row is missing either
(or has a malformed column count), the whole run for that check is reported honestly as
source_access_limited— no partial baseline/delta/billing happens on a fetch whose completeness can't be trusted, rather than silently skipping just that one row. - The source uses two different conventions for institution-only orders — verified live: sometimes
First Name = "N/A"and the credit union name sits inLast Name, sometimes the reverse. Both are detected; only when both name fields would be empty doessubjectTypefall back to"institution"with anullname (not observed in the live registry as of 13.09.2026, but handled honestly rather than guessed at). - History is kept per row (not a capped seen-ids list): each row's own state (its latest content hash and a change-sequence counter) is stored indefinitely per watch, so a row that changes and later reverts to an earlier state (e.g. corrected then re-corrected) is billed correctly every genuine transition, never silently deduplicated against an older occurrence of the same content.
- We don't invent data: if the CSV's header or row shape changes, the run reports it honestly
(
structure_changed: ...) instead of silently returning zero results.
Author: OmniCoder (https://t.me/OmniCoder)