# US WARN Layoff Notices - Oregon & Texas (`maydit/us-warn-layoff-notices`) Actor

Official Oregon and Texas WARN notice records with source links, reported worker counts, explicit date meanings and saved revision comparisons. Keyless; bounded state coverage.

- **URL**: https://apify.com/maydit/us-warn-layoff-notices.md
- **Developed by:** [Brandt May](https://apify.com/maydit) (community)
- **Categories:** News, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.80 / 1,000 layoff notice observations

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

![Track published WARN notices — illustrative workflow](https://api.apify.com/v2/key-value-stores/YGxD9JRpduom8Q5Zd/records/us-warn-layoff-notices-942d4ff1d5db.png?signature=1IVBt57jesMfv4TxXpfvf)

### Track published WARN notices

For workforce researchers and company watchlists, collect official WARN notice observations and compare revisions to the same source record.

**Coverage:** Oregon HECC and Texas TWC only, within the selected page window. Agency update cadence determines freshness.

[Open this Actor in Console](https://console.apify.com/actors/Dq2OyjowuZcmccMah/input) · [First run](#try-this-actor) · [Results](#result-preview) · [Cost](#usage-and-pricing) · [Full guide](#full-guide)

### Try this Actor

1. Use the existing “Recent Oregon notice observations” example below: up to five saved notices from one inspected page, without comparison history.
2. Open the dataset for notices and source links. In the key-value store, inspect `SUMMARY.sources` for page coverage and source status.

**Read the results correctly:** Notices are not a census of layoffs or proof of completed job losses. Oregon's reported city may be a corporate location; repeat counts are not unique workers.

**Oregon WARN Notice Observations** — copy this input into the JSON editor in Console.

```json
{"states":["OR"],"maxResults":5,"maxSourcePages":1}
```

### Result preview

The dataset view highlights these columns:

- **Source state** · `state`
- **Published employer** · `employerName`
- **Reported location** · `reportedLocation`
- **Source notice date** · `noticeDate`
- **Meaning of notice date** · `noticeDateMeaning`
- **Effective layoff date** · `effectiveDate`

Use the original source links and the field definitions below when interpreting the results. CSV works well for flat columns; JSON preserves nested values.

### Usage and pricing

Base result rate on the FREE tier: **$3 per 1,000 layoff notice observations**. The [Pricing tab](https://apify.com/maydit/us-warn-layoff-notices/pricing) shows your plan's result rate and any Actor Start charge. Set a small result limit for the first run; the requested limit is not a guarantee of that many results.

***

### Customer workflow: A source-linked WARN revision desk

Keep one current row for each published Oregon or Texas notice, with revisions separated from first observations. Researchers can review the original notice before using it in a company or regional brief.

**Setup:** Connect your own Apify and Google Sheets notice register and a human review queue through [Make](https://docs.apify.com/integrations/make) or [n8n](https://docs.apify.com/integrations/n8n). Keep credentials in your connector's credential manager.

```json
{
  "states": [
    "OR"
  ],
  "maxSourcePages": 1,
  "maxResults": 100,
  "comparePrevious": true,
  "onlyChanges": false,
  "snapshotName": "customer-or-warn-v1",
  "maxRunSeconds": 240
}
```

Start with a **300-second Run timeout** and **$0.50 maximum run charge**, alongside the input's 240-second budget. Check current pricing and the selected scope before increasing either limit.

1. Create a Notices sheet with one row per `id`. Run the input above once and seed the register. Label these rows "First observed" so an older notice is not presented as a newly announced layoff.
2. Review Run report and `SUMMARY`. Require no source, time, spending, or history errors; check each row has `sourceCollectionComplete: true`. Save the whole matched page window before treating this as an established baseline.
3. For later runs, keep the same scope and `snapshotName`, then set `onlyChanges: true`. Run one writer at a time. In n8n use Sheets "Append or Update Row"; in Make use a key lookup followed by update-or-create.
4. Route `changed` rows to a revision queue with the official `recordUrl`, `changedFields`, and previous/current worker counts. Let a researcher review the notice before adding it to a brief.

| Destination information | Actor fields |
| --- | --- |
| Sheet key | `id` |
| Employer and place | `employerName`, `reportedLocation`, `locationMeaning` |
| Dates and their meanings | `noticeDate`, `noticeDateMeaning`, `effectiveDate` |
| Reported count revision | `affectedWorkers`, `previousAffectedWorkers`, `affectedWorkersDelta` |
| Evidence | `recordUrl`, `contentHash`, `observedAt` |

**Keep the meaning:** This input inspects one Oregon page, currently 20 notices. OR and TX are the only supported sources. Notice dates are source-defined, and Oregon locations can be corporate locations. Repeat notices and amendments must not be summed as unique people.

**Empty or interrupted runs:** A healthy change-only repeat may be empty. Keep the existing sheet; absence is not withdrawal. First observations mean new to your saved history, not newly published.

**Reliable delivery:** Read the completed run's own SUMMARY and paginated dataset. Retain its run ID; if destination delivery fails, replay that dataset and deduplicate by run ID plus row key. Keep destination writes sequential, and write source text literally.

**Validation:** Inputs and mappings were checked locally against this Actor. The exact customer connection has not been run end to end. Choose recurrence after a manual bootstrap; this guide creates no schedule. See the [run API](https://docs.apify.com/api/v2/actors-runs-post), [pagination guide](https://docs.apify.com/api/v2/dataset-items-get), and the full Actor guide below for detailed setup and limits.

### Full guide

Read official WARN notice records from **Oregon HECC and Texas Workforce Commission**. Get employer names, reported worker counts, source links, dates with explicit meanings, and optional comparisons with previously saved observations.

Useful for company watchlists, workforce research, regional reporting and recruiting operations. Each result retains its source record ID and a content hash so a changed headcount can be handled as a revision to that record.

#### Coverage and source meaning

| Source | Fields and limits |
| --- | --- |
| [Oregon HECC WARN list](https://ccwd.hecc.oregon.gov/Layoff/WARN) | Tracking number, Notification Date, employer, published City, affected-worker count, layoff type and notice-attachment page. The index does not expose an effective layoff date. Published City can be an employer or corporate location outside Oregon; it is **not a verified affected worksite**. |
| [Texas TWC open data](https://data.texas.gov/dataset/Worker-Adjustment-and-Retraining-Notification-WARN/8w53-c4f6) | Socrata row ID, employer/job-site name, affected city/county/workforce area, notice receipt date, effective layoff date, reported worker count and TWC system-entry date. Dataset update time is included when available. |

`noticeDateMeaning` distinguishes Oregon's published Notification Date from Texas's employer-notice receipt date. Neither is advertised as a publication date. `observedAt` is this Actor's retrieval time; `sourceDataUpdatedAt` is Texas's dataset update time. No publication timestamp is inferred.

**These are published notices, not all layoffs or confirmed completed job losses.** Notices can change, be withdrawn, cover phased separations or overlap. Do not add repeat observations, amendments or matching company names together as unique people. Employer names are not resolved to legal entities. The Actor does not read notice PDFs, extract employee names, infer layoff causes, assess legal compliance or predict financial distress.

At the October 8, 2026 source check, Oregon's recent list included an October 6 notice. Texas's dataset was last updated July 7 and its newest notice-received date was June 23. Source freshness depends on the agency; successful retrieval does not imply new notices or same-day coverage.

#### Quick start

Run `{}` without credentials. Code defaults select Oregon, inspect one index page (currently 20 notices), and save up to 10 matching observations. No proxy or browser is required.

The Actor supports only OR and TX. It sorts matching observations by `noticeDate` descending after collection. Oregon's index is traversed in its published order; a bounded window is not a claim of complete chronological or statewide coverage. Texas pages are ordered by received date and source ID. See `SUMMARY.sources` for inspected pages, latest date within the window, source failures and whether the end of each published index was reached.

#### Inputs

| Input | Default | Meaning |
| --- | --- | --- |
| `states` | `["OR"]` | `OR`, `TX`, or both. Empty also selects OR. |
| `maxResults` | `10` | Saved notice observations across selected sources, 1–1000. |
| `maxSourcePages` | `1` | Pages inspected per state, 1–20. Oregon currently returns 20 records/page; Texas uses 100. Filters apply to this inspected window. |
| `companyNames` | `[]` | Up to 30 case-insensitive employer-name fragments, matched with OR logic. No company discovery outside the inspected pages. |
| `noticeDateFrom`, `noticeDateTo` | empty | Inclusive YYYY-MM-DD bounds on each source's notice date. These do not filter the effective layoff date. |
| `minAffectedWorkers` | `0` | Minimum published worker count. Zero retains records with an unknown count. |
| `comparePrevious` | `false` | Compare each record against its last saved observation. |
| `onlyChanges` | `false` | Enables comparison and emits first observations or changed records. |
| `snapshotName` | `"default"` | Independent history namespace, 1–80 letters, digits, `_` or `-`. Use one concurrent writer per name. |
| `maxRunSeconds` | `240` | Actor budget, 30–900 seconds, also constrained by the platform deadline with a 25-second reserve. |

#### Three exact examples

##### 1. Recent Oregon notice observations

Use the [copyable first-run input](#try-this-actor) above.

##### 2. Texas notices with effective layoff dates

```json
{"states":["TX"],"maxResults":5,"maxSourcePages":1}
```

##### 3. Larger reported workforce reductions in both sources

```json
{"states":["OR","TX"],"minAffectedWorkers":100,"maxResults":10,"maxSourcePages":1}
```

These examples do not require a baseline. Their date coverage follows the agencies' currently available data and the inspected page window.

#### Output

One dataset row is one successful source-record observation. Main fields:

- `id`, `state`, `sourceRecordId`, `sourceName`, `sourceUrl`, `recordUrl`.
- `employerName`, `reportedLocation`, `locationMeaning`, `county`, `workforceArea`.
- `noticeDate`, `noticeDateMeaning`, `effectiveDate`, `systemEnteredDate`.
- `affectedWorkers`, `layoffType`, and `raw` source date/count values.
- `contentHash`, `observedAt`, `sourceDataUpdatedAt`, `sourceCollectionComplete`.
- `comparisonStatus`, `changed`, `changedFields`, `previousObservedAt`, `previousAffectedWorkers`, `affectedWorkersDelta`.

Fields unavailable in a source are null. An Oregon `recordUrl` leads to its official notice attachment index, not extracted PDF content. Texas's record link is a public API query for that exact source row.

`affectedWorkersDelta` compares the same source record's current and previously saved counts. A negative value is a revision, not evidence that jobs were restored. `first_observation` means this record has no saved history in the selected namespace; it does not mean the agency just published it. Texas source IDs can change if the agency replaces its dataset, which would create new observations in this Actor's history.

#### Change tracking and history

History uses an Actor-specific named key-value store. **The first comparison run emits the matching inspected records.** Repeat runs with `onlyChanges: true` can legitimately return zero rows. Unchanged records are not billed because no dataset row is saved. If `maxResults` or a spending limit stops the first run before the whole inspected window is saved, a later run may emit the remaining previously unseen records.

The content hash covers the normalized employer, location, dates, worker count and type. Retrieval time and dataset update time do not cause false content changes. History advances only after a confirmed dataset write, and only if that source completed its selected page window. Failed collection, invalid history, exhausted deadlines and rejected output do not overwrite the affected history. Storage write failures are reported in SUMMARY. A saved final row at a charge limit can still update its history.

The Actor never treats a missing notice as a deletion or withdrawal. An index omission, changing page window or state archive rollover is insufficient evidence. Separate snapshots do not coordinate; use one writer at a time per `snapshotName`.

#### Run summary, limits and failures

`SUMMARY` in the default key-value store records `total`, `matched`, `inspected`, `sources`, `failedSources`, `scopeLimited`, `incomplete`, charge/deadline stops and history updates. `savedSourceNoticeCount` counts distinct source IDs in saved output. `distinctPublishedEmployerNames` counts exact published names, not unique legal entities. Worker counts are not summed.

An intentional page/output bound sets `scopeLimited`; it is not an upstream failure. Partial failures set `incomplete` and `status: "partial"`. If every source fails, or the deadline expires before any usable output, the run fails with diagnostics instead of saving error rows. Valid empty filters, unchanged windows and a spending limit permitting no rows return a clear summary. Successful records from an earlier page may be saved after a later-page failure with `sourceCollectionComplete: false`; their history is not advanced.

Public requests respect robots directives, public-address checks, redirect validation, response-size limits and the remaining deadline. Texas requests are paced at least one second apart. A bounded retry is used for 429/5xx responses; access restrictions are not bypassed. Socrata allows [unauthenticated queries](https://dev.socrata.com/docs/app-tokens.html) but applies shared IP rate limits. The Actor needs no API key. Oregon's older Socrata dataset is not used because it was unavailable during qualification.

#### Pricing

The proposed price is **$0.003 per saved notice observation** ($3 per 1,000). The Store's current pricing card is authoritative, including any Actor start charge and plan discounts. An observation with unavailable optional fields is still a notice; fake error rows are never saved. Comparison rows repeat a source notice when its tracked fields change or when comparison is disabled.

#### Support

For bugs or source corrections, use Actor Issues or email **bmay@mayd-it.com**. Please include the run ID and source record ID, without credentials or employee personal information. Public data correction requests should also be directed to the relevant publishing agency.

### Help with your run

Open the **Issues** tab on this Actor with the run URL, the input field that caused trouble and what you expected to receive. Remove API keys and private information before posting.

[Explore more Mayd-It Actors](https://apify.com/maydit)

### Understand your run

Open **Run report** in the run’s Output tab for saved-record counts, reported source issues and limits, and suggested next steps. Use **CSV export** to take the saved results into a spreadsheet. The existing JSON results and detailed machine-readable summary remain available.

The report reflects this run’s recorded coverage. A successful run or a saved result does not establish that every possible source record was collected.

# Actor input Schema

## `states` (type: `array`):

OR and/or TX only. Empty or omitted selects Oregon. This is source coverage, not a claim of all layoffs in either state. Oregon City values may be corporate locations.

## `maxResults` (type: `integer`):

Global saved-observation cap across selected states. Results are sorted by each source's notice date within the inspected page window. Later runs may emit previously unsaved records.

## `maxSourcePages` (type: `integer`):

Bounded inspection window per selected source. OR currently returns 20 records/page and TX uses 100. Filters apply only to this inspected window; increase to search older records.

## `companyNames` (type: `array`):

Up to 30 case-insensitive employer-name fragments, matched with OR logic within the inspected pages. Empty means no name filter. No parent-company/entity inference.

## `noticeDateFrom` (type: `string`):

Optional inclusive YYYY-MM-DD. OR uses published Notification Date; TX uses receipt of employer notice. This is not a publication-date or effective-layoff-date filter.

## `noticeDateTo` (type: `string`):

Optional inclusive YYYY-MM-DD on source notice date. Must not precede noticeDateFrom. Dates are calendar dates without an inferred timezone.

## `minAffectedWorkers` (type: `integer`):

Minimum published affected-worker count. Zero includes unknown counts. Counts are reported notices, not confirmed completed layoffs or unique people.

## `comparePrevious` (type: `boolean`):

Compare each source record with its last saved observation in this snapshot. First observations are emitted. Source failures or rejected output do not advance history. One writer per snapshotName.

## `onlyChanges` (type: `boolean`):

Enables comparison and skips unchanged notices. The first run emits matching inspected records; later runs may legitimately return zero. Missing records never imply deletion.

## `snapshotName` (type: `string`):

1–80 letters, digits, underscore or hyphen. Reuse the same name to compare source IDs across runs; only one concurrent writer per name. Invalid history is preserved.

## `maxRunSeconds` (type: `integer`):

Own wall-clock budget; all source requests/retries are constrained to remaining time. A platform deadline reserve of 25 seconds also applies. Early stops are recorded in SUMMARY.

## Actor input object example

```json
{
  "states": [
    "OR"
  ],
  "maxResults": 10,
  "maxSourcePages": 1,
  "companyNames": [],
  "minAffectedWorkers": 0,
  "comparePrevious": false,
  "onlyChanges": false,
  "snapshotName": "default",
  "maxRunSeconds": 240
}
```

# Actor output Schema

## `results` (type: `string`):

Successful source-record observations. Counts are reported, and dates have explicit source meanings. Inspect sourceCollectionComplete before using history.

## `runReport` (type: `string`):

Readable summary of saved records, reported source coverage, limits and next steps. Available when this run saves its SUMMARY.

## `csvExport` (type: `string`):

Download saved dataset records as a CSV file for spreadsheets and other tools.

## `summary` (type: `string`):

Saved counts, inspected pages, freshness, source failures, spending/deadline stops and history updates. Intentional scope limits do not imply full coverage.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "states": [
        "OR"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("maydit/us-warn-layoff-notices").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "states": ["OR"] }

# Run the Actor and wait for it to finish
run = client.actor("maydit/us-warn-layoff-notices").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "states": [
    "OR"
  ]
}' |
apify call maydit/us-warn-layoff-notices --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,maydit/us-warn-layoff-notices"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/Dq2OyjowuZcmccMah/builds/K7S7DbOyioIhE8GC5/openapi.json
