# OSHA Injury & Illness Data (ITA Form 300A) Rate Monitor (`malonestar/osha-ita-injury-illness-establishment-monitor`) Actor

Establishment-level OSHA Form 300A injury and illness data from the OSHA Injury Tracking Application (ITA), CY2016 onward. Total Case Rate and DART injury rates from OSHA's own formula, a peer-industry median benchmark computed from the filers themselves, and a year-over-year delta. Keyless.

- **URL**: https://apify.com/malonestar/osha-ita-injury-illness-establishment-monitor.md
- **Developed by:** [Kyle Maloney](https://apify.com/malonestar) (community)
- **Categories:** Business, Developer tools, Agents
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.40 / 1,000 establishment injury & illness records

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## OSHA Injury & Illness Data (ITA Form 300A) — establishment rates, industry benchmark, and year-over-year delta

Establishment-level workplace injury and illness data straight from **OSHA's Injury Tracking Application (ITA)**, calendar years **2016 through the current filing year**, with the **Total Case Rate (TCR)** and **DART rate** computed using OSHA's own published formula, a **peer-industry median** computed from the filers themselves, and a **year-over-year delta**.

Keyless. No login, no API key, no scraping of a search UI — this reads the bulk Form 300A files OSHA publishes on its own data page.

**Every March 2, employers above OSHA's size and industry thresholds must electronically submit their prior-year Form 300A summary.** OSHA then publishes the whole national file. That deadline is the recurring event this actor exists to serve: run it after each March filing window to see who filed, what their rates look like against their industry, who got worse, who stopped filing.

***

### Who this is for

- **EHS / safety consultants and brokers** — benchmark a prospect or a client against every other ITA filer in the same NAICS industry, nationally, in the same year. "Your TCR is 11.4 against an industry median of 3.2" is a sales conversation.
- **Workers' comp underwriters and risk engineers** — an employer-reported, government-published injury rate per establishment, with the denominators (hours worked, employees) visible so you can audit the arithmetic yourself.
- **Union organizers, plaintiff-side researchers, and journalists** — establishment-level injury counts, deaths, and days away from work, by employer name and street address.
- **Corporate safety teams** — pull your own establishments' filings back out, compare sites against each other and against the industry, and check what OSHA actually has on file for you.
- **Supply-chain and vendor-risk teams** — screen contractors and suppliers by name across a state before you sign.
- **AI agents** — clean, fully described fields with an explicit `rate_basis` on every row, so an agent can tell "rate is 0" from "there is no rate".

### What makes this different

Every OSHA actor on the Apify Store reads the **inspection and enforcement** database (citations, penalties, violations). This one reads the **injury file** — a completely different OSHA dataset that nobody sells. An inspection record tells you OSHA showed up. This tells you how many people got hurt.

It also does the two things a raw dump does not:

1. **Computes the rates.** OSHA publishes counts and hours, not rates. TCR and DART are computed here with OSHA's published formula and the arithmetic is spelled out on every row.
2. **Benchmarks against the peer group.** For each establishment, the median TCR of every other ITA filer nationally in the same NAICS prefix and the same year, plus this establishment's percentile within that group. The peer group falls back 6-digit → 4-digit → 2-digit until it has at least 20 filers, and the level it actually used ships on the row.

***

### Example input

```json
{
  "states": ["CO"],
  "years": ["2024"],
  "naicsPrefixes": ["23"],
  "onlyWithRecordableCases": true,
  "maxResults": 300
}
```

Year-over-year change for every Colorado hospital:

```json
{
  "states": ["CO"],
  "years": ["2024"],
  "mode": "delta",
  "naicsPrefixes": ["622"]
}
```

One employer's whole footprint in a state:

```json
{
  "states": ["TX"],
  "years": ["2024"],
  "nameContains": "Kroger"
}
```

### Input fields

| Field | Required | What it does |
|---|---|---|
| `states` | **yes** | Two-letter state codes. Matching is case-insensitive because OSHA's own file carries mixed-case spellings in some years. Also accepts AS, GU, MP, PR, VI, AA, AE, AP. |
| `years` | **yes** | Calendar years, e.g. `["2024"]`. Max 3 per run. The published year list is read live from OSHA's data page every run; an unpublished year fails loudly with the list of years that do exist. |
| `mode` | no | `establishments` (default) or `delta`. |
| `naicsPrefixes` | no | 2- to 6-digit NAICS prefixes. Prefix matching, not exact-code matching — see the NAICS note below. |
| `nameContains` | no | Case-insensitive substring across both `establishment_name` and `company_name`. |
| `minEmployees` | no | Minimum annual average employees. An establishment that reported no employee count is excluded, because an unreported count is not a small count. |
| `onlyWithRecordableCases` | no | Keep only establishments that reported at least one case or death. Off by default — a zero-case filing is a real answer. |
| `maxResults` | no | Hard cap on emitted rows, and therefore on what you are billed. Default 500. |

***

### Output fields

One row per establishment per calendar year (`mode: "establishments"`), or one row per establishment (`mode: "delta"`). **84 fields**; every one of them is documented in the dataset schema and visible on the Store page.

#### Identity and location

`record_type` · `run_mode` · `filing_year` · `establishment_id` · `record_id` · `establishment_name` · `company_name` · `street_address` · `city` · `state` · `zip_code` · `ein`

`establishment_id` is OSHA's own stable identifier and is the documented key for linking to OSHA's case-detail files.

#### Industry and size

`naics_code` · `naics_vintage_year` · `naics_vintage_raw` · `industry_description` · `establishment_type_code` · `size_code` · `size_code_peer_count` · `size_code_peer_median_employees` · `annual_average_employees` · `total_hours_worked`

`size_code` ships as OSHA's **raw code with no invented label**, because the code set is not stable (see gotchas). `size_code_peer_median_employees` gives you what the code actually means *in this file*: the median employee count of every establishment carrying the same code.

#### Reported counts (OSHA Form 300A columns G–M)

`had_recordable_cases` · `no_injuries_illnesses_code` · `total_deaths` (G) · `total_dafw_cases` (H) · `total_djtr_cases` (I) · `total_other_cases` (J) · `total_recordable_cases` (H+I+J) · `dart_cases` (H+I) · `total_dafw_days` (K) · `total_djtr_days` (L) · `total_injuries` (M1) · `total_skin_disorders` (M2) · `total_respiratory_conditions` (M3) · `total_poisonings` (M4) · `total_hearing_loss` (M5) · `total_other_illnesses` (M6)

#### Computed rates

`total_case_rate` · `dart_rate` · `dafw_case_rate` · `rate_basis` · `rate_is_implausible` · `rate_formula` · `data_quality_flags`

```
Total Case Rate (TCR) = (H + I + J) x 200,000 / hours worked
DART rate             = (H + I)     x 200,000 / hours worked
```

That is OSHA's published Rate Calculation, verbatim. 200,000 is 100 full-time-equivalent workers for a year.

`rate_basis` is the honest part. It is one of `computed`, `hours_not_reported`, `hours_reported_zero`, `case_counts_incomplete` — or, in delta mode, `establishment_absent_in_current_year` / `establishment_absent_in_prior_year`. **When a rate cannot be computed it is `null`, never `0`.**

#### Industry benchmark

`industry_benchmark_naics_level` · `industry_benchmark_naics_prefix` · `industry_benchmark_peer_count` · `industry_median_total_case_rate` · `total_case_rate_vs_industry_median` · `total_case_rate_percentile_in_industry` · `industry_benchmark_note`

#### Delta mode only

`prior_filing_year` · `filing_status` · `prior_annual_average_employees` · `prior_total_hours_worked` · `prior_total_recordable_cases` · `prior_total_deaths` · `prior_total_case_rate` · `total_case_rate_change` · `total_case_rate_change_pct` · `rate_direction` · `prior_rate_basis` · `prior_dart_rate` · `stopped_filing_note` · `delta_current_year` · `delta_prior_year` · `prior_data_source_file` · `prior_data_vintage_last_modified` · `prior_national_filers_scanned`

`filing_status` is `continuing`, `new_filer` or `stopped_filing`.

#### Provenance and completeness

`submitted_date` · `change_reason` · `data_source_url` · `data_source_file` · `data_vintage_last_modified` · `source_file_changed_since_last_run` · `national_filers_scanned` · `optional_columns_present` · `matched_rows_total` · `max_results` · `results_truncated` · `retrieved_at` · `in_ita_scope_note` · `data_quality_note`

`source_file_changed_since_last_run` is `null` on the first run for a given scope — **never `false`**. Having never looked is not the same as nothing having changed.

***

### Honesty and limitations — read this before you use a number

These are not editorial hedges. They come from measuring the live files, and several of them ship as text on every row.

**Absence from this dataset is not evidence that an establishment had no injuries.** OSHA collects Form 300A data only from establishments with 250+ employees not in the exempt-industry list (29 CFR 1904 Subpart B App A), and from establishments with 20–249 employees in the 300A Table (29 CFR 1904 Subpart E App A). Most US workplaces are out of scope entirely. OSHA also states it has not removed data submitted by establishments that were *not* required to submit, so the file contains some voluntary filers too. This sentence ships on every row as `in_ita_scope_note`.

**OSHA does not validate what employers report.** OSHA's own guidance says concluding an establishment is the "most dangerous" or "least dangerous" solely from these rates would be inappropriate. This ships on every row as `data_quality_note`. Concretely, in the CY2024 file: one establishment reports **41,092,597 employees**, another reports **862,847,000,000 hours worked**, **763 rows** compute a TCR above 200 per 100 workers, and **1,574 rows** report zero hours. None of that is corrected here — it is flagged in `data_quality_flags`, and flagged rows sort **below** sound ones so a truncated result set is not a page of data-entry errors.

**The benchmark is not a BLS SOII estimate.** It is the median TCR of the other ITA filers in the same NAICS prefix and year, computed from the same file. ITA filers are a size- and industry-selected subset of US workplaces, so the benchmark is not generalizable to the whole worker population. For generalizable national estimates, use the BLS Survey of Occupational Injuries and Illnesses. This ships on every row as `industry_benchmark_note`.

**`stopped_filing` is not evidence of closure.** It means an `establishment_id` present in the earlier year is absent from the later one. That can mean closure — or falling below the reporting threshold, or an acquisition, or a changed identifier, or simply not filing. This ships on every delta row as `stopped_filing_note`.

**A run that matches nothing succeeds with zero rows.** That is the answer, and it costs you nothing beyond the tiny actor start. A run that *cannot* answer — OSHA unreachable, a file that failed the live drift gate, a year OSHA does not publish, an input that cannot be interpreted — **fails loudly and bills nothing**.

**Not in v1: case-detail (Form 300/301) data.** OSHA also publishes per-case detail for CY2023 onward, including AI-assigned OIICS injury codes for 2023–2024 and free-text incident narratives. It is a much larger and structurally different product (the CY2025 case file alone is a 422 MB uncompressed CSV with 39 columns, and OIICS codes are present on 2023–2024 but not yet on 2025). It is deliberately not merged in here rather than half-supported. `establishment_id` on every row is the join key when it ships.

***

### What was measured in the source, and why the code looks the way it does

Every item below was measured live on 2026-09-03 against the published files and is pinned by an offline fixture.

- **`no_injuries_illnesses` is coded the opposite way to its name.** Code `1` means the establishment **did** record cases; code `2` means it recorded **none**. Measured across CY2024: code 1 → 227,666 rows with cases and 13 without; code 2 → 170,941 rows with zero cases and **zero** with cases. A naive `Boolean()` or `=== 1` reading inverts the meaning on 398,607 of 398,620 rows. A live gate asserts this mapping on every run, so an OSHA recoding fails the run rather than silently inverting every answer.
- **The file URLs change naming convention almost every year** — `ITA_300A_Summary_Data_2024_through_12-31-2025.zip`, `ITA-data-cy2022.zip`, `ITA-Data-CY-2020.zip`, `ITA%20Data%20CY%202019.zip` — across two directories, and the current year is published as a **bare CSV, not a zip**. URLs are scraped from OSHA's data page on every run and never guessed.
- **The CSV entry name inside each zip also differs every year** (`ITA Data CY 2016.csv`, `CY 2022.csv`, `ITA_300A_Summary_Data_2024_through_12-31-2025_v2.csv`), so the entry is selected by extension.
- **Column order differs between years and CY2024 added a 32nd column** (`naics_year`). Columns are addressed by name; a positional parser reads the wrong column for at least two years.
- **CY2022 carries a UTF-8 BOM**; the other years do not.
- **CY2022 carries 24 mixed-case state spellings** (`Fl` on 50 rows, `Co`, `ca`, `Tx`, `ny`, …) across 85 distinct values. A case-sensitive state filter silently drops those establishments.
- **Three NAICS vintages coexist in one file** — CY2024 holds 2022 (222,316 rows), 2012 (164,137), 2017 (11,964) codes plus a `"0"` sentinel. Industry filtering is by prefix, and the `"0"` sentinel is never published as a year.
- **`size` is not the documented three-value code.** CY2024 carries five values and **168,310 of 398,620 rows read `21`**; the same code covers 227 rows in CY2022, and the employee bands behind codes 2 and 3 differ between the two years. No label is invented — the raw code ships with a measured peer-median employee count.
- **CY2016 publishes no EIN at all** (blank on all 214,978 rows); ~11% of CY2024 rows are blank and 84 CY2022 values are non-numeric. Blank is `null`, never `0`.
- **OSHA revises published years in place** — CY2016 through CY2020 all carry a 2025-11-25 `Last-Modified`. Every row publishes the file's own `Last-Modified` as its vintage.
- **`www.osha.gov` answers HTTP 403 with an HTML body to a non-browser User-Agent on every file path**, including paths that do not exist, so a bot-gate 403 is indistinguishable from a deleted file. It also 403s `HEAD` on files it serves at 200 to `GET`.

***

### Cost — read this first

**$8.00 per 1,000 result rows** ($0.008 per row), on Apify's pay-per-result model, with graduated discounts on the paid plans (Bronze −20%, Silver −30%, Gold −45%, Platinum −60%, Diamond −70%). One emitted row = one billed result. There is no per-run fee beyond Apify's tiny actor-start event.

Measured row counts so you can price a run before you make it (CY2024 file, 398,620 establishments nationally):

| Scope | Rows matched | Cost at list price |
|---|---|---|
| Colorado, all industries | 7,243 | $57.94 uncapped — **use `maxResults`** |
| Colorado, `maxResults: 500` (the default) | 500 | **$4.00** |
| Colorado, construction only (`naicsPrefixes: ["23"]`) | ~1,000 | ~$8.00 |
| Colorado, one 4-digit industry | 200–400 | $1.60–$3.20 |
| One employer by `nameContains` in one state | 1–60 | under $0.50 |

`maxResults` defaults to **500**, so a default run costs at most **$4.00**. Every emitted row carries `matched_rows_total` and `results_truncated`, so you always know whether the cap bit.

A run that fails — bad input, OSHA unreachable, drift gate tripped — emits nothing and bills nothing.

***

### Use as an MCP tool

This actor is callable by AI agents (Claude, Cursor, Windsurf, any MCP client) through Apify's hosted MCP server. Billing is unchanged when it is called as a tool, and a run that cannot answer fails without billing.

**Endpoint:** `https://mcp.apify.com/?actors=malonestar/osha-ita-injury-illness-establishment-monitor`

**Claude Desktop / Claude Code / Cursor config:**

```json
{
  "mcpServers": {
    "osha-injury-data": {
      "url": "https://mcp.apify.com/?actors=malonestar/osha-ita-injury-illness-establishment-monitor",
      "headers": { "Authorization": "Bearer YOUR_APIFY_TOKEN" }
    }
  }
}
```

**A worked agent prompt:**

> "Using the OSHA ITA tool, pull every Colorado construction establishment (NAICS 23) that filed a CY2024 Form 300A and recorded at least one case. Rank them by how far their Total Case Rate sits above their own industry's median, and tell me which ones have a `rate_basis` other than `computed` so I know which rankings to distrust."

**Chaining with the rest of the fleet** — an agent can load several of these at once:

```
https://mcp.apify.com/?actors=malonestar/osha-ita-injury-illness-establishment-monitor,malonestar/dol-enforcement-rollup,malonestar/warn-layoff-aggregator
```

That combination answers a whole employer-risk question in one agent turn: OSHA-reported injury rates, DOL wage-and-hour enforcement history, and WARN-Act layoff notices for the same employer.

### Related actors

- [dol-enforcement-rollup](https://apify.com/malonestar/dol-enforcement-rollup) — US Department of Labor Wage & Hour enforcement cases, penalties and back wages by employer. The enforcement half of the same employer-risk picture.
- [warn-layoff-aggregator](https://apify.com/malonestar/warn-layoff-aggregator) — state WARN-Act mass-layoff and closure notices. Useful next to `filing_status: stopped_filing`, which on its own is not evidence of closure.
- [epa-tri-facility-release-rollup](https://apify.com/malonestar/epa-tri-facility-release-rollup) — EPA Toxics Release Inventory chemical releases per facility, for the environmental side of the same industrial sites.
- [epa-rcra-hazwaste-generator-rollup](https://apify.com/malonestar/epa-rcra-hazwaste-generator-rollup) — RCRA hazardous-waste generation by handler.
- [license-verifier](https://apify.com/malonestar/license-verifier) — professional and occupational licence verification across 19 boards in 9 states.

### FAQ

**Where does this data come from?**
OSHA's Injury Tracking Application, published at <https://www.osha.gov/Establishment-Specific-Injury-and-Illness-Data>. It is public, keyless bulk data. This actor reads OSHA's own files directly; it does not scrape a search interface.

**How is the injury rate calculated?**
`(number of cases x 200,000) / employee hours worked`, which is OSHA's published formula. TCR uses Form 300A columns H + I + J; DART uses H + I. `rate_formula` ships on every row.

**Why is `total_case_rate` null on some rows?**
Because it could not be computed. Check `rate_basis`: the establishment reported zero hours worked, reported no hours at all, or its case counts were incomplete. A null rate is never presented as a zero rate.

**Does a high rate mean an employer is dangerous?**
No, and OSHA says so explicitly. Rates depend on self-reported hours and counts that OSHA does not validate, and small establishments produce volatile rates. Use `industry_benchmark_peer_count`, `rate_is_implausible` and `data_quality_flags` before drawing a conclusion.

**Why is my company not in the results?**
Most likely it is not required to file. OSHA only collects Form 300A data above specific employee-count and industry thresholds. Absence here is not evidence of no injuries.

**How current is the data?**
Employers file by March 2 for the prior calendar year, and OSHA publishes shortly after. The actor reads the published-year list live on every run and reports each file's `Last-Modified` as `data_vintage_last_modified`. OSHA also revises historical years in place, which is why the vintage ships on every row.

**Can I get individual injury case details, not just the annual summary?**
Not in v1 — see the limitations section. `establishment_id` is the documented join key for when it ships.

**How do I keep the cost down?**
Filter. `naicsPrefixes`, `nameContains` and `minEmployees` all narrow the result set before anything is billed, and `maxResults` is a hard cap enforced by a single audited code path with a pre-push tripwire.

# Actor input Schema

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

REQUIRED. Two-letter state codes to return establishments for, e.g. \["CO"] or \["TX","NM"]. OSHA publishes roughly 400,000 establishment records per calendar year, so an unscoped national run is rejected before it starts rather than billed. Matching is case-insensitive on purpose: the CY2022 file carries 24 mixed-case spellings such as "Fl", "ca" and "Co", and a case-sensitive filter silently drops those establishments. OSHA also publishes AS, GU, MP, PR, VI and the military codes AA, AE and AP.

## `years` (type: `array`):

REQUIRED. Calendar years of Form 300A data, e.g. \["2024"]. OSHA collects one year at a time and publishes each year as a separate 12-85 MB download, so at most 3 years per run. Summary data exists from 2016 onward; the exact list of published years is read live from OSHA's own data page on every run and an unpublished year fails loudly with the list of years that do exist. In "delta" mode pass exactly one year — the prior year is fetched automatically.

## `mode` (type: `string`):

"establishments" returns one row per establishment per calendar year, with the OSHA-formula Total Case Rate and DART rate plus a peer-industry benchmark. "delta" compares the requested year against the year before it and returns one row per establishment with the rate change and a filing\_status of continuing / new\_filer / stopped\_filing. Omitted = "establishments".

## `naicsPrefixes` (type: `array`):

Optional. Two- to six-digit NAICS prefixes, e.g. \["23"] for construction, \["2382"] for building-equipment contractors, \["238310"] for drywall contractors, \["622"] for hospitals. Matching is by PREFIX rather than exact code because OSHA stores three NAICS vintages side by side in the same file (2012, 2017 and 2022 codes all appear in CY2024, plus a "0" vintage sentinel), so an exact-code filter against one vintage's code list silently loses whole industries. Leave empty for all industries.

## `nameContains` (type: `string`):

Optional. Case-insensitive substring matched against BOTH establishment\_name and company\_name, e.g. "Kroger" or "Post Acute". Useful for tracking one employer's whole establishment footprint across a state. Leave blank for all names.

## `minEmployees` (type: `integer`):

Optional. Keep only establishments reporting at least this many annual average employees. An establishment that reports no employee count is excluded when this is above 0, because an unreported count is not a small count. Note OSHA does not validate this figure — the CY2024 file contains a single establishment reporting 41,092,597 employees, which is flagged rather than corrected. Omitted or 0 = no employee filter.

## `onlyWithRecordableCases` (type: `boolean`):

When true, keep only establishments that reported at least one recordable case or death. Roughly 43% of CY2024 filers reported zero cases, and a zero-case filing is a real, meaningful answer, so this is off by default. Turning it on does not change any rate — it only narrows which establishments are returned and therefore what you are billed for.

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

Hard cap on emitted rows — each row is one billed result. Enforced by a single audited code path for both modes plus a pre-push tripwire. When the cap bites, rows are ordered trustworthy-rate-first (an establishment reporting 547 employees against 6,571 hours produces an arithmetically valid but meaningless rate, and those sort below the sound ones rather than dominating the top of your results), and every emitted row carries results\_truncated=true and matched\_rows\_total so a capped answer is never mistaken for a complete one. Omitted = 500.

## Actor input object example

```json
{
  "states": [
    "CO"
  ],
  "years": [
    "2024"
  ],
  "mode": "establishments",
  "onlyWithRecordableCases": false,
  "maxResults": 500
}
```

# Actor output Schema

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

The default dataset.

# 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": [
        "CO"
    ],
    "years": [
        "2024"
    ],
    "mode": "establishments",
    "maxResults": 500
};

// Run the Actor and wait for it to finish
const run = await client.actor("malonestar/osha-ita-injury-illness-establishment-monitor").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": ["CO"],
    "years": ["2024"],
    "mode": "establishments",
    "maxResults": 500,
}

# Run the Actor and wait for it to finish
run = client.actor("malonestar/osha-ita-injury-illness-establishment-monitor").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": [
    "CO"
  ],
  "years": [
    "2024"
  ],
  "mode": "establishments",
  "maxResults": 500
}' |
apify call malonestar/osha-ita-injury-illness-establishment-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,malonestar/osha-ita-injury-illness-establishment-monitor"
        }
    }
}

```

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/oc6lP1bwg5YojAcB6/builds/49A9POOlI7RcB3xzb/openapi.json
