# FDA Supplier & Competitor Risk Monitor (`barking_wisdom/fda-supplier-competitor-risk-monitor`) Actor

Monitors public FDA/openFDA enforcement records for watched suppliers, competitors, brands, products and risk terms.

- **URL**: https://apify.com/barking\_wisdom/fda-supplier-competitor-risk-monitor.md
- **Developed by:** [Влад](https://apify.com/barking_wisdom) (community)
- **Categories:** Business, Lead generation
- **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/platform/actors/running/actors-in-store#pay-per-usage

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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

## FDA Supplier & Competitor Risk Monitor

Monitor public FDA/openFDA enforcement records for suppliers, competitors,
brands, products and risk terms that matter to your compliance or market
intelligence workflow.

This Actor is designed for regulatory consultants, food safety teams, medical
device teams, pharma operations, supplier-risk analysts and competitive
intelligence teams that need a compact feed of relevant FDA enforcement events
instead of a broad raw export.

### What It Does

- Fetches public enforcement records from official openFDA food, drug and device
  enforcement APIs.
- Matches records against a watch list of suppliers, competitors, brands,
  products or risk terms.
- Scores each matched event using FDA classification, status, distribution
  pattern and serious-risk keywords.
- Emits only matched, data-minimized regulatory event rows.
- Supports scheduled monitoring with `emitOnlyNew`.
- Supports pay-per-event monetization with `matched_regulatory_event`.

### Sources

The Actor uses official public openFDA endpoints:

- `https://api.fda.gov/food/enforcement.json`
- `https://api.fda.gov/drug/enforcement.json`
- `https://api.fda.gov/device/enforcement.json`

No login, proxy, browser automation, CAPTCHA bypass or private data source is
used.

### Example Input

```json
{
  "watchList": [
    "salmonella",
    {
      "name": "Example Supplier",
      "aliases": ["example brand"]
    }
  ],
  "sourceTypes": ["food", "drug", "device"],
  "classifications": ["Class I", "Class II"],
  "statuses": ["Ongoing"],
  "riskKeywords": ["sterility", "undeclared allergen"],
  "lookbackDays": 365,
  "maxRecordsPerSource": 100,
  "maxResults": 50,
  "minRiskScore": 20,
  "emitOnlyNew": false
}
````

### Output Fields

Each dataset row includes:

- `eventId`
- `eventType`
- `sourceType`
- `riskScore`
- `riskLevel`
- `matchedWatchTerms`
- `matchedFields`
- `riskSignals`
- `classification`
- `status`
- `recallNumber`
- `reportDate`
- `recallInitiationDate`
- `recallingFirm`
- `productDescription`
- `reasonForRecall`
- `distributionPattern`
- `country`
- `state`
- `sourceUrl`
- `summary`
- `observedAt`

The output avoids personal data and keeps the fields focused on business,
product, recall and source attribution.

### Risk Scoring

The score is deterministic and explainable:

- Class I, ongoing events score higher.
- Nationwide distribution increases the score.
- Serious terms such as death, serious injury, sterility, salmonella, listeria,
  e. coli, undeclared allergen, contamination and foreign material increase the
  score.
- Matches in `recalling_firm`, product fields or openFDA manufacturer/brand
  fields increase confidence.

Risk levels:

- `critical`: 80-100
- `high`: 60-79
- `medium`: 35-59
- `low`: 1-34

### Local Development

```powershell
npm install
npm run check
'{"watchList":["unapproved colors"],"sourceTypes":["food"],"lookbackDays":3650,"maxRecordsPerSource":1,"maxResults":1,"minRiskScore":1,"emitOnlyNew":false}' | C:\Users\User\.apify\bin\apify.exe run --purge --input-file -
```

The source adapter first tries the openFDA query API with native Node fetch. In
this Windows development environment, openFDA can reject Node clients with HTTP
403 even when the same public URL works through .NET/PowerShell. For that local
case, the Actor falls back to PowerShell's `Invoke-RestMethod` with the URL
passed through an environment variable. On non-Windows runtimes, it falls back
to a Playwright browser-backed fetch for the same official API query. ZIP
downloads from `download.open.fda.gov` are retained as an opt-in emergency
fallback through `ALLOW_OPENFDA_DOWNLOAD_FALLBACK=1`.

### Monetization Hypothesis

Suggested Apify Store model:

- Pricing model: pay per event
- Event name: `matched_regulatory_event`
- Initial test price: `$0.10` per matched regulatory event

The final price should be set only after cloud cost measurement and Store
comparison. The Actor already calls:

```js
await Actor.charge({ eventName: 'matched_regulatory_event' });
```

before writing monetized rows when monetization is enabled.

### Compliance Notes

This Actor is for B2B compliance monitoring, supplier risk review, market
intelligence and internal workflow triage.

It is not medical advice, legal advice, a patient-facing recall alert system or
a substitute for official FDA communications. Users should verify important
events against the FDA/openFDA source records and their own regulatory process.

This Actor is not affiliated with or endorsed by the FDA.

# Actor input Schema

## `watchList` (type: `array`):

Suppliers, competitors, brands, products or risk terms to match against public FDA/openFDA enforcement records. Entries can be strings or objects with name and aliases.

## `sourceTypes` (type: `array`):

openFDA enforcement datasets to monitor.

## `classifications` (type: `array`):

Optional recall classifications to keep. Leave empty to include all classes.

## `statuses` (type: `array`):

Optional FDA status values to keep. Leave empty to include all statuses.

## `riskKeywords` (type: `array`):

Additional risk keywords that increase scoring when found in the recall reason or product fields.

## `lookbackDays` (type: `integer`):

How many days of report\_date history to fetch from openFDA.

## `maxRecordsPerSource` (type: `integer`):

Maximum public openFDA records to fetch from each selected source type before local matching.

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

Maximum matched regulatory events to save to the dataset.

## `minRiskScore` (type: `integer`):

Only events with this risk score or higher are emitted.

## `emitOnlyNew` (type: `boolean`):

When true, previously emitted event IDs are skipped in scheduled runs.

## `monetizationEnabled` (type: `boolean`):

For local testing this can stay false. In Apify cloud, the Actor enables charge calls automatically unless owner override is configured.

## Actor input object example

```json
{
  "watchList": [
    "salmonella",
    {
      "name": "Example Supplier",
      "aliases": [
        "example brand"
      ]
    }
  ],
  "sourceTypes": [
    "food",
    "drug",
    "device"
  ],
  "classifications": [
    "Class I",
    "Class II"
  ],
  "statuses": [
    "Ongoing"
  ],
  "riskKeywords": [
    "salmonella",
    "sterility",
    "undeclared allergen"
  ],
  "lookbackDays": 365,
  "maxRecordsPerSource": 100,
  "maxResults": 50,
  "minRiskScore": 20,
  "emitOnlyNew": false,
  "monetizationEnabled": false
}
```

# 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 = {
    "watchList": [
        "salmonella",
        {
            "name": "Example Supplier",
            "aliases": [
                "example brand"
            ]
        }
    ],
    "sourceTypes": [
        "food",
        "drug",
        "device"
    ],
    "classifications": [
        "Class I",
        "Class II"
    ],
    "statuses": [
        "Ongoing"
    ],
    "riskKeywords": [
        "salmonella",
        "sterility",
        "undeclared allergen"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("barking_wisdom/fda-supplier-competitor-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 = {
    "watchList": [
        "salmonella",
        {
            "name": "Example Supplier",
            "aliases": ["example brand"],
        },
    ],
    "sourceTypes": [
        "food",
        "drug",
        "device",
    ],
    "classifications": [
        "Class I",
        "Class II",
    ],
    "statuses": ["Ongoing"],
    "riskKeywords": [
        "salmonella",
        "sterility",
        "undeclared allergen",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("barking_wisdom/fda-supplier-competitor-risk-monitor").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "watchList": [
    "salmonella",
    {
      "name": "Example Supplier",
      "aliases": [
        "example brand"
      ]
    }
  ],
  "sourceTypes": [
    "food",
    "drug",
    "device"
  ],
  "classifications": [
    "Class I",
    "Class II"
  ],
  "statuses": [
    "Ongoing"
  ],
  "riskKeywords": [
    "salmonella",
    "sterility",
    "undeclared allergen"
  ]
}' |
apify call barking_wisdom/fda-supplier-competitor-risk-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=barking_wisdom/fda-supplier-competitor-risk-monitor",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "FDA Supplier & Competitor Risk Monitor",
        "description": "Monitors public FDA/openFDA enforcement records for watched suppliers, competitors, brands, products and risk terms.",
        "version": "0.1",
        "x-build-id": "s8ofYBSff7TjB561E"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/barking_wisdom~fda-supplier-competitor-risk-monitor/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-barking_wisdom-fda-supplier-competitor-risk-monitor",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/barking_wisdom~fda-supplier-competitor-risk-monitor/runs": {
            "post": {
                "operationId": "runs-sync-barking_wisdom-fda-supplier-competitor-risk-monitor",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/barking_wisdom~fda-supplier-competitor-risk-monitor/run-sync": {
            "post": {
                "operationId": "run-sync-barking_wisdom-fda-supplier-competitor-risk-monitor",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "watchList"
                ],
                "properties": {
                    "watchList": {
                        "title": "Watch list",
                        "type": "array",
                        "description": "Suppliers, competitors, brands, products or risk terms to match against public FDA/openFDA enforcement records. Entries can be strings or objects with name and aliases.",
                        "default": [
                            "salmonella",
                            {
                                "name": "sterility risk",
                                "aliases": [
                                    "sterility",
                                    "sterile"
                                ]
                            }
                        ]
                    },
                    "sourceTypes": {
                        "title": "FDA source types",
                        "type": "array",
                        "description": "openFDA enforcement datasets to monitor.",
                        "default": [
                            "food",
                            "drug",
                            "device"
                        ]
                    },
                    "classifications": {
                        "title": "FDA recall classifications",
                        "type": "array",
                        "description": "Optional recall classifications to keep. Leave empty to include all classes.",
                        "default": []
                    },
                    "statuses": {
                        "title": "FDA status filter",
                        "type": "array",
                        "description": "Optional FDA status values to keep. Leave empty to include all statuses.",
                        "default": []
                    },
                    "riskKeywords": {
                        "title": "Extra risk keywords",
                        "type": "array",
                        "description": "Additional risk keywords that increase scoring when found in the recall reason or product fields.",
                        "default": []
                    },
                    "lookbackDays": {
                        "title": "Lookback days",
                        "minimum": 1,
                        "maximum": 3650,
                        "type": "integer",
                        "description": "How many days of report_date history to fetch from openFDA.",
                        "default": 365
                    },
                    "maxRecordsPerSource": {
                        "title": "Max records per source",
                        "minimum": 1,
                        "maximum": 1000,
                        "type": "integer",
                        "description": "Maximum public openFDA records to fetch from each selected source type before local matching.",
                        "default": 100
                    },
                    "maxResults": {
                        "title": "Max matched events",
                        "minimum": 1,
                        "maximum": 1000,
                        "type": "integer",
                        "description": "Maximum matched regulatory events to save to the dataset.",
                        "default": 50
                    },
                    "minRiskScore": {
                        "title": "Minimum risk score",
                        "minimum": 1,
                        "maximum": 100,
                        "type": "integer",
                        "description": "Only events with this risk score or higher are emitted.",
                        "default": 20
                    },
                    "emitOnlyNew": {
                        "title": "Emit only new events",
                        "type": "boolean",
                        "description": "When true, previously emitted event IDs are skipped in scheduled runs.",
                        "default": false
                    },
                    "monetizationEnabled": {
                        "title": "Enable pay-per-event charge calls",
                        "type": "boolean",
                        "description": "For local testing this can stay false. In Apify cloud, the Actor enables charge calls automatically unless owner override is configured.",
                        "default": false
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
