# NHTSA TSB & Manufacturer Communication Monitor (`nintendo424/nhtsa-manufacturer-communication-risk-monitor`) Actor

Monitor official NHTSA TSB and manufacturer communications for new or revised technical service bulletins, vehicle service campaigns, and warranty/service updates. Get review-ready signals for fleet risk monitoring with transparent concern tags and priority rationale.

- **URL**: https://apify.com/nintendo424/nhtsa-manufacturer-communication-risk-monitor.md
- **Developed by:** [Blake Panter](https://apify.com/nintendo424) (community)
- **Categories:** Automation, Business, Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

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

## 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

## NHTSA TSB & Manufacturer Communication Monitor

Monitor official **NHTSA TSB data and manufacturer communications** for new or revised technical service bulletins, vehicle service campaigns, and warranty/service updates. Turn NHTSA's bulk archive into review-ready signals for fleet risk monitoring without repeatedly downloading, parsing, filtering, and comparing the source yourself.

Each paid result represents one matching document + make + model + model-year identity. It includes the verbatim NHTSA summary, change type, transparent concern tags and priority rationale, official source links, and a stable deduplication key.

### Built for

- fleet operations and fleet risk monitoring teams prioritizing service-related document review
- warranty, service, and dealership teams tracking manufacturer guidance
- automotive compliance and product-quality analysts reviewing new or revised communications
- data teams feeding traceable NHTSA document changes into internal workflows

### Why this instead of a raw TSB scraper

- **Monitor changes, not just rows:** persistent snapshots identify `initial`, `new`, and `revised` communications and suppress unchanged results by default.
- **Focus the review queue:** filter by make, model, model year, keyword, concern category, and minimum priority before results are emitted.
- **See why an item was ranked:** every result carries exact evidence terms and deterministic priority rationale rather than an unexplained score.
- **Keep results traceable:** retain the verbatim agency summary, official archive and dataset URLs, detection time, and stable `dedupeKey`.
- **Process large source files predictably:** the Actor streams and bounds the official ZIP/CSV workflow instead of loading the full archive into memory.

This is **not** a raw TSB export, defect detector, recall predictor, or legal/safety determination. A communication can be routine service guidance. `priority` only ranks explicit words in NHTSA's concise summary so a human can decide what to review.

### What it emits

One paid `manufacturer-communication-signal` per matching document + make + model + model-year identity:

- `signalType`: `initial`, `new`, `revised`, or optionally `unchanged`
- NHTSA `documentId`, `make`, `model`, `modelYears`, and verbatim `summary`
- transparent `concernCategories` and exact `evidenceTerms`
- deterministic `priority` (`low`, `medium`, `high`, `critical`) and `priorityRationale`
- `changedFields` (`summary` for a revised stable identity)
- official archive and NHTSA dataset URLs, detection time, and stable `dedupeKey`

`critical` is reserved for explicit severe phrases such as “vehicle fire,” “loss of braking,” “loss of steering,” “air bag may not deploy,” or “loss of motive power.” It means “review first,” never “confirmed defect.”

### Example input

```json
{
  "makes": ["FORD"],
  "modelYears": ["2025"],
  "keywords": ["brake", "fire"],
  "concernCategories": ["braking", "fire-thermal"],
  "minimumPriority": "high",
  "includeInitial": true,
  "emitUnchanged": false,
  "maxSourceRecords": 200000,
  "maxItems": 100,
  "requestTimeoutSecs": 60,
  "baselineStoreName": "my-nhtsa-comms-baseline"
}
```

All make/model/year filters are exact and case-insensitive. Keyword filters are case-insensitive summary substrings. Multiple keywords and concern categories use OR within their group; different filter groups combine with AND.

### Delta semantics

- **initial** — matching identity first seen while the named baseline is fresh
- **new** — previously unseen identity after that baseline has been initialized
- **revised** — same stable identity but normalized summary fingerprint changed
- **unchanged** — same identity and summary fingerprint; suppressed unless `emitUnchanged` is true

`includeInitial: false` builds the baseline without charging initial records. Use a dedicated `baselineStoreName` per monitoring configuration when you want independent history. Filtering happens before baseline access and before PPE charging, so materially changing filters is best paired with a new store name.

Each snapshot and its per-record pending-delivery state are persisted **before** its PPE dataset push, and a successful push is acknowledged afterward. This provides **at-least-once delivery**, not exactly-once delivery: if the run stops after a successful push but before its acknowledgement is persisted, the next run retries that signal and can produce a duplicate. Once A is acknowledged, a later failure on B retries B without pushing A again. Consumers that maintain current state should upsert/idempotently process records by the stable `dedupeKey`; append-only consumers should use it with the signal's business fields to detect retry duplicates while still retaining genuine later revisions. Snapshots use SHA-256-derived legal KV keys with 256 two-hex partition prefixes (`record-00-…` through `record-ff-…`) rather than one oversized JSON value. If a run stops because `maxItems` or the platform event-charge limit is reached, later source rows are intentionally not consumed or baselined.

### Resource and source boundaries

Default source: [`MFR_COMMS_RECEIVED_2025-2026.zip`](https://static.nhtsa.gov/odi/ffdd/tsbs/MFR_COMMS_RECEIVED_2025-2026.zip), currently one CSV with these required columns:

`TSB/Document ID`, `Make`, `Model`, `Model Year`, `Concise Summary`

The downloader accepts HTTPS only, follows redirects, enforces a 25 MB compressed-download limit and timeout through body consumption, validates ZIP magic across arbitrary network chunks, and writes to a temporary file. `unzip -p` streams decompression through an RFC 4180 parser; neither the ~80 MB CSV text nor all records are retained. Uncompressed data is capped at 160 MB and any single CSV record at 2 MB measured in actual UTF-8 input bytes, including multiline content and record syntax. In-run duplicate tracking retains only fixed-size SHA-256 digests and is capped by `maxSourceRecords`, which also bounds consumed rows. Override `sourceUrl` only with an official archive that follows the same format.

### Concern rules

Rules are deterministic case-insensitive phrase/token matches and may assign several categories:

- `fire-thermal`: fire, thermal, overheat, smoke, burning, melting terms
- `braking`: brake/braking/ABS terms
- `steering`: steering system terms
- `airbag-restraint`: airbag, seat-belt, restraint terms
- `engine-stall-damage`: stall, motive-power loss, engine damage/failure terms
- `electrical`: short circuit, wiring, battery, charging, fuse, voltage terms
- `visibility`: windshield, camera image, wiper, defroster terms
- `software`: software, firmware, programming, calibration-update terms
- `warranty-service`: warranty/service-campaign/inspection terms (inspection alone remains `low` unless another component or severity rule also matches)
- `other`: no category rule matched

Priorities are then assigned in order: explicit severe phrase → `critical`; failure/loss/smoke/crash/injury/stall language → `high`; a non-software/non-service component category → `medium`; otherwise → `low`. The exact matched terms and rationale are included in every result.

### Local development

Requires Bun and the `unzip` executable.

```bash
bun install --frozen-lockfile
bun run test
bun run typecheck
npx --yes apify-cli validate-schema
APIFY_LOCAL_STORAGE_DIR=./storage bun run start
```

For local input, write `storage/key_value_stores/default/INPUT.json`. Reuse the same local storage and baseline name to test unchanged suppression.

### Responsible use

The archive and summaries are official public NHTSA material, but users should verify every signal against the underlying communication and current NHTSA recall/vehicle records. Text matching can miss synonyms or flag routine guidance. Do not use this output alone for safety decisions, legal claims, recall status, automated adverse action, or claims that a manufacturer concealed or confirmed a defect.

# Actor input Schema

## `sourceUrl` (type: `string`):

HTTPS URL of an NHTSA manufacturer-communications ZIP with the documented CSV columns.

## `makes` (type: `array`):

Exact, case-insensitive make filters.

## `models` (type: `array`):

Exact, case-insensitive model filters.

## `modelYears` (type: `array`):

Exact model-year filters such as 2025.

## `keywords` (type: `array`):

At least one case-insensitive substring must occur in the concise summary.

## `concernCategories` (type: `array`):

Emit records matching at least one selected transparent rule category.

## `minimumPriority` (type: `string`):

Deterministic attention threshold; not a safety or legal conclusion.

## `includeInitial` (type: `boolean`):

Emit matching records on a fresh baseline. They are still stored when disabled.

## `emitUnchanged` (type: `boolean`):

Emit unchanged matching snapshots on later runs; disabled by default.

## `maxSourceRecords` (type: `integer`):

Hard processing bound over CSV data rows.

## `maxItems` (type: `integer`):

Hard cap checked before each paid dataset push.

## `requestTimeoutSecs` (type: `integer`):

Timeout covering archive headers and body download.

## `baselineStoreName` (type: `string`):

Persistent named store shared by recurring runs.

## Actor input object example

```json
{
  "sourceUrl": "https://static.nhtsa.gov/odi/ffdd/tsbs/MFR_COMMS_RECEIVED_2025-2026.zip",
  "minimumPriority": "low",
  "includeInitial": true,
  "emitUnchanged": false,
  "maxSourceRecords": 200000,
  "maxItems": 100,
  "requestTimeoutSecs": 60,
  "baselineStoreName": "nhtsa-manufacturer-communication-risk-baseline"
}
```

# Actor output Schema

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

Dataset items emitted by this run.

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("nintendo424/nhtsa-manufacturer-communication-risk-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 = {}

# Run the Actor and wait for it to finish
run = client.actor("nintendo424/nhtsa-manufacturer-communication-risk-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 '{}' |
apify call nintendo424/nhtsa-manufacturer-communication-risk-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,nintendo424/nhtsa-manufacturer-communication-risk-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/OmPfBjjBvShIHVsfZ/builds/YFVnbGoa9ztGebINb/openapi.json
