CFPB Company Complaint Delta Monitor
Pricing
$5.00 / 1,000 new complaint detecteds
CFPB Company Complaint Delta Monitor
Watches specific companies in the official CFPB Consumer Complaint Database and reports only complaints filed since your last check. Informational feed only, not a verified finding of wrongdoing. A check with nothing new is free.
Pricing
$5.00 / 1,000 new complaint 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 new consumer complaints filed against specific companies, via the official, free
CFPB Consumer Complaint Database Search API (consumerfinance.gov). No API key needed.
Important legal/factual disclaimer
This is an informational feed of complaints as filed with the CFPB — not a verified finding of wrongdoing, not investment advice, not a compliance conclusion. The CFPB itself states that complaints in this database are not verified: consumers submit them, the named company may have responded and disputed the complaint, and publication can be delayed. A complaint appearing here means someone filed it — nothing more. Do not represent this actor's output as evidence of misconduct. Not real-time: the CFPB's own published data lags several days behind the current date (observed ~5-7 days live on 12.09.2026).
How it works
- Each
watchis one company, identified by its exact name as recorded in the CFPB database (e.g."WELLS FARGO & COMPANY","EQUIFAX, INC.") — check the exact spelling onconsumerfinance.gov/data-research/consumer-complaints/search/first; a near-miss name silently returns zero complaints, it does not error. - Every run fetches that company's most recent complaints (
sort=created_date_desc, up to 100 per request — the CFPB Search API returns a window of the newest complaints, not the full history in one response) and diffscomplaint_idagainst a durable checkpoint of ids already seen for that watch. - Genuinely new complaints are pushed to the dataset and billed once each (
new-complaint-detected); checking a company with nothing new costs nothing beyond the fixed platform run cost. The first check of a new watch establishes a baseline (no charge) — you get a free look at the current top of the complaint stream, then pay only for what's genuinely new afterward. - Optional
product/issue/statefilters narrow the complaint stream server-side for a given watch (e.g. only "Credit card" complaints from "CA").
Input
{"monitorId": "my-companies","watches": [{ "watchId": "wells-fargo", "company": "WELLS FARGO & COMPANY" },{ "watchId": "equifax-ca-fraud", "company": "EQUIFAX, INC.", "issue": "Fraud or scam", "state": "CA" }],"notifyOn": "new_alerts","webhookUrl": "https://example.com/webhook"}
Add more watches later under the same monitorId — each watch keeps its own independent history.
Billing
Pay-per-event: new-complaint-detected — charged only for a complaint genuinely new 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 guarantee: at-most-once (not exactly-once)
The right to write a row and to charge for it is granted by a single atomic primitive — one
addRequest(uniqueKey) into a dedicated, named claim-journal Request Queue
(<prefix>-<monitorId>-claims). Exactly one run ever wins that key. Claim requests are never deleted
and never handled: the queue is a permanent journal of irreversible attempts, not a work list.
- You will never be charged twice for the same complaint. That is the guarantee.
- It is not exactly-once. If a run wins the claim and then dies before the row reaches the dataset
(or before the charge completes), that complaint is lost: it closes as
dataset_unknown/charge_unknownand is never re-delivered. We deliberately prefer losing a delivery over double-charging you. - Boundary of the guarantee: it holds for as long as the named claim-journal queue exists. Anyone with account access can delete or re-create that queue through the Apify Console/API; a fresh journal starts empty, and previously delivered complaints could then be delivered and billed again. That is an inherent limit of any durable storage, not a defect of the protocol.
- Migration boundary: the guarantee applies from the build that introduced the claim gate onward.
Older builds of this actor must not keep running against the same
monitorId. That same build also had to shorten the durable storage name prefix (the old one, the full actor name, could not fit Apify's 63-character storage-name limit together with a 40-charactermonitorId), so a monitor that ran on an older build starts from a fresh baseline once. A baseline is never charged. coverage.claimJournalSizereports the journal's size each run (best-effort;nullif the queue's metadata could not be read, and the value lags a few seconds because Apify'stotalRequestCountis eventually consistent). Use it to watch growth, not to make decisions.
Honest limits
- Window, not full history. The CFPB Search API returns up to 100 of the newest complaints per
request; if a company has more new complaints since your last check than fit on one page,
coverage.windowFullCountreports it honestly rather than silently dropping older-but-still-new complaints (they surface on the following run once the window catches up, same pattern asfederal-register-monitor). - Exact company name required. There is no fuzzy matching: a misspelled or slightly different company name returns zero complaints (a legitimate, non-error "nothing new" result), not an error. Use the CFPB's own search page to confirm exact spelling before configuring a watch.
- Not real-time. The CFPB itself publishes complaints with a delay (observed ~5-7 days on 12.09.2026); this actor cannot see a complaint the CFPB has not yet published, no matter how often you run it.
- We don't invent data. If the CFPB API response shape changes or returns an unexpected status, the
run reports it honestly (
permanent_error: .../transient_error: ...) instead of silently returning zero results. Fields not present in the live CFPB response (e.g. the historicalconsumer_disputedfield, retired by CFPB some years ago) are not fabricated — we only surface fields confirmed present in a live response. seenIdsper watch is capped (FIFO by discovery order, 2000 entries) — only matters for a company with an extraordinarily high complaint volume relative to check frequency.- The
urlfield on each delivered row links to the CFPB's own complaint-detail page (.../search/detail/<id>). That page is client-rendered (SPA) and returns HTTP 200 for the URL shape itself regardless of whether the id resolves inside the app — it is a best-effort deep link into the same UI the CFPB publishes, not a server-validated permalink.
Deviations from the original brief (see also ROADMAP.md)
- The brief's example query included
format=json. Live testing on 12.09.2026 showed this parameter makes the API return HTTP 404 — the response is JSON by default without it, so we never send it. - Live testing also found the API sits behind an Akamai WAF that returns HTTP 403 for a plausible
chunk of "app-looking"
User-Agentstrings (including our own actor name as a plainname/versionstring, and evenMozilla/5.0) while passing through strings that honestly self-identify as a bot/ crawler (containingbot/crawler) or well-known tool UAs (curl,Wget, unmodifiedpython-requests). We sendcfpb-company-complaint-delta-bot/0.1— an honest self-identification, not UA spoofing — which passes reliably in live testing. - The brief's example schema listed
consumer_disputed. It is not present in the live API response (CFPB retired this field in the published dataset some years ago); we do not fabricate it.
No CFPB endpoint used here required an API key or authentication at any point during development.
Author: OmniCoder (https://t.me/OmniCoder)