---
title: "The recall watcher: about ninety alerts a week, and the one that names your shelf"
subtitle: "The official alert lists land in a mailbox nobody reads, get matched against what you actually stock, and what reaches your phone is a pull-list and the customers who bought it - not another digest to skim"
url: "https://rxed.ai/blueprints/product-recall-watcher.html"
id: "product-recall-watcher"
version: "1.0"
published: "2026-08-27"
kind: "workflow"
setup_effort: "A weekend"
setup_hours: "6-14"
running_cost_usd_per_month: "0-12"
paid_software_usd_per_month: "0"
time_saved: "not a weekly time saving - it is the difference between finding a recall in a feed and hearing about it from a customer or an inspector"
time_saved_basis: "on a normal week this saves nothing, because the alternative is not doing it; the case is Article 12 of the GPSR, which since 13/12/2024 obliges a distributor who has reason to believe a product it sold is dangerous to act, and an alert published under the brand and model you stocked is exactly that reason"
runs_by: "owner"
data_location: "your-server"
data_location_note: "Your stock list, your sales lookups and the alert register stay on your own server, and the screening model runs locally so no product list is sent anywhere. The only traffic leaving the building is fetching public alert data from the Commission, CPSC and openFDA."
first_to_break: "the Safety Gate subscription quietly stops arriving - the address bounces once, a filter reclassifies it, or the subscription lapses - and the watcher keeps running happily against an empty mailbox"
failure_signal: "silent"
problem: "Thousands of dangerous products are flagged across Europe every year, and nobody in your shop has time to read the weekly list. You find out that something you sold was recalled when a customer tells you, or when an inspector does."
fix: "The official alert lists arrive in a mailbox nobody reads, and get checked automatically against the products you actually stock. When one of them is yours, you get a message on your phone with what to take off the shelf and who bought it."
tools: ["n8n", "NocoDB", "Baserow", "Ollama", "ntfy", "Gotenberg", "Docker"]
tech: ["n8n", "NocoDB", "Ollama", "ntfy", "Gotenberg", "Docker"]
repos:
  - name: "n8n"
    url: "https://github.com/n8n-io/n8n"
  - name: "NocoDB"
    url: "https://github.com/nocodb/nocodb"
  - name: "Baserow"
    url: "https://github.com/baserow/baserow"
  - name: "Ollama"
    url: "https://github.com/ollama/ollama"
  - name: "ntfy"
    url: "https://github.com/binwiederhier/ntfy"
  - name: "Gotenberg"
    url: "https://github.com/gotenberg/gotenberg"
categories: ["Self-hosted", "n8n", "Local AI", "Email", "Reporting"]
source: "RXed AI News — https://rxed.ai"
---
# The recall watcher: about ninety alerts a week, and the one that names your shelf

> The official alert lists land in a mailbox nobody reads, get matched against what you actually stock, and what reaches your phone is a pull-list and the customers who bought it - not another digest to skim

## Before you start

- A current list of what you stock - brand, product name, model, barcode where you have it, and the supplier it came from. This is the weekend, and without it there is nothing to match against
- A dedicated mailbox that nobody reads, subscribed to the official Safety Gate weekly alert email and filtered to your product categories
- Sales records you can query by product and date range, so a hit can produce a customer list rather than a guess
- A machine that stays switched on - a small VPS runs the watcher, but not a language model, so the optional screening step needs an office machine or gets dropped
- A named person who reads the flagged alert and decides. Nothing here contacts a customer or an authority by itself

## What breaks first

the Safety Gate subscription quietly stops arriving - the address bounces once, a filter reclassifies it, or the subscription lapses - and the watcher keeps running happily against an empty mailbox. Silence is the normal output of this system, so a broken feed looks exactly like a good week. Add a staleness check that alerts you when no alert of any kind has been ingested for eight days, and make that check the one thing you never switch off.

The EU published 4,671 dangerous-product alerts in 2025, about ninety a week, and almost none of them are yours. The job is not reading them. The job is the filter that says "this one names something on your shelf", and the lookup that says "and these eleven people bought it".

 

### The problem

 Start with the volume, because it is the whole reason nobody does this by hand. The Commission's Safety Gate report for 2025 recorded 4,671 alerts — the highest since the system started in 2003, up 13% on 2024 and more than double 2022, running at close to 100 notifications a week . National authorities took 5,794 follow-up actions on top. Cosmetics were the most-notified category at 36% , then toys at 16% and electrical appliances at 11% . Chemical risk drove 53% of all alerts, including 1,278 notifications for the fragrance BMHCA and 60 for TPO in nail polish since it was banned in September 2025.

 Read those three categories again if you run a salon, a gift shop or an electrical installation business. This is not an importer's problem. Cosmetics on a salon shelf, a toy on a counter display, a charger fitted last spring — that is where a third of the alerts land.

 And since 13 December 2024 the obligation is explicit. Under Article 12 of the GPSR (Regulation (EU) 2023/988), a distributor — which is what a shop that buys from a wholesaler is — who has reason to believe a product it has made available is dangerous must immediately inform the manufacturer or importer, ensure corrective measures are taken including withdrawal or recall, and inform the market surveillance authorities through the Safety Business Gateway. "Reason to believe" is doing a lot of work in that sentence. An alert was published. It named the brand and the model. Nobody in your shop read it.

 Then Article 35 turns the sales record into a legal instrument. In a recall you must directly notify every affected consumer you can identify, without undue delay, using the personal data you already hold . Not a website banner. Not a post. If you have their email because they bought it, you owe them an email. Article 35(2) goes further and says you must offer customers the option to register contact details used for safety purposes only. Article 35(4) covers the rest with website, social, newsletter, in-store and media notices.

 Article 36 then tells you how to write it, and Implementing Regulation (EU) 2024/1435 gives the template that has applied since the same December date. The notice must be in plain language and must not use wording that softens the risk — "voluntary", "precautionary", "discretionary", "in rare situations", or any statement that no accidents have been reported. Article 37 prices it: the consumer gets a choice of at least two of repair, replacement or a refund of at least the price paid, free of charge, offered proactively, with no time limit for claiming. The EU's own rationale for all of this is blunt — roughly one in three consumers keeps using a recalled product after seeing the notice, because the notice was written to be survivable rather than clear.

 So the shape of the work is: watch about ninety alerts a week, throw away eighty-nine, and on the ninetieth produce a shelf action, a customer list and a compliant notice. That is a filter and a database query. It is not a subscription.

 

### The architecture

 
 THE FEEDS — official, and deliberately boring 
 [ Safety Gate weekly email ] → dedicated mailbox (filtered to your categories at source) 
 [ CPSC Recalls API ] → saferproducts.gov/RestWebServices/Recall (US, no key) 
 [ openFDA enforcement ] → api.fda.gov/food/enforcement.json (US, backstop only) 
         ▼ 
 [ n8n — the sorter ] IMAP trigger + daily schedule 
         ├─ 1. exact match: barcode / GTIN, when the alert carries one 
         ├─ 2. exact match: brand, model, supplier — against NocoDB "what we stock" 
         └─ 3. the rest → Ollama : "could this be one of ours?" ranks, never decides 
         ▼ 
         ├─ no hit → one row in the register, and silence. This is the normal week. 
         └─ possible hit → ntfy on your phone, with the alert and the reason 
 
 THE HIT — a handful of times a year, if that 
 [ you confirm it is yours ] 
         ├─ pull-list: where it is, how many, which batch codes 
         ├─ customer list: query sales for that product and date range 
         ├─ notice: 2024/1435 template → Gotenberg → PDF, banned-word check first 
         └─ register row: what you found, when, what you did, who you told 
         ▼ 
 [ you ] send the notice, inform the supplier, notify through the Safety Business Gateway. 
 Nothing is sent to a customer or an authority automatically. 
 

 The load-bearing decision is the first line. Safety Gate has no documented public API and no RSS feed, but it does have an official weekly email subscription that you can filter by product category, notifying country and country of origin. So the automation subscribes a dedicated mailbox and parses email. That sounds like the crude option and it is the durable one: the portal is an Angular app over an internal endpoint that owes you nothing, while the subscription is a service the Commission runs on purpose. Scrape the portal and you are one redeploy away from a watcher that silently stops watching.

 The second decision is that the "what we stock" table is the actual product. Everything else here is plumbing you could rebuild in a day. A current list of brands, models, barcodes and suppliers is the thing that takes a weekend and then takes ten minutes a month forever, and without it there is nothing to match against.

 

### Tool choices — and why

 n8n (Sustainable Use License, free for internal business use, 202k stars, last commit 27/08/2026) does the fetching, the matching and the alerting. It has an IMAP trigger for the Safety Gate mail, HTTP nodes for the two US APIs, and a schedule that will retry when a feed is down. If you already run it for another blueprint here, this is one more workflow, not one more machine.

 NocoDB (Sustainable Use License since 29/01/2026, free for internal business use, 65k stars, last commit 27/08/2026) holds two tables: what you stock, and the alert register. Spreadsheet-shaped is right because a shop owner has to maintain the first one by hand and read the second one under pressure. Baserow (5.6k stars, actively developed) is the swap if you prefer its licence.

 Ollama (MIT, 180k stars, last commit 22/08/2026) runs the screening model locally for the alerts that did not match exactly — "SUNTECH beach umbrella, model BX-40, plastic pole" against a stock list that says "Suntec parasol 2m". A small model is fine here because the question is a similarity judgement, not a legal one. It costs nothing per alert and no product list leaves your building. This step is optional: drop it and you still have a working exact-match watcher, you just read a few more borderline alerts yourself.

 ntfy (Apache-2.0, 30.5k stars, pushed 30/05/2026) puts the hit on your phone. Email is the wrong channel for this because the whole failure mode is a message that gets skimmed and archived, and you already have a mailbox filling up with weekly alert digests.

 Gotenberg (MIT, last commit 21/08/2026) turns the filled template into the PDF you hand to customers and attach to the register. Docker runs all of it on one box.

 Monthly cost. Software: €0 , every piece. Feeds: €0 — Safety Gate's subscription is free, CPSC's Recalls API needs no key, and openFDA is free keyless at 240 requests a minute and 1,000 a day per IP address, or 120,000 a day with a free key. Hosting: nothing new if you already run an automation box, otherwise roughly €5–12/month for a small VPS. One honest caveat on that number: a €5 VPS will not run a language model usefully. Either run Ollama on an office machine that is already switched on, or skip the model step. Commercial recall-monitoring services start in the hundreds per month and are sold to compliance teams, not to shops with four hundred product lines.

 

### Setup outline

 1. Build the stock list first, before any automation. Brand, product name, model, barcode where you have it, supplier, and the categories you actually sell. Four hundred rows is a Saturday. Without this the rest is decoration. 
 2. Create a dedicated mailbox — alerts@ — that nobody reads. It exists to be parsed. 
 3. Subscribe it on the Safety Gate portal and use the filters: your product categories, and country of origin if that narrows things honestly. Confirm the activation link. Wait a week and check the first mail actually arrived before building anything on top of it. 
 4. Add the national feed for your own country. Every member state publishes its own recall page, and it lands earlier and in your language. 
 5. Wire the IMAP trigger in n8n, parse the mail into one record per alert — case number, product, brand, model, barcode, category, risk, measures, notifying country — and store every one of them, matched or not. The register is the point. 
 6. Add the US feeds if you sell there: GET saferproducts.gov/RestWebServices/Recall?format=json&RecallDateStart=… daily, and openFDA if you handle food. 
 7. Match in that order: barcode, then brand plus model, then supplier name. Normalise both sides first — case, punctuation, accents, and the spaces people put in model numbers. 
 8. Send the leftovers to the local model with the stock list in the prompt, and ask for a score and one sentence of reasoning. Store the reasoning. You will want to know why it flagged something at 2am six months from now. 
 9. Alert to ntfy with the case number, the product, the risk and the reason. One message, not a digest. 
 10. Build the response side only once the watching side has run quietly for a month: the sales query, the 2024/1435 notice template with the banned-word check, and the register fields for what you did and who you told. 
 11. Test it against a real past alert. Pick something you genuinely stocked last year from the Safety Gate archive, feed it in, and see whether your own filter catches it.

 

### Pitfalls — the real ones

 The alert names the manufacturer, and you know the wholesaler. This is the failure that matters. Safety Gate records the brand and model as the notifying authority found them, which is often a factory brand you have never typed into anything. Barcode is the only reliable key, and it is only sometimes present — CPSC's own field list says UPC is included "when provided in a recall". So keep the supplier against every stock line as a third matching key, and accept that this filter is tuned to over-flag. A false alarm costs you two minutes. The other kind of miss is the one that ends up in front of a market surveillance authority. 
 openFDA enforcement is an archive, not an alarm. Checked live on 27/08/2026, the endpoint held 43 food enforcement reports with an August report date, and the first one was recall H-1219-2026: initiated 4 June 2026 , reported 12 August 2026 . That is 69 days. The dataset's own last_updated was 19 August. It is a good backstop and a useless siren, so treat the FDA and CPSC press pages as the fast signal and the API as the record. 
 RASFF will not do what you want for food. The RASFF Window is public, but the Commission states plainly that its notifications "do not reveal commercial details such as brands and business operators". You cannot brand-match against it. For food the usable routes are the RASFF consumers' portal, which carries actual recall notices, and your national food authority. Build the food watcher on those, and do not pretend the EU has one clean food feed, because it does not. 
 The model must never be the last word. It ranks, you decide. Ask it for a score and a reason, show both, and make confirming a hit a deliberate tap. And tune it towards noise: in this workflow a false positive is an inconvenience and a false negative is the actual hazard. 
 An LLM will write a notice that breaks Article 36 on the first try. "We are issuing a voluntary precautionary recall. No incidents have been reported." Every clause in that sentence is prohibited wording. Run a literal banned-word check over the draft before it can be exported — voluntary, precautionary, discretionary, "in rare cases", "no accidents reported" — and fail the export rather than warning about it. 
 You are about to use the customer database for something the customer never asked for, and that is the correct behaviour here. Article 35(1) requires you to use the personal data you hold to notify affected consumers. What it does not do is licence a marketing send. Keep the safety contact list separate, write down that its purpose is recall notification, and offer the safety-only contact option Article 35(2) asks for rather than bolting a consent checkbox onto your newsletter. 
 The register is the deliverable, not the alert. The Commission's business guidelines ask you to keep an internal register of consumer complaints, recalls and corrective measures. Store every alert you screened, including the thousands you dismissed, with the reason. "We check the EU alerts weekly" is a claim. A table with 4,671 rows and a decision on each is evidence. 
 This is not the expiry tracker and it is not the goods-in check. Those watch your own dates and your own deliveries. This one watches what the rest of the market found out about a product you already sold.

 

### Verified repos

 
 [n8n](https://github.com/n8n-io/n8n) — Sustainable Use License (free self-hosted internal use), 202k stars, last commit 27/08/2026 
 [NocoDB](https://github.com/nocodb/nocodb) — Sustainable Use License since 29/01/2026 (free for internal business use), 65k stars, last commit 27/08/2026 
 [Baserow](https://github.com/baserow/baserow) — open-source core with a paid edition, 5.6k stars, actively developed — alternative to NocoDB 
 [Ollama](https://github.com/ollama/ollama) — MIT, 180k stars, last commit 22/08/2026 
 [ntfy](https://github.com/binwiederhier/ntfy) — Apache-2.0, 30.5k stars, pushed 30/05/2026 
 [Gotenberg](https://github.com/gotenberg/gotenberg) — MIT, last commit 21/08/2026
 

 
 Get the next blueprint as it publishes — free, practical, verified tooling only.

 [Subscribe](https://subscribe.rxed.ai) · Want this audited or extended for your business? DM [@RXed_EU](https://x.com/RXed_EU)
