# FDA Recall Monitor — Real-Time Slack & Telegram Alerts (`incontrovertible_gate/fda-recall-monitor`) Actor

Real-time alerts on FDA drug, food, and medical device recalls from the official openFDA API. Watch any firms or products and push notifications to Slack,
Discord, Telegram, or webhook. A modern alternative to FDAzilla, RegEd, and FDA email subscriptions — pay only $0.50 per match

- **URL**: https://apify.com/incontrovertible\_gate/fda-recall-monitor.md
- **Developed by:** [Netsrac](https://apify.com/incontrovertible_gate) (community)
- **Categories:** Automation, Integrations, Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, NaN bookmarks
- **User rating**: No ratings yet

## Pricing

from $500.00 / 1,000 result delivereds

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

## 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 Recall Monitor — Real-Time openFDA API Alerts to Slack, Discord & Telegram

**Get push notifications the moment a new FDA recall is published** — across drugs, food, and medical devices. Built directly on the official **[openFDA API](https://open.fda.gov/apis/drug/enforcement/)** (no scraping, no anti-bot drama, no auth needed). Set a **firm watchlist** or **product-keyword watchlist**, choose your severity classification (Class I, II, III), and recall events get pushed to your Slack, Discord, Telegram, or any HTTPS webhook within minutes of openFDA publishing them.

A modern, programmable alternative to manual FDA email subscriptions, FDA RSS, **FDAzilla**, **RegEd**, and other $300–$1,500/mo regulatory-monitoring SaaS — for compliance teams, supplement brands, food manufacturers, medical device firms, pharma RegOps, and equity analysts who need to know **before their lawyers do**.

> **TL;DR:** FDA publishes recalls weekly through the openFDA enforcement API. This actor is a **recall watchlist + watcher** — it polls that feed, filters by your firm/product/severity criteria, and pushes clean structured alerts. Pay only $0.50 per recall match delivered. Quiet weeks cost $0.

### What does FDA Recall Monitor do?

This actor is a programmable wrapper around the official **openFDA Enforcement Reports API** (`api.fda.gov/drug/enforcement.json`, `api.fda.gov/food/enforcement.json`, `api.fda.gov/device/enforcement.json`). It polls the openFDA API for new FDA enforcement actions across:

- **Drugs** (~17,000+ historical records)
- **Food** (~28,000+ historical records)
- **Medical devices** (~38,000+ historical records)

It filters by **firm name keywords**, **product description keywords**, **classification severity** (Class I, II, III), and optional **US state**, then pushes a structured alert to your Slack, Discord, Telegram, or HTTPS webhook. Every alert is also written to the run's dataset for backup and downstream integrations.

Real-world signals like *"Class I recall — Philips Respironics — CPAP machines — pending field safety notice"* hit your channel within a polling interval of FDA publishing them.

#### What this actor solves
- **Push notifications** the moment a new recall posts — not a daily/weekly email digest
- **Custom watchlists** — by firm name, product keyword, or severity classification
- **Direct openFDA API** — clean JSON, no scraping, no breakage
- **Programmatic access** — pipe alerts to your compliance dashboard, ticketing system, or LLM
- **No Zapier or n8n needed** — Apify's built-in Schedules feature does the cron

### Why use FDA Recall Monitor instead of FDA email or expensive RegOps SaaS?

| | FDA email subscriptions | RegOps SaaS (RegEd, Kallpa, FDAzilla) | **FDA Recall Monitor** |
|---|---|---|---|
| **Cost** | Free, but unfiltered noise | $300–$1,500/month | ~$0.50 per match delivered |
| **Push to your channel** | ❌ Email only | Limited, paid integrations | ✅ Slack, Discord, Telegram, webhook |
| **Firm watchlist filter** | ❌ | ✅ | ✅ |
| **Product keyword filter** | ❌ | ✅ | ✅ |
| **Classification (Class I/II/III) filter** | ❌ | ✅ | ✅ |
| **JSON dataset for archiving** | ❌ | ✅ | ✅ |
| **No dashboard required** | ✅ | ❌ | ✅ |
| **Pay only when something matches** | n/a | ❌ (flat fee) | ✅ |

For most compliance teams watching <50 firms or <20 keywords, this actor costs **under $25/month**.

### Use cases & workflows

#### 1. Pharma / supplement compliance
Watch your own firm name + your contract manufacturers + your raw-material suppliers. Get a Slack ping the moment any of them appears in an FDA enforcement action — often before your QA team would notice.

#### 2. Competitor & sector intelligence
Watch competitors. A Class I recall on a competing product is a sales-team signal worth millions: launch a "switch from X" campaign within hours of the news breaking.

#### 3. M&A and due diligence
Monitor target acquisitions during deal evaluation. A surprise Warning Letter or recall mid-process can swing valuation by 8 figures.

#### 4. Investor / hedge fund tracking
Watch a basket of pharma / food / device tickers' parent firms. A material recall is often a stock-moving event before press releases hit the wire.

#### 5. Insurance / liability monitoring
Insurers and legal teams watch entire supply chains. Aggregating openFDA + alert routing dramatically cuts time-to-claim-prep.

#### 6. Journalists & researchers
Beat the FDA RSS feed by hours. Custom keyword watches like "infant formula", "EpiPen", "compounding pharmacy" surface stories before competitors.

### How to use FDA Recall Monitor

> ⚠️ **Important: this actor must be scheduled to receive ongoing alerts.** A single run only checks once. Use Apify's **built-in Schedules** feature — no Zapier, n8n, or external cron needed.

1. **Click "Try for free"** to add the actor to your Apify account.
2. **Configure the input:** select product types (drug/food/device), add `firmKeywords` and/or `productKeywords`, set classification severity, pick a `notificationChannel`.
3. **Paste your webhook URL or Telegram credentials.** All secret fields are stored encrypted by Apify.
4. **First run: enable `testMode`** to fire one alert for the most recent matching recall and confirm your webhook works.
5. **Set up the Schedule:** Actor → Schedules tab → New schedule → cron `0 */12 * * *` (every 12 hours, since openFDA updates weekly there's no value in faster polling).
6. **Optional:** add an [openFDA API key](https://open.fda.gov/apis/authentication/) for higher rate limits in `openFdaApiKey`. Free tier (no key) gives 1,000 req/day, which is plenty for typical use.

#### Schedule cadence cheat sheet

| Cron | Frequency | Best for |
|------|-----------|----------|
| `0 */6 * * *` | every 6 hours | Active monitoring (default for compliance teams) |
| `0 */12 * * *` | every 12 hours | Standard — matches openFDA's update cadence |
| `0 9 * * 1-5` | weekdays 9am UTC | Daily morning digest |

### Input

| Field | Description |
|-------|-------------|
| `productTypes` | One or more of `drug`, `food`, `device` |
| `firmKeywords` | Optional list of firm-name substrings (case-insensitive). Empty = match all firms. |
| `productKeywords` | Optional list of product/reason substrings. Empty = match all products. |
| `classifications` | Severity: `Class I`, `Class II`, `Class III`. Default Class I + II. |
| `states` | Optional 2-letter US state codes (e.g. `["CA","NY"]`). Empty = all locations. |
| `lookbackDays` | How many days back to scan each run. Default 30 (recommended due to openFDA's reporting lag). |
| `notificationChannel` | `none` \| `slack` \| `discord` \| `telegram` \| `webhook` |
| `slackWebhookUrl` / `discordWebhookUrl` | Channel webhooks |
| `telegramBotToken` + `telegramChatId` | Telegram bot credentials |
| `customWebhookUrl` | Any HTTPS endpoint receiving JSON alerts |
| `openFdaApiKey` | Optional — recommended for production schedules |
| `testMode` | First-run sanity check — fires one alert without dedup |

### Output

Every alert is also pushed to the run's dataset. Example item:

```json
{
  "recallNumber": "Z-1646-2026",
  "eventId": "98763",
  "reportDate": "2026-04-29",
  "recallInitiationDate": "2026-04-09",
  "productType": "device",
  "classification": "Class I",
  "recallingFirm": "Philips Respironics, Inc.",
  "city": "Murrysville",
  "state": "PA",
  "country": "United States",
  "productDescription": "DreamStation 2 Auto CPAP Advanced...",
  "reasonForRecall": "Potential health risk from heater plate degradation...",
  "distributionPattern": "Nationwide in the USA",
  "status": "Ongoing",
  "voluntaryMandated": "Voluntary: Firm initiated",
  "fdaUrl": "https://www.fda.gov/safety/recalls-market-withdrawals-safety-alerts?search_api_fulltext=Z-1646-2026"
}
````

You can download the dataset in **JSON, CSV, Excel, or HTML** from the Apify Console.

### Data table

| Field | Type | Description |
|-------|------|-------------|
| `reportDate` | date | When FDA published the recall |
| `productType` | string | drug / food / device |
| `classification` | string | Class I / II / III |
| `recallingFirm` | string | Name of company recalling |
| `productDescription` | string | What's being recalled |
| `reasonForRecall` | string | Why |
| `distributionPattern` | string | Where the product was distributed |
| `state` | string | US state of recalling firm |
| `recallNumber` | string | Official FDA recall number |
| `fdaUrl` | link | Direct link to FDA recall page |

### Pricing — pay-per-event

This actor uses **Apify pay-per-event pricing: ~$0.50 per recall alert delivered**. On days with no matching recalls, you pay nothing. Compare to:

| Service | Approx cost | Notes |
|---|---|---|
| FDA email subscription | Free | Unfiltered, email-only, no API |
| Email-to-Slack via Zapier | $20/mo + Zapier fees | DIY, brittle |
| RegOps SaaS (RegEd, FDAzilla) | $300–$1,500/month | Enterprise contracts, far more features |
| **FDA Recall Monitor** | **$5–$50/month for typical use** | Push alerts + JSON API |

### Tips & advanced options

- **Use firm + product filters together.** If you watch 20 firms with no keyword filter, expect 20–100 alerts/month. Add product keywords to narrow.
- **Default to Class I + II.** Class III recalls are technical/cosmetic — usually noise.
- **Get an openFDA API key.** Free, raises your daily quota from 1,000 → 120,000 requests. Useful if you watch many product types or have very wide keyword filters.
- **Pipe to a database.** Set `notificationChannel: "none"` and use Apify's Webhook Integration to POST every new dataset item to your own backend or BI tool.
- **Combine with FDA Warning Letter / Form 483 monitoring.** Recalls are downstream signals; Warning Letters and 483s are leading indicators. Pair this actor with separate Warning Letter and 483 monitors for full coverage.

### FAQ

**Is this legal?** Yes. openFDA is the FDA's official public API under the [Open Government Initiative](https://open.fda.gov/). All data is public-domain.

**How fresh is the data?** openFDA updates roughly weekly with a 3–10 day lag from the original FDA enforcement report. Keep `lookbackDays` at 30 to ensure no recalls slip through.

**Why might I see 0 alerts on a single run?** openFDA batches updates — many days have no new postings. With dedup, repeat runs only alert once per recall.

**Why isn't my firm appearing?** Firms appear in openFDA exactly as they're listed in the FDA report. If you watch "Pfizer", you may also need "Pfizer Inc.", "Pfizer Pharmaceuticals", and any subsidiaries. Use shorter substrings ("pfizer") for broader matching.

**Does this cover Warning Letters or Form 483?** No — only enforcement recalls. Warning Letters and 483 inspections are separate FDA data sources.

**Does this cover non-US recalls (EU EMA, UK MHRA, Canada Health)?** No — US FDA only. Each authority would need its own actor.

### Support

Open an issue on the actor's **Issues** tab. Feature requests and feedback welcome.

***

*Disclaimer: This actor is an information-retrieval tool for publicly available FDA data. Nothing in its output constitutes legal, medical, or compliance advice.*

**Keywords:** FDA recall alerts, FDA recall monitor, FDA recall watchlist, FDA recall watcher, openFDA API, openFDA enforcement API, openFDA wrapper, FDA enforcement reports API, drug recall alerts, food recall monitor, medical device recall tracker, FDA Class I recall, FDA enforcement reports, FDA recall Slack alerts, FDA recall Discord bot, FDA recall Telegram bot, pharma compliance monitoring, supplement recall tracker, recall notification API, FDAzilla alternative, RegEd alternative, real-time FDA recalls.

# Actor input Schema

## `productTypes` (type: `array`):

Which FDA recall categories to check on every run.

## `firmKeywords` (type: `array`):

Match if any of these strings appears (case-insensitive) in the recalling firm name. Leave empty to match all firms.

## `productKeywords` (type: `array`):

Match if any of these strings appears (case-insensitive) in the product description or reason for recall. Leave empty to match all products.

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

Class I = imminent danger of death/serious injury. Class II = temporary or medically reversible. Class III = unlikely to cause adverse health.

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

Two-letter state codes (e.g. CA, NY). Leave empty to include all states and international firms.

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

On each run, check recalls reported within this many days. openFDA updates ~weekly with a few-days lag, so 30 is a safe default — the dedup state ensures you only get alerted once per recall regardless of this window.

## `notificationChannel` (type: `string`):

Where to send alerts. 'none' = dataset only (use Apify integrations like Zapier or Make to wire that up).

## `slackWebhookUrl` (type: `string`):

Required when channel is 'slack'.

## `discordWebhookUrl` (type: `string`):

Required when channel is 'discord'.

## `telegramBotToken` (type: `string`):

Bot token from @BotFather. Required when channel is 'telegram'.

## `telegramChatId` (type: `string`):

Required when channel is 'telegram'.

## `customWebhookUrl` (type: `string`):

Any HTTPS endpoint. Receives a JSON POST per match.

## `openFdaApiKey` (type: `string`):

openFDA allows 240 requests/min and 1,000/day without a key. With a free key (https://open.fda.gov/apis/authentication/) you get 240/min and 120,000/day. Recommended for production schedules.

## `testMode` (type: `boolean`):

Ignore dedup state and fire one alert for the most recent matching recall. Use this to confirm your webhook works before scheduling.

## Actor input object example

```json
{
  "productTypes": [
    "drug",
    "food",
    "device"
  ],
  "firmKeywords": [],
  "productKeywords": [],
  "classifications": [
    "Class I",
    "Class II"
  ],
  "states": [],
  "lookbackDays": 30,
  "notificationChannel": "none",
  "testMode": false
}
```

# Actor output Schema

## `alerts` (type: `string`):

All matched recalls from this run. Download as JSON, CSV, Excel, or HTML.

## `runConsole` (type: `string`):

No description

# 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 = {
    "firmKeywords": [],
    "productKeywords": [],
    "states": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("incontrovertible_gate/fda-recall-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 = {
    "firmKeywords": [],
    "productKeywords": [],
    "states": [],
}

# Run the Actor and wait for it to finish
run = client.actor("incontrovertible_gate/fda-recall-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 '{
  "firmKeywords": [],
  "productKeywords": [],
  "states": []
}' |
apify call incontrovertible_gate/fda-recall-monitor --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "FDA Recall Monitor — Real-Time Slack & Telegram Alerts",
        "description": "Real-time alerts on FDA drug, food, and medical device recalls from the official openFDA API. Watch any firms or products and push notifications to Slack,\n  Discord, Telegram, or webhook. A modern alternative to FDAzilla, RegEd, and FDA email subscriptions — pay only $0.50 per match",
        "version": "0.0",
        "x-build-id": "3eUY8tF8tCyLV9rQN"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/incontrovertible_gate~fda-recall-monitor/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-incontrovertible_gate-fda-recall-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/incontrovertible_gate~fda-recall-monitor/runs": {
            "post": {
                "operationId": "runs-sync-incontrovertible_gate-fda-recall-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/incontrovertible_gate~fda-recall-monitor/run-sync": {
            "post": {
                "operationId": "run-sync-incontrovertible_gate-fda-recall-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": [
                    "productTypes",
                    "classifications"
                ],
                "properties": {
                    "productTypes": {
                        "title": "Recall categories to watch",
                        "uniqueItems": true,
                        "type": "array",
                        "description": "Which FDA recall categories to check on every run.",
                        "items": {
                            "type": "string",
                            "enum": [
                                "drug",
                                "food",
                                "device"
                            ],
                            "enumTitles": [
                                "Drug recalls",
                                "Food recalls",
                                "Medical device recalls"
                            ]
                        },
                        "default": [
                            "drug",
                            "food",
                            "device"
                        ]
                    },
                    "firmKeywords": {
                        "title": "Firm name keywords (optional)",
                        "type": "array",
                        "description": "Match if any of these strings appears (case-insensitive) in the recalling firm name. Leave empty to match all firms.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "productKeywords": {
                        "title": "Product description keywords (optional)",
                        "type": "array",
                        "description": "Match if any of these strings appears (case-insensitive) in the product description or reason for recall. Leave empty to match all products.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "classifications": {
                        "title": "Severity classifications to alert on",
                        "uniqueItems": true,
                        "type": "array",
                        "description": "Class I = imminent danger of death/serious injury. Class II = temporary or medically reversible. Class III = unlikely to cause adverse health.",
                        "items": {
                            "type": "string",
                            "enum": [
                                "Class I",
                                "Class II",
                                "Class III"
                            ],
                            "enumTitles": [
                                "Class I — imminent danger",
                                "Class II — temporary harm",
                                "Class III — minor"
                            ]
                        },
                        "default": [
                            "Class I",
                            "Class II"
                        ]
                    },
                    "states": {
                        "title": "Limit to recalling firms in these US states (optional)",
                        "type": "array",
                        "description": "Two-letter state codes (e.g. CA, NY). Leave empty to include all states and international firms.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "lookbackDays": {
                        "title": "Lookback window (days)",
                        "minimum": 1,
                        "maximum": 365,
                        "type": "integer",
                        "description": "On each run, check recalls reported within this many days. openFDA updates ~weekly with a few-days lag, so 30 is a safe default — the dedup state ensures you only get alerted once per recall regardless of this window.",
                        "default": 30
                    },
                    "notificationChannel": {
                        "title": "Notification channel",
                        "enum": [
                            "none",
                            "slack",
                            "discord",
                            "telegram",
                            "webhook"
                        ],
                        "type": "string",
                        "description": "Where to send alerts. 'none' = dataset only (use Apify integrations like Zapier or Make to wire that up).",
                        "default": "none"
                    },
                    "slackWebhookUrl": {
                        "title": "Slack webhook URL",
                        "type": "string",
                        "description": "Required when channel is 'slack'."
                    },
                    "discordWebhookUrl": {
                        "title": "Discord webhook URL",
                        "type": "string",
                        "description": "Required when channel is 'discord'."
                    },
                    "telegramBotToken": {
                        "title": "Telegram bot token",
                        "type": "string",
                        "description": "Bot token from @BotFather. Required when channel is 'telegram'."
                    },
                    "telegramChatId": {
                        "title": "Telegram chat ID",
                        "type": "string",
                        "description": "Required when channel is 'telegram'."
                    },
                    "customWebhookUrl": {
                        "title": "Custom webhook URL",
                        "type": "string",
                        "description": "Any HTTPS endpoint. Receives a JSON POST per match."
                    },
                    "openFdaApiKey": {
                        "title": "openFDA API key (optional)",
                        "type": "string",
                        "description": "openFDA allows 240 requests/min and 1,000/day without a key. With a free key (https://open.fda.gov/apis/authentication/) you get 240/min and 120,000/day. Recommended for production schedules."
                    },
                    "testMode": {
                        "title": "Test mode",
                        "type": "boolean",
                        "description": "Ignore dedup state and fire one alert for the most recent matching recall. Use this to confirm your webhook works before scheduling.",
                        "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
