{
  "openapi": "3.0.1",
  "info": {
    "title": "FDA Recall Database API, Food, Drug, Device Enforcement Reports",
    "description": "A recall scraper for the FDA database — food, drug and device — from openFDA, plus an optional press-release feed up to 9 days faster. 37 fields incl. severity, a documented 0-100 riskScore (not AI), recalling firm, ISO dates, NDC/UPC/brand on drug recalls. From $0.0024/result, no start fee. FDA API",
    "version": "0.1",
    "x-build-id": "cwMAOIZ3HwFlTMtg4"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/fetchsmith~fda-recall-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-fetchsmith-fda-recall-scraper",
        "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/fetchsmith~fda-recall-scraper/runs": {
      "post": {
        "operationId": "runs-sync-fetchsmith-fda-recall-scraper",
        "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/fetchsmith~fda-recall-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-fetchsmith-fda-recall-scraper",
        "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",
        "properties": {
          "productTypes": {
            "title": "Product types",
            "uniqueItems": true,
            "type": "array",
            "description": "Which openFDA enforcement endpoints to search. All three by default. Results are interleaved and every row is tagged with productType.",
            "items": {
              "type": "string",
              "enum": [
                "food",
                "drug",
                "device"
              ],
              "enumTitles": [
                "Food",
                "Drug",
                "Device"
              ]
            },
            "default": [
              "food",
              "drug",
              "device"
            ]
          },
          "dateField": {
            "title": "Date field to filter on",
            "enum": [
              "report_date",
              "recall_initiation_date",
              "termination_date"
            ],
            "type": "string",
            "description": "Which date the date range below applies to. Report date (default) is when FDA published the enforcement report, which can be months after the recall actually started — switch to recall initiation date to catch recalls by when the firm/FDA acted, or termination date to find recalls that closed out in a window.",
            "default": "report_date"
          },
          "reportDateFrom": {
            "title": "Date from",
            "type": "string",
            "description": "Earliest date, YYYY-MM-DD or YYYYMMDD, for whichever field dateField selects (report date by default). Defaults to one year ago."
          },
          "reportDateTo": {
            "title": "Date to",
            "type": "string",
            "description": "Latest date, YYYY-MM-DD or YYYYMMDD, for whichever field dateField selects (report date by default). Defaults to today."
          },
          "brandName": {
            "title": "Brand name (drug recalls only)",
            "type": "string",
            "description": "Filter to recalls whose drug brand name matches, for example \"Nurtec\". Phrase-matched against openFDA's cross-referenced openfda.brand_name field, which only drug recalls carry — food and device recalls will never match this filter, so combine it with productTypes:[\"drug\"] (or leave productTypes at its default; the other two types just return nothing for this field). Leave empty for all."
          },
          "genericName": {
            "title": "Generic name (drug recalls only)",
            "type": "string",
            "description": "Filter to recalls whose drug generic/active-ingredient name matches, for example \"ibuprofen\". Same drug-only field as brandName above — see that description. Leave empty for all."
          },
          "manufacturerName": {
            "title": "Manufacturer name (drug recalls only)",
            "type": "string",
            "description": "Filter to recalls whose drug manufacturer name matches, for example \"Pfizer\". Same drug-only field as brandName above (not to be confused with recallingFirm, which is the firm that issued the recall and applies to all three product types). Leave empty for all."
          },
          "recallingFirm": {
            "title": "Recalling firm",
            "type": "string",
            "description": "Filter to recalls by one firm, for example \"Tyson Foods\". Phrase-matched against the recalling_firm field. Leave empty for all firms. Narrower than searchQuery, which also matches product description and recall reason."
          },
          "city": {
            "title": "Recalling firm city",
            "type": "string",
            "description": "Filter to recalls whose recalling firm is in this city, for example \"Chicago\". Leave empty for all cities."
          },
          "voluntaryMandated": {
            "title": "Voluntary or FDA mandated",
            "enum": [
              "",
              "Voluntary: Firm initiated",
              "FDA Mandated"
            ],
            "type": "string",
            "description": "Filter by whether the recall was voluntary (firm-initiated) or FDA mandated. FDA-mandated recalls are rare (under 2% of all recalls) and often signal a more serious enforcement action.",
            "default": ""
          },
          "classifications": {
            "title": "Classifications",
            "uniqueItems": true,
            "type": "array",
            "description": "Recall severity. Class I = reasonable probability of serious harm or death, Class II = temporary/reversible harm, Class III = unlikely to cause harm. Leave empty for all.",
            "items": {
              "type": "string",
              "enum": [
                "Class I",
                "Class II",
                "Class III"
              ],
              "enumTitles": [
                "Class I (most serious)",
                "Class II",
                "Class III (least serious)"
              ]
            }
          },
          "states": {
            "title": "Recalling firm states",
            "uniqueItems": true,
            "type": "array",
            "description": "Two-letter US state codes of the RECALLING FIRM (not where the product was distributed — see distributionPattern in the output for that). Multiple values are ORed. For CANADIAN firms FDA spells the province out in full, so use \"British Columbia\", not \"BC\" (also Ontario, Quebec, Nova Scotia, Alberta, Manitoba, New Brunswick); matching is case-insensitive. Set together with countries the two fields are ANDed, not ORed — a recall must match both. Leave empty for all.",
            "items": {
              "type": "string"
            }
          },
          "countries": {
            "title": "Recalling firm countries",
            "uniqueItems": true,
            "type": "array",
            "description": "Country names of the RECALLING FIRM, exactly as FDA writes them (for example \"United States\", \"Canada\", \"Israel\"). Most recalls are United States firms, but FDA also lists foreign firms whose products entered the US market. Multiple values are ORed; set together with states the two fields are ANDed, not ORed — a recall must match both. Leave empty for all.",
            "items": {
              "type": "string"
            }
          },
          "recallNumber": {
            "title": "Recall number (exact)",
            "type": "string",
            "description": "Look up one recall by its exact FDA recall number, for example \"F-1233-2022\". Overrides every other filter above except productTypes (FDA recall numbers aren't unique across food/drug/device, so leave productTypes narrowed if you know which one). Leave empty for normal filtered search."
          },
          "eventId": {
            "title": "Recall event ID (exact)",
            "type": "string",
            "description": "Look up every product recalled under one FDA enforcement event ID, for example \"90105\" (a single recall event can cover several products, each its own row here). Overrides every other filter above except productTypes. Leave empty for normal filtered search."
          },
          "status": {
            "title": "Recall status",
            "enum": [
              "",
              "Ongoing",
              "Completed",
              "Terminated",
              "Pending"
            ],
            "type": "string",
            "description": "Filter by FDA recall status. Leave empty for all. \"Pending\" is a value in FDA's own status vocabulary but has never appeared in openFDA's enforcement data for any product type (verified 2026-09-25) -- expect zero rows if you select it; it's offered only because FDA defines it.",
            "default": ""
          },
          "searchQuery": {
            "title": "Search query",
            "type": "string",
            "description": "Free-text phrase matched against product description, reason for recall and recalling firm name. One distinctive word works better than a long phrase."
          },
          "order": {
            "title": "Sort order",
            "enum": [
              "desc",
              "asc"
            ],
            "type": "string",
            "description": "Sort by whichever field dateField selects, newest or oldest first.",
            "default": "desc"
          },
          "maxResults": {
            "title": "Max results",
            "minimum": 1,
            "maximum": 50000,
            "type": "integer",
            "description": "Stop after this many recalls in total across all selected product types.",
            "default": 100
          },
          "includeRiskScore": {
            "title": "Include risk score",
            "type": "boolean",
            "description": "Add a riskScore field (0-100) to every row: a documented, deterministic formula (not AI) combining Class I/II/III severity (45%), how recent the recall is (30%, linear decay to 0 at two years old), and distribution scope parsed from distributionPattern (25%: nationwide/international text or count of US state codes mentioned). Useful for sorting/triaging a large result set. On by default; set false to skip the computation.",
            "default": true
          },
          "includePressReleases": {
            "title": "Also include FDA press releases (faster than the enforcement API)",
            "type": "boolean",
            "description": "Off by default. The openFDA enforcement API above is complete but slow: newest reports typically lag the real recall announcement by over a week (measured 11 days on 2026-09-20). Turning this on additionally fetches FDA's own recall press-release RSS feed, which had items up to 9 days ahead of the enforcement API in that same measurement. It's a rolling ~20-item window (a few weeks of history, not an archive), so use it for freshness, not completeness. These rows are tagged source:\"press_release\" and carry only productDescription, reasonForRecall, reportDate and sourceUrl — recallNumber, classification, status, distributionPattern and every drug-only field are null (the press release simply doesn't state them; the same recall usually appears again later, tagged source:\"enforcement\", once openFDA catches up — that's expected, not a duplicate bug). Automatically skipped (with a log warning) if you also set a filter the feed can't support: dateField other than report date, productTypes narrowed to fewer than all three, classifications, states, countries, status, recallingFirm, city, voluntaryMandated, brandName, genericName, manufacturerName, or an exact recallNumber/eventId lookup.",
            "default": false
          },
          "watchLabel": {
            "title": "Watch label (only new since last run)",
            "type": "string",
            "description": "Optional. Name a saved search (e.g. \"my-class-i-watch\") and this run returns ONLY recalls not delivered under that same label and filter set before, instead of the full match set every time. The first run for a label is a free baseline: it records what already matches and returns zero rows. Run it again later -- on a schedule, typically -- to get only what's new. The baseline is kept in your own Apify account (a named key-value store), keyed by label plus a fingerprint of your other filters, so changing a filter starts a fresh baseline instead of dumping previously-excluded recalls as \"new\"."
          },
          "watchChanges": {
            "title": "Also alert on status/classification changes",
            "type": "boolean",
            "description": "Only used with watchLabel. When on, a recall you were already alerted on is re-delivered (charged again) if its status changes (e.g. Ongoing -> Terminated) or FDA reclassifies its severity (e.g. Class II -> Class I), tagged with _watchChangeType and _watchPrevious showing exactly what moved. Off by default, so a plain watchLabel only ever alerts on brand-new recalls, same as before this option existed.",
            "default": false
          },
          "webhookUrl": {
            "title": "Webhook URL (notify on completion)",
            "type": "string",
            "description": "Optional. An http(s) URL to POST a small JSON summary to when the run finishes — recalls pushed, rows scanned, watch-label new/changed counts if Watch label is set, and the run's dataset ID so you can fetch the results. A convenience for callers who want a completion ping without setting up an Apify platform webhook (which needs separate Console/API configuration per Task, not per run). Best-effort: a failed or slow webhook is logged as a warning and never fails the run or affects charging — it fires after every recall has already been pushed and charged. Leave empty to skip."
          }
        }
      },
      "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
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "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
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}