{"openapi":"3.1.0","info":{"title":"Food Recall Monitor API","description":"Normalized U.S. food recalls from FDA and USDA FSIS with allergen detection, distribution states, and a change-history feed. Data is derived from official U.S. FDA (openFDA food enforcement reports) and USDA FSIS recall notices. It is provided as-is, may be delayed or incomplete, and is not a safety guarantee. Always confirm with the original notice (source_url). FDA and USDA source records are U.S. government works. Authenticate with a marketplace subscription (the gateway sends its proxy secret; clients send X-RapidAPI-Key to the gateway) or a direct X-API-Key issued by Wryborg. Direct keys are rate limited on this server (per second and a monthly quota) and are not enabled for arbitrary browser origins. The free plan covers the last 12 months. When a date filter is clamped, the response adds a warnings array and an X-History-Clamped header. brand is best-effort: it is parsed from the product description when the notice names one, and the brand filter also matches firm and product text.","contact":{"name":"Wryborg","url":"https://wryborg.com/","email":"hello@wryborg.com"},"version":"2.0.0"},"servers":[{"url":"/v1"},{"url":"https://api.wryborg.com/v1","description":"Production"}],"paths":{"/health":{"get":{"tags":["meta"],"summary":"Service health","description":"Liveness and the last successful ingest per source. This endpoint is public; it does not require X-API-Key or a marketplace secret.","operationId":"getHealth","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Health"}}}}},"security":[]}},"/recalls":{"get":{"tags":["recalls"],"summary":"List recalls","description":"Filter, sort, and page recalls. Invalid enum values return 422 and list the allowed values. Case-insensitive aliases are accepted for source (fsis, usda), state names, and allergen plurals. date_from after date_to returns 422. On the free plan a date_from before the 12-month window is clamped; warnings and X-History-Clamped report that.","operationId":"listRecalls","parameters":[{"name":"brand","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"description":"Case-insensitive substring against firm, brand, and the indexed search text (firm, brand, product description, and reason). At most 200 characters.","examples":["kraft"],"title":"Brand"},"description":"Case-insensitive substring against firm, brand, and the indexed search text (firm, brand, product description, and reason). At most 200 characters."},{"name":"product_category","in":"query","required":false,"schema":{"anyOf":[{"type":"string","enum":["supplements","infant_formula_baby","frozen_desserts","meat_poultry","seafood","eggs","dairy","nuts_seeds","dips_spreads_sauces","bakery","snacks_confectionery","grains_pasta_flour","beverages","spices_seasonings","produce","prepared_foods","oils_fats","ingredients_bulk","other"]},{"type":"null"}],"description":"Case-insensitive. Spaces and hyphens are accepted. Allowed: supplements, infant_formula_baby, frozen_desserts, meat_poultry, seafood, eggs, dairy, nuts_seeds, dips_spreads_sauces, bakery, snacks_confectionery, grains_pasta_flour, beverages, spices_seasonings, produce, prepared_foods, oils_fats, ingredients_bulk, other.","examples":["dairy"],"title":"Product Category"},"description":"Case-insensitive. Spaces and hyphens are accepted. Allowed: supplements, infant_formula_baby, frozen_desserts, meat_poultry, seafood, eggs, dairy, nuts_seeds, dips_spreads_sauces, bakery, snacks_confectionery, grains_pasta_flour, beverages, spices_seasonings, produce, prepared_foods, oils_fats, ingredients_bulk, other."},{"name":"allergen","in":"query","required":false,"schema":{"anyOf":[{"type":"string","enum":["milk","egg","peanut","tree_nut","soy","wheat","fish","shellfish","sesame"]},{"type":"null"}],"description":"Case-insensitive. Spaces, hyphens, and a trailing plural are accepted. Allowed: milk, egg, peanut, tree_nut, soy, wheat, fish, shellfish, sesame.","examples":["peanut"],"title":"Allergen"},"description":"Case-insensitive. Spaces, hyphens, and a trailing plural are accepted. Allowed: milk, egg, peanut, tree_nut, soy, wheat, fish, shellfish, sesame."},{"name":"state","in":"query","required":false,"schema":{"anyOf":[{"type":"string","enum":["AL","AK","AZ","AR","CA","CO","CT","DE","FL","GA","HI","ID","IL","IN","IA","KS","KY","LA","ME","MD","MA","MI","MN","MS","MO","MT","NE","NV","NH","NJ","NM","NY","NC","ND","OH","OK","OR","PA","RI","SC","SD","TN","TX","UT","VT","VA","WA","WV","WI","WY","DC","PR","GU","VI","AS","MP","NATIONWIDE"]},{"type":"null"}],"description":"US state, DC, or territory: 2-letter code or full name, case-insensitive. NATIONWIDE is allowed. Filtering a state also returns NATIONWIDE recalls. Allowed: AL, AK, AZ, AR, CA, CO, CT, DE, FL, GA, HI, ID, IL, IN, IA, KS, KY, LA, ME, MD, MA, MI, MN, MS, MO, MT, NE, NV, NH, NJ, NM, NY, NC, ND, OH, OK, OR, PA, RI, SC, SD, TN, TX, UT, VT, VA, WA, WV, WI, WY, DC, PR, GU, VI, AS, MP, NATIONWIDE.","examples":["CA"],"title":"State"},"description":"US state, DC, or territory: 2-letter code or full name, case-insensitive. NATIONWIDE is allowed. Filtering a state also returns NATIONWIDE recalls. Allowed: AL, AK, AZ, AR, CA, CO, CT, DE, FL, GA, HI, ID, IL, IN, IA, KS, KY, LA, ME, MD, MA, MI, MN, MS, MO, MT, NE, NV, NH, NJ, NM, NY, NC, ND, OH, OK, OR, PA, RI, SC, SD, TN, TX, UT, VT, VA, WA, WV, WI, WY, DC, PR, GU, VI, AS, MP, NATIONWIDE."},{"name":"classification","in":"query","required":false,"schema":{"anyOf":[{"type":"string","enum":["Class I","Class II","Class III"]},{"type":"null"}],"description":"Case-insensitive. Allowed: Class I, Class II, Class III. Aliases: I, II, III or 1, 2, 3.","examples":["Class I"],"title":"Classification"},"description":"Case-insensitive. Allowed: Class I, Class II, Class III. Aliases: I, II, III or 1, 2, 3."},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string","enum":["Ongoing","Completed","Terminated"]},{"type":"null"}],"description":"Case-insensitive. Allowed: Ongoing, Completed, Terminated. Alias: complete = Completed.","examples":["Ongoing"],"title":"Status"},"description":"Case-insensitive. Allowed: Ongoing, Completed, Terminated. Alias: complete = Completed."},{"name":"source","in":"query","required":false,"schema":{"anyOf":[{"type":"string","enum":["FDA","USDA-FSIS"]},{"type":"null"}],"description":"Case-insensitive. Allowed: FDA, USDA-FSIS. Aliases: fsis, usda, usda_fsis, usda-fsis.","examples":["FDA"],"title":"Source"},"description":"Case-insensitive. Allowed: FDA, USDA-FSIS. Aliases: fsis, usda, usda_fsis, usda-fsis."},{"name":"date_from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"report_date on or after this day (YYYY-MM-DD).","examples":["2026-01-01"],"title":"Date From"},"description":"report_date on or after this day (YYYY-MM-DD)."},{"name":"date_to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"report_date on or before this day (YYYY-MM-DD).","examples":["2026-10-01"],"title":"Date To"},"description":"report_date on or before this day (YYYY-MM-DD)."},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"description":"Full-text keyword search over firm, product, and reason. At most 200 characters and 10 words, ANDed.","examples":["listeria"],"title":"Q"},"description":"Full-text keyword search over firm, product, and reason. At most 200 characters and 10 words, ANDed."},{"name":"sort","in":"query","required":false,"schema":{"type":"string","description":"Case-insensitive. Allowed: report_date, -report_date, recall_initiation_date, -recall_initiation_date. A leading '-' sorts descending.","examples":["-report_date"],"default":"-report_date","title":"Sort","enum":["report_date","-report_date","recall_initiation_date","-recall_initiation_date"]},"description":"Case-insensitive. Allowed: report_date, -report_date, recall_initiation_date, -recall_initiation_date. A leading '-' sorts descending."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Page size. 1–100.","examples":[25],"default":25,"title":"Limit"},"description":"Page size. 1–100."},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"Rows to skip. Must be >= 0.","examples":[0],"default":0,"title":"Offset"},"description":"Rows to skip. Must be >= 0."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Page"}}}},"401":{"description":"Missing or invalid credentials. Send the marketplace proxy secret (added by the gateway) or a direct X-API-Key. Direct keys are rate limited on this server.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"A query parameter is missing, out of range, or not one of the allowed values. detail[].msg names the parameter and lists the allowed values.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"429":{"description":"Direct X-API-Key per-second rate limit (detail.error rate_limited) or monthly quota (detail.error quota_exceeded). Retry-After is set. Marketplace quotas are enforced by the marketplace, not here.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/recalls/changes":{"get":{"tags":["changes"],"summary":"List recall changes","description":"Created and updated recalls since a UTC timestamp. since is parsed to UTC before it is compared (offsets such as -05:00 and a space between date and time are accepted). Page with after_seq / next_seq so rows that share changed_at are not repeated. Requires Pro or Business (403 plan_upgrade_required otherwise). since format: YYYY-MM-DD or an ISO-8601 datetime, for example 2026-10-01, 2026-10-01T00:00:00Z, or 2026-10-01 00:00:00-05:00.","operationId":"listRecallChanges","parameters":[{"name":"since","in":"query","required":true,"schema":{"type":"string","description":"Lower bound on changed_at, inclusive. Parsed to UTC before comparison. Format: YYYY-MM-DD or an ISO-8601 datetime, for example 2026-10-01, 2026-10-01T00:00:00Z, or 2026-10-01 00:00:00-05:00. A date with no time is 00:00:00Z. Offsets such as -05:00 are converted to UTC. A space between date and time is accepted and treated as UTC when no offset is given.","examples":["2026-10-01"],"title":"Since"},"description":"Lower bound on changed_at, inclusive. Parsed to UTC before comparison. Format: YYYY-MM-DD or an ISO-8601 datetime, for example 2026-10-01, 2026-10-01T00:00:00Z, or 2026-10-01 00:00:00-05:00. A date with no time is 00:00:00Z. Offsets such as -05:00 are converted to UTC. A space between date and time is accepted and treated as UTC when no offset is given."},{"name":"change_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string","enum":["created","updated"]},{"type":"null"}],"description":"Case-insensitive. Allowed: created, updated. Aliases: create, update.","examples":["created"],"title":"Change Type"},"description":"Case-insensitive. Allowed: created, updated. Aliases: create, update."},{"name":"include_recall","in":"query","required":false,"schema":{"type":"boolean","description":"Embed the current recall on each change.","default":true,"title":"Include Recall"},"description":"Embed the current recall on each change."},{"name":"include_baseline","in":"query","required":false,"schema":{"type":"boolean","description":"Include the initial-load 'created' records (baseline snapshot).","default":false,"title":"Include Baseline"},"description":"Include the initial-load 'created' records (baseline snapshot)."},{"name":"after_seq","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"description":"Return changes with seq greater than this cursor. Use next_seq from the previous page.","title":"After Seq"},"description":"Return changes with seq greater than this cursor. Use next_seq from the previous page."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"description":"Page size before the plan cap. Pro and Business cap this at 1,000.","default":100,"title":"Limit"},"description":"Page size before the plan cap. Pro and Business cap this at 1,000."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangePage"}}}},"401":{"description":"Missing or invalid credentials. Send the marketplace proxy secret (added by the gateway) or a direct X-API-Key. Direct keys are rate limited on this server.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"A query parameter is missing, out of range, or not one of the allowed values. detail[].msg names the parameter and lists the allowed values.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"429":{"description":"Direct X-API-Key per-second rate limit (detail.error rate_limited) or monthly quota (detail.error quota_exceeded). Retry-After is set. Marketplace quotas are enforced by the marketplace, not here.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"This plan cannot access the resource. detail.error is plan_upgrade_required. The changes feed requires Pro or Business. A single recall older than 12 months requires Basic or higher.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/recalls/{recall_id}":{"get":{"tags":["recalls"],"summary":"Get one recall","description":"Fetch by internal id or official recall number. Unknown ids return 404 {\"detail\": \"Recall not found\"}. A recall older than the free-plan window returns 403 plan_upgrade_required.","operationId":"getRecall","parameters":[{"name":"recall_id","in":"path","required":true,"schema":{"type":"string","description":"Internal id (fda-H-0089-2027, fda-event-…, fsis-027-2026) or the official recall number (H-0089-2027, 027-2026).","examples":["H-0089-2027"],"title":"Recall Id"},"description":"Internal id (fda-H-0089-2027, fda-event-…, fsis-027-2026) or the official recall number (H-0089-2027, 027-2026)."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Recall"}}}},"401":{"description":"Missing or invalid credentials. Send the marketplace proxy secret (added by the gateway) or a direct X-API-Key. Direct keys are rate limited on this server.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"A query parameter is missing, out of range, or not one of the allowed values. detail[].msg names the parameter and lists the allowed values.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"429":{"description":"Direct X-API-Key per-second rate limit (detail.error rate_limited) or monthly quota (detail.error quota_exceeded). Retry-After is set. Marketplace quotas are enforced by the marketplace, not here.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"This plan cannot access the resource. detail.error is plan_upgrade_required. The changes feed requires Pro or Business. A single recall older than 12 months requires Basic or higher.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No recall with that id or official recall number.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/allergens":{"get":{"tags":["reference"],"summary":"List major allergens","description":"The nine FDA major food allergens (FALCPA + FASTER Act) and how many recalls mention each.","operationId":"listAllergens","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AllergenList"}}}},"401":{"description":"Missing or invalid credentials. Send the marketplace proxy secret (added by the gateway) or a direct X-API-Key. Direct keys are rate limited on this server.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"A query parameter is missing, out of range, or not one of the allowed values. detail[].msg names the parameter and lists the allowed values.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"429":{"description":"Direct X-API-Key per-second rate limit (detail.error rate_limited) or monthly quota (detail.error quota_exceeded). Retry-After is set. Marketplace quotas are enforced by the marketplace, not here.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/stats":{"get":{"tags":["reference"],"summary":"Corpus statistics","description":"Counts by source, classification, status, category, allergen, and the ten most common distribution states.","operationId":"getStats","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Stats"}}}},"401":{"description":"Missing or invalid credentials. Send the marketplace proxy secret (added by the gateway) or a direct X-API-Key. Direct keys are rate limited on this server.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"A query parameter is missing, out of range, or not one of the allowed values. detail[].msg names the parameter and lists the allowed values.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"429":{"description":"Direct X-API-Key per-second rate limit (detail.error rate_limited) or monthly quota (detail.error quota_exceeded). Retry-After is set. Marketplace quotas are enforced by the marketplace, not here.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}},"components":{"schemas":{"AllergenCount":{"properties":{"code":{"type":"string","title":"Code"},"name":{"type":"string","title":"Name"},"recall_count":{"type":"integer","title":"Recall Count"}},"type":"object","required":["code","name","recall_count"],"title":"AllergenCount"},"AllergenList":{"properties":{"standard":{"type":"string","title":"Standard"},"data":{"items":{"$ref":"#/components/schemas/AllergenCount"},"type":"array","title":"Data"}},"type":"object","required":["standard","data"],"title":"AllergenList"},"Change":{"properties":{"seq":{"type":"integer","title":"Seq"},"recall_id":{"type":"string","title":"Recall Id"},"change_type":{"type":"string","title":"Change Type"},"changed_at":{"type":"string","title":"Changed At"},"is_baseline":{"type":"boolean","title":"Is Baseline","default":false},"changed_fields":{"items":{"type":"string"},"type":"array","title":"Changed Fields"},"previous":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Previous"},"current":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Current"},"recall":{"anyOf":[{"$ref":"#/components/schemas/Recall"},{"type":"null"}]}},"type":"object","required":["seq","recall_id","change_type","changed_at","changed_fields"],"title":"Change"},"ChangePage":{"properties":{"since":{"type":"string","title":"Since","description":"The since value you sent, compared as UTC. YYYY-MM-DD or an ISO-8601 datetime, for example 2026-10-01, 2026-10-01T00:00:00Z, or 2026-10-01 00:00:00-05:00"},"count":{"type":"integer","title":"Count"},"next_seq":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Next Seq","description":"Pass as after_seq to read the next page. Null on the last page. seq is strictly increasing, so rows that share changed_at are not repeated."},"next_since":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Since","description":"Deprecated. The last changed_at on this page, kept for one release. Rows that share a timestamp can repeat if you page with it. Use next_seq."},"data":{"items":{"$ref":"#/components/schemas/Change"},"type":"array","title":"Data"}},"type":"object","required":["since","count","data"],"title":"ChangePage"},"ErrorResponse":{"properties":{"detail":{"anyOf":[{"type":"string"},{"additionalProperties":true,"type":"object"}],"title":"Detail"}},"type":"object","required":["detail"],"title":"ErrorResponse","description":"401 and 404 use a string detail. 403 and 429 use an object detail.","examples":[{"detail":"Missing credentials: use a marketplace subscription or an X-API-Key header"},{"detail":"Invalid API key"},{"detail":"Recall not found"},{"detail":{"error":"plan_upgrade_required","message":"The changes feed requires the Pro or Business plan","pricing":"Free: last 12 months · Basic $25: full history · Pro $75: changes feed + bulk · Business $150: commercial"}},{"detail":{"error":"quota_exceeded","message":"Monthly quota of 100 calls for the free plan is used up","reset":1767225600}},{"detail":{"error":"rate_limited","message":"Rate limit of 1 requests/second for the free plan exceeded","reset":1762000001}}]},"Health":{"properties":{"status":{"type":"string","title":"Status"},"version":{"type":"string","title":"Version"},"records":{"type":"integer","title":"Records"},"last_ingest":{"items":{"$ref":"#/components/schemas/IngestRun"},"type":"array","title":"Last Ingest"},"time":{"type":"string","title":"Time"}},"type":"object","required":["status","version","records","last_ingest","time"],"title":"Health","examples":[{"last_ingest":[{"last_success":"2026-11-02T14:50:47+00:00","source":"FDA"}],"records":1319,"status":"ok","time":"2026-11-02T18:00:00+00:00","version":"2.0.0"}]},"IngestRun":{"properties":{"source":{"type":"string","title":"Source"},"last_success":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Success"}},"type":"object","required":["source"],"title":"IngestRun"},"Location":{"properties":{"city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"City"},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"country":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country"}},"type":"object","title":"Location"},"Page":{"properties":{"total":{"type":"integer","title":"Total"},"limit":{"type":"integer","title":"Limit"},"offset":{"type":"integer","title":"Offset"},"plan":{"type":"string","title":"Plan"},"history_from":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"History From","description":"Earliest report_date this plan may read. Null when the plan has full history."},"warnings":{"items":{"type":"string"},"type":"array","title":"Warnings","description":"Set when a requested date filter was clamped to history_from. Empty when nothing was clamped."},"data":{"items":{"$ref":"#/components/schemas/Recall"},"type":"array","title":"Data"},"disclaimer":{"type":"string","title":"Disclaimer"}},"type":"object","required":["total","limit","offset","plan","data","disclaimer"],"title":"Page"},"Recall":{"properties":{"id":{"type":"string","title":"Id","description":"Stable id. fda-{recall_number} when FDA assigned one; otherwise fda-event-{event_id}-{hash}. Legacy rows may still be fda-{event_id} (for example fda-99833) until a recall number is merged onto that same id. FSIS ids are fsis-{recall_number}."},"source":{"type":"string","title":"Source","description":"Issuing agency: FDA or USDA-FSIS.","examples":["FDA"]},"source_url":{"type":"string","title":"Source Url","description":"HTTPS link to the source record or the official notice."},"retrieved_at":{"type":"string","title":"Retrieved At","description":"When this record was first fetched from the source. ISO-8601 UTC (YYYY-MM-DDTHH:MM:SS+00:00)."},"last_verified_at":{"type":"string","title":"Last Verified At","description":"When an ingest run last observed this record at the source and the stored payload matched that observation. ISO-8601 UTC. Advances on an unchanged re-fetch and when a new snapshot is stored. Does not move between ingests."},"recall_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Recall Number","description":"Official recall number when the source has assigned one. Null until then; the id does not change when it appears."},"event_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Event Id","description":"Source event or notice id (FDA event_id, FSIS node id)."},"recall_initiation_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Recall Initiation Date"},"report_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Report Date"},"classification_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Classification Date"},"termination_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Termination Date"},"firm":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Firm"},"brand":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Brand","description":"Best-effort brand parsed from the product description. Null when the notice does not name one. Not a guaranteed trade name."},"product_description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Product Description"},"product_category":{"type":"string","title":"Product Category"},"allergens":{"items":{"type":"string"},"type":"array","title":"Allergens"},"classification":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Classification","description":"Class I, Class II, or Class III when the source classified the recall."},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"},"voluntary_mandated":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Voluntary Mandated"},"distribution_pattern":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Distribution Pattern"},"distribution_states":{"items":{"type":"string"},"type":"array","title":"Distribution States"},"distribution_countries":{"items":{"type":"string"},"type":"array","title":"Distribution Countries"},"firm_location":{"anyOf":[{"$ref":"#/components/schemas/Location"},{"type":"null"}]},"product_quantity":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Product Quantity"},"code_info":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Code Info"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"},"recall_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Recall Type","description":"FDA: Voluntary or Mandated, from voluntary_mandated. FSIS: the notice type (Active Recall, Public Health Alert, …)."},"risk_level":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Risk Level","description":"Source risk string when present (FSIS). Otherwise High, Medium, or Low from Class I / II / III."},"last_updated":{"type":"string","title":"Last Updated"}},"type":"object","required":["id","source","source_url","retrieved_at","last_verified_at","product_category","allergens","distribution_states","distribution_countries","last_updated"],"title":"Recall"},"Stats":{"properties":{"total":{"type":"integer","title":"Total"},"by_source":{"additionalProperties":true,"type":"object","title":"By Source"},"by_classification":{"additionalProperties":true,"type":"object","title":"By Classification"},"by_status":{"additionalProperties":true,"type":"object","title":"By Status"},"by_category":{"additionalProperties":true,"type":"object","title":"By Category"},"by_allergen":{"additionalProperties":true,"type":"object","title":"By Allergen"},"top_states":{"additionalProperties":true,"type":"object","title":"Top States"},"last_30_days":{"type":"integer","title":"Last 30 Days"},"date_range":{"additionalProperties":true,"type":"object","title":"Date Range"}},"type":"object","required":["total","by_source","by_classification","by_status","by_category","by_allergen","top_states","last_30_days","date_range"],"title":"Stats"},"ValidationErrorResponse":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationIssue"},"type":"array","title":"Detail"}},"type":"object","required":["detail"],"title":"ValidationErrorResponse","examples":[{"detail":[{"input":"Foo","loc":["query","status"],"msg":"Value error, Invalid status 'Foo'. Allowed: Ongoing, Completed, Terminated","type":"value_error"}]}]},"ValidationIssue":{"properties":{"type":{"type":"string","title":"Type"},"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Loc"},"msg":{"type":"string","title":"Msg"},"input":{"anyOf":[{},{"type":"null"}],"title":"Input"}},"type":"object","required":["type","loc","msg"],"title":"ValidationIssue"}},"securitySchemes":{"RapidAPIKey":{"type":"apiKey","in":"header","name":"X-RapidAPI-Key","description":"RapidAPI subscription key. Callers send it to the RapidAPI gateway. The origin instead checks the gateway's X-RapidAPI-Proxy-Secret and maps X-RapidAPI-Subscription to a plan."},"ApiKey":{"type":"apiKey","in":"header","name":"X-API-Key","description":"Direct Wryborg key (API_KEYS or API_KEYS_FILE). Enforced on this server: a per-second rate limit (free 1, basic 5, pro 10, business 25) and a monthly quota (free 100, basic 10000, pro 50000, business 200000). A leaked key can be called from a server; browser calls are limited to the CORS allowlist and are not paired with a wildcard origin. This path does not go through marketplace billing."}}},"tags":[{"name":"meta","description":"Liveness. GET /health does not require a key."},{"name":"recalls","description":"Search and fetch normalized FDA and USDA FSIS recalls."},{"name":"changes","description":"Incremental change feed. Requires the Pro or Business plan."},{"name":"reference","description":"Allergen codes and corpus statistics."}],"security":[{"RapidAPIKey":[]},{"ApiKey":[]}]}