US WARN Layoff Notice Aggregator & Delta Monitor (OR/TX API)
Pricing
from $4.40 / 1,000 results
US WARN Layoff Notice Aggregator & Delta Monitor (OR/TX API)
Aggregate US state WARN Act layoff & closure notices into one normalized schema and track new / updated / removed deltas. Oregon & Texas live (keyless Socrata); CA/NY/WA/WI/IL/NJ scaffolded. For RevOps, recruiting, econ research and CRE. No API key.
Pricing
from $4.40 / 1,000 results
Rating
0.0
(0)
Developer
Kyle Maloney
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
0
Monthly active users
3 days ago
Last modified
Categories
Share
US WARN Layoff Notice Aggregator & Delta Monitor
Aggregate US state WARN Act layoff & plant-closure notices into one normalized schema, and get a delta feed of exactly what changed since your last run: new notices, updated notices (employee count / effective date / type revised), and removed notices.
Every state publishes WARN filings in a different shape (Socrata, CSV, HTML, Excel) with different column names and layoff-type wording. This actor unifies them so you can monitor layoffs across states from a single, stable dataset — no logins, no API keys.
What v1.1 changed (2026-08-01 validation pass)
Every source is now checked live, before a single row is billed, and every row carries the outcome of every requested state. Concretely:
- A dead state is loud. If Texas fails and Oregon succeeds, every emitted row carries
run_complete = false,run_states_failed = "TX"and the error text. Previously the run emitted Oregon rows and nothing else, indistinguishable from "Texas had no layoffs". If every requested state fails, the run fails and nothing is billed. - The delta engine no longer invents changes. Oregon's WARN number is not one-per-row — 397 live rows carry only 239 distinct WARN numbers, and WARN 9434 alone covers 19 separate Kroger store closures. Keying on it made a re-run against byte-identical upstream data report 146 "updated" notices, complete with invented headcount changes. A re-run now reports zero.
maxResultsis split evenly across states.maxResults: 100over["OR","TX"]used to return 100 Oregon rows and zero Texas rows with no error. Rows now also carrysource_truncatedwhen a state was cut short.- Source freshness is on every row.
source_last_notice_dateandsource_stale_days. Oregon's dataset measured 80 days since its newest notice on 2026-08-01 — a fact a buyer needs, and one no amount of offline testing could surface. - Nine fields that were fetched and thrown away are now emitted — see the table below.
- An unrecognised layoff-type value fails the run instead of being silently bucketed to
null. - Nothing was removed or renamed. Every 1.0 field still means exactly what it meant.
Who it's for
- RevOps & recruiting / staffing — catch fresh layoffs the day they're filed to source candidates or reach affected employers before competitors.
- Economic & labor-market researchers — build a clean cross-state layoff time series without hand-scraping each agency portal.
- Commercial real estate (CRE) & site selection — flag closures that free up facilities and shifts in regional employment.
- Investors & risk / supply-chain teams — track distress signals by company, county and sector.
Coverage
| State | Source | Status (verified live 2026-08-01) |
|---|---|---|
| OR Oregon | Socrata data.oregon.gov (ijbz-jpx8) | Live — 397 rows, newest notice 2026-05-13 |
| TX Texas | Socrata data.texas.gov (8w53-c4f6) | Live — 2,368 rows, newest notice 2026-06-23 |
| CA California | EDD WARN report (HTML/Excel) | Scaffolded — requesting it fails loudly |
| NY New York | NY DOL WARN (HTML) | Scaffolded — requesting it fails loudly |
| WA Washington | ESD WARN (Excel) | Scaffolded — requesting it fails loudly |
| WI Wisconsin | DWD WARN (HTML) | Scaffolded — requesting it fails loudly |
| IL Illinois | DCEO WARN (HTML/PDF) | Scaffolded — requesting it fails loudly |
| NJ New Jersey | NJ DOL WARN (HTML) | Scaffolded — requesting it fails loudly |
Adding a state is a single config block (
{ state, format, domain, datasetId, map, requiredColumns, expectedMinRows, expectedMaxRows }source.js. States marked
"scaffolded" publish only HTML/Excel/PDF today. Requesting only scaffolded states now
returns HTTP-400-style failure before the run starts rather than a zero-row success, so a
buyer never mistakes "not implemented" for "no layoffs".
Example input — snapshot
{"states": ["OR", "TX"],"mode": "snapshot","sinceDate": "2026-01-01","maxResults": 100000}
Example input — delta (scheduled monitoring)
{"states": ["OR", "TX"],"mode": "delta","sinceDate": "2026-01-01","priorKvKey": "warn_last_snapshot","deltaStoreName": "warn-layoff-delta"}
In delta mode with priorKvKey, the actor diffs against the snapshot stored under that key
in a named, cross-run key-value store and saves the current snapshot back to it — so
a daily schedule emits only what changed. (The platform's default key-value store is
per-run, so a delta built on it would find an empty baseline every run and re-report the
whole registry as "new". This actor uses a named store for exactly that reason.) The stored
key is scoped to the states and window of the run, so two schedules with different filters
cannot overwrite each other's baseline. Alternatively pass the prior records directly as
priorItems.
Output fields — all 38 declared fields
The notice
| Field | Meaning |
|---|---|
state | Two-letter code of the state registry that issued the notice (the jurisdiction). |
state_name | Full name of that state. |
company | Employer or job-site name named in the notice. |
city | City where the layoff or closure occurs. |
county | County, where the state publishes it. Texas only — Oregon publishes none. |
site_state | Two-letter state of the actual job site. Oregon publishes this and it is not always OR: 26 of 397 live rows are sites in GA, CA, IL, WI, VA and elsewhere (e.g. WARN 9178, UPS, Atlanta, GA). Texas publishes only Texas sites. |
site_state_matches_jurisdiction | true in-state, false out-of-state, null when the source publishes no site state. |
notice_date | Date the notice was filed (YYYY-MM-DD). |
state_received_date | Date the state agency received the notice. Texas publishes this separately and the two differ on 1,249 of 2,368 rows (52.7%). Oregon publishes one date, so the two agree there. |
effective_date | Date the layoff or closure takes effect. |
employees_affected | Workers affected. null, never 0, when the state published no number (4 Oregon rows, 4 Texas rows). |
layoff_type | Normalized bucket: layoff, closure or relocation. |
layoff_type_raw | The state's exact reason string. layoff_type null + layoff_type_raw null = the state does not publish a reason (all of Texas). layoff_type null + layoff_type_raw non-null = the state published a value outside the three buckets (Oregon "Other", 16 live rows). |
industry | Industry / sector. Neither Oregon nor Texas publishes it, so it is null on every row from these two sources. Retained because removing a published field would break existing pipelines; it will populate when a state that publishes industry is wired. |
region | Workforce development area. Texas only. |
notice_id | State-assigned WARN number. Oregon only — and it is NOT unique: one WARN number can cover 19 store closures. Use notice_key, not this, as a key. |
notice_key | Stable per-row cross-run key: state + notice id + company + city + effective date. Unique on 2,746 of 2,765 live rows; the residual pairs are byte-identical duplicate rows in the sources themselves. |
identity_key | Key for the notice-site independent of every changeable field. Two rows sharing it are the same site across runs even if the effective date moved. |
source_url | The official state open-data endpoint the row was pulled from. |
source_dataset_id | Socrata dataset identifier. |
retrieved_at | ISO 8601 timestamp of this run. |
The per-source outcome contract
null means not checked. false means checked and negative. These four fields exist
so a buyer can never mistake an outage for an absence of layoffs.
| Field | Meaning |
|---|---|
source_status | "ok" for the state that produced this row. |
source_row_count | Exact upstream row count (count(*)) measured on this run — the free truncation guard. null if not measured. |
source_last_notice_date | Newest notice date present in the source dataset. If this is far in the past, the registry has stopped publishing — not the employers. |
source_stale_days | Whole days between source_last_notice_date and this run. Oregon measured 80, Texas 39, on 2026-08-01. |
source_truncated | true when maxResults cut this state short. null when undetermined. |
run_states_requested | Every state this run attempted. |
run_states_ok | Every state that answered. |
run_states_failed | Requested states that did not answer. null on a healthy run. A state listed here has no rows here for reasons of availability. |
run_states_failed_reason | Per-state error text. null on a healthy run. |
run_complete | true only when every requested state answered. |
Delta mode only
change_type (new / updated / removed), plus old_employees_affected,
new_employees_affected, old_effective_date, new_effective_date, old_layoff_type,
new_layoff_type. All seven are null in snapshot mode by design.
Inputs that populate the conditionally-null fields (each verified on a live run):
county / region — any run including "TX". notice_id / layoff_type /
layoff_type_raw — any run including "OR". site_state_matches_jurisdiction = false —
{"states":["OR"]} (26 rows). layoff_type null + raw non-null — {"states":["OR"]}
(16 rows). The seven delta columns — {"states":["OR"],"mode":"delta","sinceDate":"2026-04-01","priorItems":[...]}.
run_states_failed / run_states_failed_reason — populate only during a genuine partial
upstream outage; observed live on run JkmtVBtuTh8EgXBUI's successor when
data.oregon.gov transiently refused a connection, and pinned by offline fixtures.
industry is the one field with no populating input from the two live sources.
Live drift assertions
An offline fixture cannot see a silently degraded upstream, because the fixture was shaped
from the degraded data. Before any row is fetched or billed, each live state is checked
against the running service and every measured value is written to the log
(DRIFT PROBE OR: {...}):
- Every column the mapper reads is named in a
$select. Socrata returns HTTP 400 on a renamed column, so the drift that would otherwise emit a full dataset of billable all-null rows fails the run instead. 8 columns asserted per state. - Exact row count via
count(*), checked against a measured band (Oregon 150–20,000 against a live 397; Texas 800–60,000 against a live 2,368). Bands are deliberately wide — a false-positive drift failure on a live actor costs real money. - A negative control:
<date field> >= '2999-01-01'must return exactly 0. If the$whereclause ever stops being applied,sinceDateis silently ignored, and this is what catches it. - A positive canary: the newest row must map to a non-null company and notice date.
- Freshness: the source's own
max(<date field>), reported on every row. - Closed vocabulary: any Oregon
layoff_typevalue outside the six live values fails the run rather than being bucketed tonull.
Use as an MCP tool
This actor is callable by AI agents (Claude, Cursor, etc.) via mcp.apify.com. The clean,
field-level output schema makes it a good chainable tool: an agent can pull a state's WARN
notices, filter by company, county or headcount, and hand rows to an outreach, enrichment or
analysis step. The run_complete / run_states_failed fields let an agent tell a genuine
"no layoffs" from an unavailable registry without reading logs.
Pricing
Pay per result — one WARN notice (or one delta change row) = one dataset item. Graduated discounts apply on paid Apify plans. A run that fails because every source was unavailable emits nothing and bills no result events.
FAQ
How do I monitor for new layoff notices? Run in delta mode on a schedule with a
priorKvKey; each run emits only new / updated / removed rows. The first run establishes
the baseline and reports everything as new — the log says so explicitly.
Which states are live today? Oregon and Texas, via their keyless Socrata open-data APIs. California, New York, Washington, Wisconsin, Illinois and New Jersey are scaffolded config blocks; requesting only those fails the run with a message naming the live states, rather than returning an empty dataset.
What counts as an "updated" notice? The employee count, effective date, notice date, or layoff type changed versus the prior snapshot — for the same job site. A revision to a region label or the run timestamp is not a change.
Why does an Oregon row sometimes show a city outside Oregon? Because Oregon's registry
contains them. state is the issuing registry; site_state is where the job site actually
is, and site_state_matches_jurisdiction flags the 26 live rows where they differ.
Oregon's newest notice is months old — is the actor broken? No: source_last_notice_date
and source_stale_days report the state of the source dataset. Oregon's Socrata dataset
had not been refreshed for 80 days as of 2026-08-01. Every row tells you that.
Do I need an API key? No. All sources are public and keyless.
How is it billed? Pay per result — one WARN notice (or one delta change row) = one dataset item.
Related actors
sos-registry-monitor— new business registrations across state Secretary-of-State registries; the growth-side counterpart to this actor's distress signal.fdic-ncua-health-rollup— bank and credit-union financial health, for the same regional-distress question from the balance-sheet side.city-business-license-leads— municipal licence filings for local market-entry signal.