Spaces:
Running
A free WARN Act API β 61,431 layoff notices, 48 states, one GET request
No key, no signup, no rate limit, CORS open. Every US state publishes the mass-layoff notices employers file under the WARN Act, and every state publishes them differently. We scrape all 48 of them every morning, normalize them into one 11-field schema, resolve the employer names, and serve the result as plain JSON and CSV over HTTPS. Rebuilt 2026-09-25; newest notice in this build is dated 2026-09-25. CC BY 4.0 β credit "WARN Feed".
Full docs, examples and a per-state list: https://approjects-warn-act-notices.static.hf.space/api.html
Quickstart
# the whole archive as JSON
curl -sL https://approjects-warn-act-notices.static.hf.space/data/warn_notices.json | jq '.[0]'
# just what is new β poll this one daily
curl -sL https://approjects-warn-act-notices.static.hf.space/data/latest.json | jq '.count, .generated_at'
# poll politely: every file carries an ETag; send it back and an unchanged file is a 304 with no body
curl -sL -o latest.json -D - -H 'If-None-Match: "<etag from last run>"' https://approjects-warn-act-notices.static.hf.space/data/latest.json
# streaming: one notice per line (NDJSON), no 20 MB buffer
curl -sL https://approjects-warn-act-notices.static.hf.space/data/warn_notices.ndjson | head -n 3 | jq -c '{company_canonical, state, notice_date}'
# one state, as CSV
curl -sL https://approjects-warn-act-notices.static.hf.space/data/by-state/ca.csv | head -3
Files over ~10 MB (the JSON and NDJSON archives) answer 302 to a CDN copy that
sends the same CORS header β keep -L (every HTTP library follows by default).
import pandas as pd
df = pd.read_csv("https://approjects-warn-act-notices.static.hf.space/data/latest.csv")
print(len(df), df.columns.tolist())
From an LLM or an agent: the MCP server
warn-mcp wraps these endpoints in six read-only
Model Context Protocol tools, so an agent asks
a question instead of pulling a 9 MB file into a context window: employer +
state + date-range search, the rolling new-notice feed, one employer's whole
history back to 1988, monthly state totals, the revision log (which rows changed
or vanished between daily builds, tagged by what is mechanically distinguishable β
never a guess at why), and a freshness call. Standard library only,
no key, disk cache with ETag revalidation.
claude mcp add warn -- uvx --from git+https://github.com/APVentureEngine/warn-mcp warn-mcp
Any client that reads an mcpServers block (Claude Desktop, Cursor, Continue):
{"mcpServers": {"warn": {"command": "uvx",
"args": ["--from", "git+https://github.com/APVentureEngine/warn-mcp", "warn-mcp"]}}}
Prefer a URL to a subprocess β ChatGPT and Claude.ai connectors, n8n, anything
that only speaks remote MCP? The same six tools are hosted over Streamable HTTP
at https://mQpACuIiQcnwK93JY.apify.actor/mcp. One honest caveat: the host
meters compute to whoever calls it, so that endpoint needs YOUR own free Apify
API token in an Authorization: Bearer header. We charge nothing for it and
keep nothing. The install-free bundle above needs no token of any kind, so use
it instead if your client can.
Both routes are listed as io.github.APProj/warn-mcp in the
official MCP registry.
Source, tool reference and issues: https://github.com/APVentureEngine/warn-mcp
Endpoints
| Endpoint | What | Records | Size |
|---|---|---|---|
/data/warn_notices.json |
Whole archive, JSON | 61,431 notices | 20.1 MB |
/data/warn_notices.ndjson |
Whole archive, NDJSON | 61,431 notices | 18.7 MB |
/data/latest.csv |
Recent notices, CSV | 88 notices | 16 kB |
/data/latest.json |
Recent notices, JSON | 88 notices | 36 kB |
/datapackage.json |
Schema (Frictionless Table Schema) | 11 fields | 3 kB |
/data/coverage.json |
Per-state coverage + freshness | 48 states | 11 kB |
/data/stale.json |
Sources behind their usual cadence | 10 late sources | 2 kB |
/data/trends.json |
Monthly series | 24 months | 56 kB |
/data/search-index.json |
Employer search index | 29,971 employers | 2.7 MB |
/data/badge.json |
Shields.io endpoint badge | β | 153 B |
/feed.xml |
RSS of new notices | 50 items | 29 kB |
Per-state CSVs for 48 states: https://approjects-warn-act-notices.static.hf.space/data/by-state/<two-letter-code-lowercase>.csv
(AK, AL, AZ, CA, CO, CT, DC, DE, FL, GA, HI, IA, ID, IL, IN, KS, KY, LA, MA, MD, ME, MI, MN, MO, MS, MT, NC, ND, NE, NJ, NM, NV, NY, OH, OK, OR, PA, RI, SC, SD, TN, TX, UT, VA, VT, WA, WI, WV).
Schema
| Field | Type | Meaning |
|---|---|---|
id |
string | Stable dedupe id (source record number where available, else content hash) |
state |
string | 2-letter US postal code |
company |
string | Employer name exactly as published by the state |
company_canonical |
string | Cleaned employer name; groups the same employer across states, renotices and store numbers |
company_dba |
string | Trade name when the state published a dba/aka alias |
location |
string | City/county/address, best effort |
employees_affected |
integer | Workers affected; empty if the state omitted it |
notice_date |
date | ISO date the notice was received/posted (NJ: month precision, day pinned to 01) |
effective_date |
date | ISO date the layoff/closure takes effect |
notice_type |
string | Layoff/closure label as published |
first_seen |
datetime | UTC timestamp the pipeline first saw this notice |
What this API does not do
- It does not push. A snapshot cannot tell you that your employer just filed; you would poll and diff it yourself. warn-layoff-alert-bot is a 120-line, dependency-free example that does exactly that from a daily GitHub Actions cron and posts to Slack or Discord (MIT; fork it).
- It does not filter. Static files have no query parameters.
- It is a once-a-morning rebuild, not a stream.
If what you wanted was an alert rather than a file, WARN Watch runs your employer list (up to 500 names, or whole states) against every daily refresh for a year and pushes hits to a private page, RSS, a calendar and your Slack/Discord/Teams webhook β $49/year, one payment, or a free 30-day trial.
Need an endpoint we do not publish? Open an issue and say which field, state or shape β the pipeline runs every day anyway.