ImmigrationClockFacts first
Open data

Free WARN layoff API

A machine-readable feed of real WARN Act layoff notices — no key, no signup, no paywall. JSON and CSV, refreshed on every build, with a link back to the government source on every row.

Notices
7,496
Employers
5,867
Employees
967,919
States
5
Structured feeds

Endpoints

Stable URLs. Fetch them from anywhere — server, notebook, or spreadsheet.

GET /api/warn.json
Full feed: notices, per-employer aggregates, per-state summaries.
Open JSON →
GET /api/warn.csv
Every notice as a flat CSV — one row per notice.
Download CSV →

Intelligence API (v1)

The change archive and employer signals as data. Read-only, free, no key. Versioned from the first release, and every response carries its source and a schema version so you can pin against it.

GET /api/v1/changes
Recorded changes, newest first. Filter by visa, form, process, country, agency, classification, status, since, until.
Open JSON →
GET /api/v1/monitor
The intelligence inbox. Pass the visas, countries, forms, processes, agencies or topics a customer follows and get back what needs attention, what takes effect soon, and the evidence behind each classification. The watchlist travels in the query string and is never stored.
Open JSON →
GET /api/v1/changes/{id}
One change. The id is the six characters that end a /what-changed/ URL.
GET /api/v1/employers/{slug}/signals
H-1B sponsorship, WARN layoff filings, and the overlap between them — each signal with its source fact, how the join was made, and the caveat that goes with it.
GET /api/v1
Endpoints, coverage counts and the boundary.
Open JSON →

Example

curl -s "https://immigrationclock.com/api/v1/changes?visa=h-1b&since=2026-01-01&limit=3" | jq '.data[] | {title, status, effectiveDate, source: .source.url}'

Three ways to integrate

1. Pull. Call /api/v1/monitor on a schedule with the dimensions your customer follows. Available today, free, no key.

2. Embedded intelligence. Render our change records inside your own workflow. Every record carries its source URL, its effective date, its evidence quotes and its limitations, so it can be shown without you having to vouch for anything we have not measured.

3. Push. Not offered. A webhook implies we will tell you about everything, and no dimension’s measured recall supports that claim yet. When one does, it will say so here with the number beside it.

How good is the classification?

Measured against hand-labelled records rather than asserted, and published per dimension. Filtering visa=h-1b scores 100% precision and 83% recall against 33 hand-labelled records — every record in the archive whose text names H-1B. Countries score 98% precision and 61% recall across 249 labelled pairs, forms 93% and 58% across 185, and employment processes 100% and 64% across 72. Recall below 100% is the honest number rather than a rounding of it. Some of the gap is recoverable: ?include=weak stops filtering matches the record already holds, which covers 30 of the 84 misses behind those figures — mostly forms. The other 54 are not in the record in any form, and no parameter will return them.

Every classification carries the verbatim quote it came from and the method that established it — whether the value appeared in the document’s title, its summary, or only in a citation. Responses return the strong methods by default. Add include=weak to also receive matches drawn from footnotes and historical asides, each labelled as such.

Coverage is a separate question and is deliberately partial: a record is classified only where its own text names the value. An empty list therefore means the document did not name one — never that we judged it irrelevant. Read classificationState to tell that apart from a record nobody has examined.

What it will not do. It describes published government material. It is not legal advice, it makes no determination about any individual or case, and it returns no personal data because it holds none. An absent field means the source did not state it — nothing is inferred to fill a gap.

Quick start

curl

curl -s https://immigrationclock.com/api/warn.json | jq '.notices[0]'

JavaScript

const res = await fetch("https://immigrationclock.com/api/warn.json");
const { notices } = await res.json();
// most recent first
console.log(notices.slice(0, 5));

Python (pandas)

import pandas as pd
df = pd.read_csv("https://immigrationclock.com/api/warn.csv")
df.groupby("state")["employees"].sum().sort_values(ascending=False)

Notice schema

FieldDescription
employerEmployer name as filed with the state
normalizedStandardized name used to join across datasets (H-1B, LCA)
cityWorksite city, where published
countyCounty/parish, where published
stateTwo-letter USPS state code
noticeDateISO date the state received the notice
effectiveDateISO date the layoff takes effect, where published
employeesEmployees affected (0 when not disclosed)
layoffTypeLayoff / closure / relocation type, where published
sourceUrlLink to the government portal the notice came from

The JSON payload also carries byEmployer (per-employer totals with the same normalized key) and states (per-state counts + the source portal), plus generatedAt and coverage metadata.

Coverage & cadence

There is no national WARN feed. This covers the states that publish a structured, machine-readable feed — currently NJ, WA, TX, VA, CA — and grows as more states do. The data refreshes on every site build. For wider (PDF/HTML) state coverage, see the layoffs vs H-1B analysis and the live feed.

Methodology & sources
Notices are public records filed by employers with state workforce agencies. The normalized field is a best-effort standardization for joining employers across datasets; verify against sourceUrl for anything consequential. WARN reports planned layoffs and does not indicate whether or how roles relate to visa sponsorship. Read the full methodology →