Most prospecting automations die in week three. Not because the idea was wrong, but because nobody planned for the second run. The first execution is a demo: you press play, watch the nodes light up green, and feel like a wizard. The second run hits a rate limit, re-processes the same four hundred domains you already emailed, and quietly writes duplicates into your CRM. What follows is the structure that survives contact with a real pipeline — four n8n workflows, each with exactly one job, wired together through a table instead of through hope.
Split it into four workflows, not one giant canvas
The most common n8n mistake in prospecting is building one enormous canvas that harvests, enriches, scores, writes copy and pushes to a sequencer. It works once. Then a node fails at step fourteen and you have no idea which of the nine hundred items already made it through. Split the machine into four: a harvester that only produces domains, an enricher that only fills in detail, a scorer that only ranks, and a drafter that only writes. Each one reads from and writes to the same table.
That table is the contract between them. Postgres, Airtable, Baserow, even a spreadsheet at low volume — the storage barely matters, as long as the domain is the primary key and every row carries a status column. Harvested. Enriched. Scored. Drafted. Queued. Sent. Replied. Every workflow selects rows in one state and advances them to the next. If a run explodes halfway, the rows that made it are already advanced and the rest get picked up tomorrow with no manual cleanup.

It is also what makes the whole thing explainable. When a client asks why a particular store received a particular email, you have a row with a timestamp on every transition and the raw payload that produced the copy. Try answering that question from a forty-node canvas with no persistence and you will understand why this split is worth the extra hour.
Workflow one: the harvester
Start with a Schedule Trigger at an unglamorous hour, then a Set node that holds the filter. Keep the filter in one place — you will edit it weekly, and scattering it across five HTTP nodes guarantees that two of them drift. A typical filter for an agency selling conversion work: platform Shopify, countries France and Belgium, product count above forty, monthly traffic between three thousand and sixty thousand. An HTTP Request node then calls /v1/stores/search with those parameters and your API key in a header.
Before you paginate, count. Fire one request with the same filter and read the total. If the number comes back as twelve, or as four hundred thousand, something is wrong with your filter and you want to know that before you burn a night of API calls. Route the count through an IF node: below a floor, stop and message yourself; above a ceiling, stop and tighten. Only the middle band continues. This single node has saved more quota than every other optimisation combined.

Pagination in n8n is a loop, and the cleanest version uses a Code node to hold the cursor plus a Loop Over Items node feeding pages back into the HTTP Request. Cap it hard — twenty pages per night keeps a runaway filter from eating a month of quota at three in the morning. Write every returned domain into the table with an upsert on the domain column, so re-running the harvester is always harmless.
Workflow two: the enricher
The harvester gives you domains and a shallow record. The enricher goes deep only on the rows you actually intend to contact, because depth costs calls and you should not pay for depth on stores you will never open. Select rows in the harvested state, cap the batch at a few hundred, and run three calls per domain: /v1/stores/:domain for the full record, /v1/stores/:domain/catalog for the products, and /v1/stores/:domain/trend for the monthly history.
That third call is the one people skip and it is the most valuable. The trend endpoint returns roughly 170 monthly buckets of organic traffic and organic positions. A Code node that compares the last three months against the same window a year earlier turns a static row into a story: this store is up forty percent, that one has been sliding for five straight months. The direction of the curve is the pitch. Everything else is context.
Use Loop Over Items with a batch size of ten and a Wait node of a second between batches — not because you will be throttled, but because it makes executions readable and retries cheap. Set every HTTP node to retry on fail, three attempts, and route the continue-on-fail output to a branch that marks the row as failed rather than killing the run. One unreachable domain should never cost you the other two hundred.
Workflow three: scoring, in code, in one place
Scoring belongs in a single Code node with the weights declared at the top as plain numbers you can explain to a client out loud. A workable set: platform match, catalog size band, traffic band, whether a Google Business profile exists at all, review count and rating, whether AI-visibility mentions exist, and trend direction. Each contributes a bounded number of points. Total it, clamp it to a hundred, write it back to the row along with the individual components so you can debug a weird score later.
Two hard filters run before the score, not after. First, exclusion: drop anything already in your CRM, anything on a suppression list, anything contacted in the last ninety days. Second, contactability: no reachable contact email, no row. Scoring an unreachable lead is a way of feeling productive while accomplishing nothing, and it inflates every dashboard you build on top.
A Switch node then splits the output three ways. High scores go to a manual queue that a human reads before anything moves. Mid scores go to the drafting workflow. Low scores go to a nurture table you re-score next quarter — a store doing two thousand visits this month may be doing twenty thousand in six, and because the trend data is already there, re-scoring costs one call instead of a fresh discovery run.
Workflow four: drafting with an evidence contract
The drafting workflow takes one enriched row and produces one email. It uses an LLM node, but the interesting part is not the model — it is the contract you impose on it. The system prompt receives the store record as structured data and one rule above all others: every factual statement in the email must be traceable to a named field, and if the field is empty the sentence does not get written at all.
In practice the model returns two things: the email, and a short list of the fields it used. A Code node downstream verifies that each cited field is actually present and non-empty in the source row. If the model claims the store sells skincare and the category is blank, the draft is rejected and the row goes back to the queue. This one check removes the vast majority of the confident nonsense that makes automated outreach embarrassing, and it costs about fifteen lines of JavaScript.

Keep the copy short and let the data carry it. One specific observation, one implication, one artifact, one low-friction ask. The artifact is the real differentiator: a one-page audit of their Google Business profile, a rewritten product page, a chart of their organic curve over the last three years. Generating it is another branch of the same workflow, and it is the reason anyone replies to a stranger.
Error handling is the actual product
Set an error workflow at the instance level and point every prospecting workflow at it. It should do three things: write the failed execution id and node name to a table, post one message to a channel you genuinely read, and — this matters — not retry automatically. Automatic retries on a failed enrichment run are how operators discover on Monday that they consumed a month of quota over the weekend.
Idempotency is the other half. Every write is an upsert keyed on domain. Every send is gated by a sent-at timestamp. Every workflow starts by selecting only rows in the state it owns. Do those three things and you can re-run anything at any time without fear, which is the only condition under which you will actually maintain the system six months from now.
Finally, log the shape of the data, not only the failures. A weekly summary reporting how many rows entered each state, the median score, and the share of drafts rejected by the evidence check will tell you a filter has gone stale weeks before your reply rate does. Silent degradation is the real risk in automation; loud errors are the easy case.
The MCP shortcut for the parts you have not built yet
n8n ships an MCP Client node, and an MCP server is included on every plan, which means you can point an agent at the same data your workflows use before writing a single HTTP node. It is the fastest way to explore: ask in plain language which platforms dominate a given country, how many stores match a draft filter, what one specific store actually looks like. When an exploration turns into something you want to run nightly, port it to explicit HTTP nodes — deterministic beats clever for anything on a cron trigger.
The division of labour that holds up: agents for discovery and for writing, plain nodes for anything scheduled. Discovery is ambiguous and benefits enormously from a model that can ask a better second question. A nightly harvest is not ambiguous, and benefits from being boring, repeatable and cheap.
What to keep manual
Sending. Every operator who runs this at volume arrives at the same place: the machine builds the list, enriches it, scores it and writes the draft, and a human presses the button. Not only for legal caution, though that exists — because the person reading fifty drafts a morning is the fastest feedback loop you will ever have on your filter, your offer and your copy. Automate the research, keep the judgement.
Start with one segment. One platform, one country, one offer. Get all four workflows running end to end on two hundred stores before you point them at thousands. The data is not going anywhere — 153,515 verified stores across 60 platforms will still be there next month, and the constraint was never supply. It was always whether your pipeline still runs on day thirty.
