# FDA Warning Letter Monitor - Supplier & Closeout Changes

Monitor FDA warning letters and response or closeout changes for supplier review. Bounded public windows, literal matches and saved comparisons. No compliance verdicts or letter-body scraping.

Canonical product page: https://mayd-it.com/data-tools/actors/fda-warning-letter-monitor/
Public Actor: https://apify.com/maydit/fda-warning-letter-monitor

## Example input

```json
{
  "sortBy": "postedDate",
  "maxSourceRecords": 25,
  "maxResults": 5
}
```

## Full guide

![FDA supplier and follow-up monitoring](https://api.apify.com/v2/key-value-stores/cCyrofyNNh9lwffXB/records/fda-warning-letter-monitor-663611836d73.png?signature=lq9S0ireTWbTMvF8hnWb)

# FDA Warning Letter Monitor

Turn FDA's warning-letter table into a repeatable supplier-review feed. Collect company names, published subjects, dates and original document links, then compare later observations to find new records and changed response or closeout links.

**Coverage:** one selected window of up to 100 FDA table records per run. Filters apply inside that window. This monitors published records; it does not decide whether a supplier is compliant, whether allegations are proven, or whether an issue remains unresolved.

## Start with five recent letters

```json
{
  "sortBy": "postedDate",
  "maxSourceRecords": 25,
  "maxResults": 5
}
```

Run the Actor, then open **Saved observations**, **Run report** or **CSV export** in Output. No API key, login or proxy setup is required. FDA currently requests a 30-second crawl delay; the Actor honors it before its single table request. Allow at least 90 seconds of platform timeout. Typical successful local checks take about 32 seconds; availability can vary.

**Cost:** $0.003 per saved letter observation at the FREE/BRONZE base rate, plus $0.00005 per Actor start. Five rows cost $0.01505 in Actor events. SILVER and GOLD+ rates are lower; check the Store's current Pricing tab for your plan. An unchanged observation is still a saved, charged row unless `onlyChanges` is enabled. Errors and skipped unchanged rows are not paid result rows. Platform charges, where applicable, are separate.

## What you get

- A spreadsheet-ready row per warning letter, with company, issuing office, subject, posted date and issue date.
- Distinct URLs and table-posted dates for a linked response and a linked closeout.
- Literal supplier-name or topic matches, with the matching field and a short excerpt.
- Saved comparisons: `new`, `changed` or `unchanged`, changed fields, prior values and prior observation time.
- A readable `RUN_REPORT` and machine-readable `SUMMARY` showing source bounds, filtering, saved rows and any errors or limits.

For example, this abbreviated record reflects an official closeout-window observation retained during development:

```json
{
  "companyName": "Talla Imports, LLC",
  "marcsCmsId": "699044",
  "postedDate": "2025-02-04",
  "letterIssueDate": "2025-01-13",
  "subject": "Foreign Supplier Verification Program (FSVP)",
  "hasPostedResponse": false,
  "hasPostedCloseout": true,
  "closeoutPostedDate": "2026-10-05",
  "comparisonStatus": "not_requested"
}
```

The complete row also includes the original warning and follow-up links, source request, observation time and comparison fields. `closeoutPostedDate` is the date shown in FDA's table; it is not an inferred date from the document URL or a current compliance status.

## Three ready-to-use workflows

### 1. Recently posted warning letters

Use the quick-start input above. It reads the first 25 records in descending posted-date order and saves at most five. Default `{}` uses the same window and saves up to ten.

### 2. Supplier-verification closeout updates

```json
{
  "sortBy": "closeoutPostedDate",
  "maxSourceRecords": 25,
  "keywords": ["Foreign Supplier Verification"],
  "maxResults": 5
}
```

This looks for FSVP subjects within the 25 most recent closeout-link dates. It returns the underlying warning-letter records and their follow-up links. Dated entries may be followed by records with no linked closeout if the requested window extends beyond them.

### 3. A saved comparison for the recent window

```json
{
  "sortBy": "postedDate",
  "maxSourceRecords": 25,
  "maxResults": 100,
  "comparePrevious": true,
  "onlyChanges": false,
  "snapshotName": "fda-latest-window"
}
```

The first run establishes history after each row is confirmed saved. Run the same input again to inspect prior values. Set `onlyChanges` to `true` to save only new or changed observations; a fully unchanged run correctly returns zero rows.

For a supplier watchlist, add `companyNames`, for example `["Eurofins", "Hanlim"]`. Matching is a case-insensitive substring of the published company name, without entity resolution. A supplier outside the selected window will not be checked. The Actor does not search the complete archive for each supplier.

## Input reference

| Field | Meaning |
| --- | --- |
| `sortBy` | `postedDate` (default), `letterIssueDate`, `responsePostedDate` or `closeoutPostedDate`; descending publisher date. |
| `maxSourceRecords` | First 1–100 source records, default 25. One request; no pagination or full-archive claim. |
| `companyNames` | Up to 30 literal company-name substrings. Any name can match. Empty means no name filter. |
| `keywords` | Up to 30 literal terms across company, subject and issuing office. Any term can match. If names are supplied too, both filter groups must match. |
| `maxResults` | Confirmed saved rows, default 10, maximum 1,000. Cannot exceed the matching source window in practice. |
| `comparePrevious` / `onlyChanges` | Enable comparisons; the latter also skips unchanged rows. Both default false. |
| `snapshotName` | Comparison namespace, default `default`. Sort, window size and normalized filters also scope history. |
| `stateStoreName` | Dedicated named storage, default `maydit-fda-warning-letter-history`; accessed only for comparisons. |
| `maxRunSeconds` | Own budget, default 240, range 30–900, also bounded by platform timeout minus 25 seconds. A 30-second budget can expire during FDA's crawl delay. |

## Comparison and coverage rules

The stable row identity is `letterUrl`. The MARCS-CMS identifier is extracted only when it is present in that official URL; it is otherwise null. Comparison covers the company, dates, issuing office, subject and linked follow-up fields. Observation timestamps and match excerpts are excluded from change detection.

**`new` means first saved observation in this comparison scope, not first FDA publication.** FDA can return different records tied on a date at the source-window boundary, even when a secondary sort is requested. A repeat can therefore discover older, previously unseen records without a new FDA publication. Use `postedDate` and `letterIssueDate` for publisher chronology. Exact letter-URL watchlists are not supported.

History advances only for confirmed saved rows. Existing observations outside a later window remain stored. Nothing leaving a window is treated as a removal, withdrawal, resolution or clean bill of health. Use **one sequential writer per identical history scope**. The Actor rereads history before committing and refuses a known conflict, but this is not an atomic multi-writer store. Incompatible history is left untouched; choose a new namespace.

`sourceWindowHasMore` indicates records beyond the selected window. `sourceWindowComplete` means the requested window was successfully fetched and validated, not that the archive was complete. `stoppedOnMaxResults` is a deliberate output cap; `status: "ok"` can accompany that cap. Time, spending, history or source failures are separately marked as incomplete. Always inspect the report before treating an empty dataset as meaningful.

## Source context and limits

The source is [FDA's public Warning Letters table](https://www.fda.gov/inspections-compliance-enforcement-and-criminal-investigations/compliance-actions-and-activities/warning-letters), including the same public JSON table transport used by that page. This transport is not advertised as a versioned public API and may change. The Actor validates the entire returned window before saving rows and stops on inconsistent counts, links, dates or ordering.

FDA identifies warning letters as a resource for [firm and supplier evaluation under FSMA](https://www.fda.gov/food/food-safety-modernization-act-fsma/firmsupplier-evaluation-resources-fsma-rules). FDA also explains the distinction between [warning and closeout letters](https://www.fda.gov/inspections-compliance-enforcement-and-criminal-investigations/warning-letters/about-warning-and-close-out-letters). Subsequent interactions may change the regulatory status of matters in a letter. A missing published response does not show that a firm failed to respond. A closeout is a specific published FDA follow-up, not a universal supplier certification.

The Actor does not fetch letter bodies, attachments, contact details, inspection reports, import-alert lists or response/closeout document text. Source updates and posting can be delayed. This is published-record monitoring for human review, not legal or regulatory advice.

## Troubleshooting and support

- **No rows:** check the selected window, literal filters and `unchangedSkipped` before widening the source window.
- **Time limit:** use at least a 90-second platform timeout and keep enough time for FDA's crawl delay. Short budgets do not skip that delay.
- **403, 429, invalid source or robots refusal:** the Actor stops without retries or bypass. Retry later after reviewing `SUMMARY`; the failed request produces no paid result rows.
- **History conflict:** schedule sequential runs or assign a separate store/namespace. Do not reset another workflow's history.

For support, open an issue on this Actor's Store page with the run URL and a redacted input. Do not include credentials or private supplier notes.
