# OSHA 300 log (https://developers.asip.io/docs/api-reference/osha-300-log)

Recordable cases on the OSHA 300 log at your establishments, with the case number and the reported day counts.

> **Status: Available on request.** API keys, the read-only Data API, the MCP server (with an API key) and signed webhooks are live on app.asip.io. Developer access is off by default for every company: ask ASIP to enable it for yours (https://developers.asip.io/docs/how-to-get-access). One-click OAuth sign-in for AI connectors (claude.ai, ChatGPT, Copilot) is not available yet; use an API key. The changelog at https://developers.asip.io/docs/changelog says when each part becomes available.

## OSHA 300 log

`GET https://app.asip.io/api/v1/data/osha-300-log`

Recordable cases on the OSHA 300 log at your establishments, with the case number and the reported day counts. A privacy case always reads "Privacy Case" in place of the name (29 CFR 1904.29(b)(9)); the confidential identity list is never returned. employeeName is null with a stated employeeNameBasis whenever a name is not placed. Ordered by last modification (updatedAt, then id), oldest first. Oversight roles only: other callers receive 403 `restricted`. MCP query id: `query://asip/osha_300_log`.

**Query parameters**

| Name | Type | Required | Description |
|---|---|---|---|
| `cursor` | string | no | Opaque cursor: pass back `pagination.endCursor` from the previous page unchanged. |
| `limit` | integer (1–200) | no | Page size, 1–200. Default 50. |
| `updatedSince` | string (date-time) | no | Only records whose ordering timestamp is at or after this ISO 8601 date-time. |
| `stationId` | string | no | Restrict to one station in your scope (an id from /api/v1/data/stations). |

**Responses**

| Status | Meaning |
|---|---|
| 200 | One page of records. |
| 400 | A parameter is malformed (`bad_input`). |
| 401 | No valid API key (`unauthenticated`). Only an `asip_pk_` API key is accepted; web sign-in and ASIP Go tokens are refused. |
| 403 | Not available to your role (`restricted`/`forbidden`), or the API key lacks this query's scope (`insufficient_scope`). |
| 404 | Module not enabled, or station not in your scope (`module_disabled`/`not_found`). |
| 429 | Rate limited; see Retry-After. |

**Record fields** (`Osha300LogEntry`)

| Field | Type | Description |
|---|---|---|
| `id` | string | Stable ASIP record id. |
| `module` | string | The ASIP module that owns the record (a module key, or "platform"). |
| `url` | string | Deep link to the record in the ASIP app. Requires the viewer to sign in. |
| `caseNumber` | string or null | The OSHA case number (column A). |
| `stationId` | string | The establishment (station). |
| `departmentId` | string or null |  |
| `coveredYear` | integer |  |
| `employeeName` | string or null | Column (B). "Privacy Case" for a privacy case (29 CFR 1904.29(b)(9)); null whenever a name is not placed — employeeNameBasis says why. An API key or connected app never places names. |
| `employeeNameBasis` | `"privacy_case"` / `"source_injured_person"` / `"capability_not_held"` / `"no_source_report"` / `"no_identified_person"` / `"ambiguous_identified_person"` / `"name_not_recorded"` / `"source_unavailable"` |  |
| `isPrivacyCase` | boolean |  |
| `description` | string or null |  |
| `outcomeColumn` | string or null | Columns (G)–(J): the most serious outcome. |
| `caseTypeColumn` | string or null | Column (M): injury or illness type. |
| `daysAway` | integer | Column (K), as reported (capped at 180 combined). |
| `daysRestricted` | integer | Column (L), as reported (capped at 180 combined). |
| `daysCapped` | boolean | True when the reported day counts are capped below the recorded ones. |
| `status` | string |  |
| `createdAt` | string (date-time) |  |
| `updatedAt` | string (date-time) |  |

## OSHA 300 log — change feed

`GET https://app.asip.io/api/v1/data/osha-300-log/feed`

Recordable cases on the OSHA 300 log at your establishments, with the case number and the reported day counts. A privacy case always reads "Privacy Case" in place of the name (29 CFR 1904.29(b)(9)); the confidential identity list is never returned. employeeName is null with a stated employeeNameBasis whenever a name is not placed. Ordered by last modification (updatedAt, then id), oldest first. Oversight roles only: other callers receive 403 `restricted`. The feed stops 30 seconds behind the current time, so a record appears on it about 30 seconds after it is written; this keeps a slow write from being skipped. MCP query id: `query://asip/osha_300_log`.

**Query parameters**

| Name | Type | Required | Description |
|---|---|---|---|
| `cursor` | string | no | Opaque cursor: pass back `pagination.endCursor` from the previous page unchanged. |
| `limit` | integer (1–200) | no | Page size, 1–200. Default 50. |
| `updatedSince` | string (date-time) | no | Only records whose ordering timestamp is at or after this ISO 8601 date-time. |

**Responses**

| Status | Meaning |
|---|---|
| 200 | One page of records. |
| 400 | A parameter is malformed (`bad_input`). |
| 401 | No valid API key (`unauthenticated`). Only an `asip_pk_` API key is accepted; web sign-in and ASIP Go tokens are refused. |
| 403 | Not available to your role (`restricted`/`forbidden`), or the API key lacks this query's scope (`insufficient_scope`). |
| 404 | Module not enabled, or station not in your scope (`module_disabled`/`not_found`). |
| 429 | Rate limited; see Retry-After. |
