Signup enrichment pipeline

Automatically research every new and abandoned signup, turn what's public about their practice into structured data, and land it in Customer.io and Pipedrive. Runs on its own metered infra, not the Claude subscription.

Build Quim (1–2 wk sprint, agreed 24 Jul) Spec & consumers Carlos Volume ~10k/mo (~300 signups + ~10 dropoffs/day) Plan date 27 Jul 2026

Why this, why now

from the 21–24 Jul huddles + 23 Jul pilot
29%
of completed owner signups have no phone. Sales works ~35 of ~52 US signups/day
~55%
of genuine US signups are findable online (own site ~36%, directory-only ~19%) pilot, n=63
~17%
of raw US signups are junk or scam clusters inflating every sales count

Jamie's sequence, agreed 23 Jul: enrichment → scraping → Tron. Enrichment is the standalone first piece because it feeds everything else: sales gets phones back, lifecycle gets the attributes the v4 signup cut (specialty, platform, insurance), and the AI onboarding agent later consumes the same enrichment docs. Jamie hypothesises 80–90% of practitioners have some online presence once directories count; the pilot's 55% is a floor from shallow searches.

v4 signup (12 Jun) killed currentSetupPlatform, so website scanning is now the only switcher detection we have. Enrichment recovers that without re-adding signup friction.

What 100 raw US signups become pilot estimates, ±10–15pts
Where enrichment can act, per the 23 Jul coverage pilot
~30 own website → full extraction ~16 directory-only → partial ~12 ambiguous → review band ~25 invisible → real answer, feeds the profile bet ~17 junk → gated, saves sales time
So enrichment fully or partially works ~46 of every 100 raw signups today, cleans 17, and honestly reports the rest. Deeper search (address signals, aliases) should push the findable share up; Jamie's hypothesis is 80–90% have some presence.

The pipeline

tap a stage to expand
0
Trigger: new signup or abandoned signup
Reuses plumbing that is already live
free

New signups: a CIO webhook action fires on signup completion (same pattern as the live Dropoff → Pipedrive chain) and POSTs the profile to the pipeline's webhook with email, name, phone, profession, provider_name, team_size, country.

Abandoned signups: campaign 86's 60-minute gate already separates genuine dropoffs from mid-flow completers (88% of entrants exit within the hour). Add one webhook action after the existing gate; no new logic needed. Post-Quim wizard identifies mean many dropoffs already carry name, phone and profession.

Key on the CIO profile id, not email alone: a known class of dropoffs (~3 in 10 early post-release) has no email at all.
1
Junk and fraud gate
Kill scam clusters before spending a cent on them
free
  • Disposable email check against the open-source blocklist (8,179 domains, CC0, actively maintained). verified
  • Shared-phone clustering: flag any phone already seen on 2+ accounts (the pilot's scam clusters shared single numbers across 4+ accounts).
  • Name heuristics: gibberish, brand-impersonation strings ("Norton", "McAfee" patterns), internal test domains.

Output: junk_score written back to CIO and Pipedrive. Junk-flagged profiles skip enrichment, drop out of SDR lists, and stop inflating the effective-signups number Jamie quotes.

Gap to accept: the free list can't catch alias services (iCloud Hide My Email, DuckDuckGo). Optional paid verification (Bouncer ~$60/10k, ZeroBounce $99/mo) only if bounce data says we need it.
2
Email domain resolution
The best signal is free and already in the payload
free

If the signup email is on a custom (non-freemail) domain, that domain is the practice website with zero ambiguity. In the pilot this was 21% of signups and caught 5 practices that name search missed. Resolve first, always.

Freemail was 67% of the pilot (Gmail ~59%). For those, fall through to stages 3–4.
3
NPI registry lookup
Free federal identity anchor for US practitioners
free

NPPES API (npiregistry.cms.hhs.gov/api, version=2.1, no key) returns taxonomy, practice address, phone and org affiliations. Name matching is exact-field, so treat a hit as a strong identity anchor and a miss as meaningless. verified live

  • Query last name + first name + state (phone area code gives a state guess when signup has no address).
  • Match taxonomy against signup profession: counselor 101Y*, MFT 106H*, LCSW 1041C0700X, psychologist 103T*, dietitian 133V*, PT 2251*, OT 225X*, SLP 235Z*.
  • NPI address + phone become extra identity signals for stage 5's match confidence.
Better at volume: download the free monthly bulk file (~1.1 GB, weekly 6–16 MB deltas) and match locally. The live API has an undocumented pagination ceiling at skip=1000 and community-reported throttling.
4
Web search: find the website and profiles
Name + profession + location across search and directories
~$10/mo

Search API query: provider/practice name + profession + state. Classify results into: own website, directory profile (Psychology Today, Tebra, Headway, Yelp, Fresha), social-only, or not found.

  • Recommended: DataForSEO SERP ($0.60/1k queries standard queue ≈ $6/mo) or Serper.dev (~$0.50/1k). Serper pricing secondhand
  • Avoid Google Places API for this: its TOS prohibits storing business names, addresses, phones or website fields in a CRM (only place IDs are exempt), and the compliant tiers cost ~$405/mo anyway. TOS blocker, verified
Directory profiles are first-class results, not failures (~19% of signups are directory-only), but don't scrape the directories themselves: Psychology Today, Tebra and Yelp block scrapers and prohibit it in their terms. Store the listing URL as evidence and extract what the search snippet and the practitioner's own site give.
5
Scrape and extract with an LLM
Fetch cheap, extract into one fixed schema
~$25–160/mo

Fetch up to ~3 pages per lead (home, about, services) with Jina Reader (~$1–5/mo at 30k pages) or Exa contents ($1/1k pages). Skip Firecrawl's AI Extract: 9–10 credits/page (~$333/mo) buys a black box, and it benchmarks worst-in-class on bot-protected sites. Keep Bright Data as fallback for the rare protected site.

Extract deterministically first: address, socials, logo and platform detection come from parsing, not prompting. Platform detection is a signature registry of booking-embed markup (SimplePractice, TherapyNotes, Jane, Tebra, IntakeQ, Healthie, Acuity, Calendly, doxy.me). The LLM handles only the semantic fields, against a fixed JSON schema, and must return null when the evidence is missing:

website · phone · specialty_detail · services[] · address/state · accepting_insurance · current_platform (booking-embed detection: SimplePractice, Jane, Healthie, Acuity, Calendly…) · socials · brand_assets (logo URL, palette) · team_size_signal

Model (deep-dive 27 Jul, incl. Chinese open-weight and new Google models): the entire field costs $12–150/mo at this volume, so pick on accuracy and risk, not price. Two findings shape the choice: producing valid JSON is a solved problem (>0.95 across models), but value accuracy tops out around 0.83, so the failure mode is well-formed JSON with a wrong specialty, and the eval must measure field correctness against a golden set, not parse success.

Model$/MTok in·outEst./moRole
Gemini 3.5 Flash-Lite on Vertex AI (new, 21 Jul)$0.30 · $2.50$55 (≈$27.50 batched)Primary: Google built it for "classification, extraction, routing"; constrained decoding via responseSchema; Vertex gives residency + VPC-SC
Claude Haiku 4.5$1 · $5$150 (≈$75 batched)Fallback: equally guaranteed schemas, fails independently of Google; keep wired up as a real second lane
DeepSeek V4 Flash (DeepInfra, US)$0.10 · $0.20$12Shadow lane: run in parallel, measure agreement, free regression signal
GLM-5 (US-hosted)$0.60 · $1.92$79Accuracy escalation: GLM-4.7 leads the structured-output benchmark (0.830) extrapolated
Gemini 3.6 Flash (new, 21 Jul)$1.50 · $7.50$225Skip: genuinely better at coding/long-context, which this task doesn't use; 4× Flash-Lite
Kimi K3 (16 Jul launch)$3 · $15$450Skip: frontier model at frontier price for a task that needs neither; capacity-constrained

Why Flash-Lite over Haiku: both now offer real constrained decoding (not prompt-and-hope), and Vertex AI matches Anthropic on governance (residency, VPC-SC, CMEK), so the tie-breakers are fit and throughput: Flash-Lite is Google's designated extraction tier at ~490 tok/s and 2.1× cheaper. Caveat: no published head-to-head value-accuracy benchmark exists for this exact task; that's what the golden set settles, and it's why Haiku stays a wired fallback rather than theoretical.

Two integration gotchas: Gemini's responseSchema is an OpenAPI 3.0 subset, not full JSON Schema. Our flat schema (enums + string arrays) should translate cleanly, but Quim should validate it in hour one, and the Anthropic/Google lanes need a small per-provider schema adapter. And the 50% batch discount means up to 24h latency with no SLA: confirm downstream CIO campaign-entry timing tolerates that before taking it.

Governance note: the Chinese models are good and MIT-licensed; the risk is only the first-party endpoints (China-resident data, ToS permits training, no SOC 2). US hosts (DeepInfra, Fireworks, Together) dissolve it for a few dollars; if OpenRouter is used, pin provider routing to US endpoints. Platform detection stays deterministic regardless: it's inference from page markup, which is why we own this prompt rather than renting a vendor's.

6
Match confidence and the wrong-entity guard
A wrong match is worse than no match
free

Deterministic weighted scoring, never an LLM judgement call. Per Codex's review: exact phone +45, email-domain match +35, name match +20, geo agreement +15 (area code or NPI address), NPI taxonomy agreement +10, conflicting signals −30 to −60.

  • Auto-accept at score ≥75 (email domain alone nearly clears it; it's unambiguous).
  • Manual-review band 55–74 and generic names ("Hope and Faith") → stored as candidate, never synced to CRM. The pilot found state conflicts on exactly these.
  • No match → record enrichment_status: not_found. That's a real answer; ~30% of genuine signups are invisible, and that number feeds the marketplace/public-profile case.
Every synced attribute carries provenance: enriched_source (email_domain / npi / search / directory) + enriched_at + confidence. Sales can see why we believe it.
7
Sync to Customer.io and Pipedrive
Store once, fan out to both, forward-only
free

Store first: one enrichment doc per workspace in the pipeline's own Postgres. CRMs get projections of it; the AI onboarding agent consumes it later. Re-runs upsert, never duplicate.

Customer.io: identify via the Data Pipelines API (preferred over Track; ~3,000 req/3s, 64KB). Attributes prefixed enr_ so they can't collide with product-written attrs. Batch endpoint trap: oversized batches return HTTP 200 and silently drop, so keep batches well under 500KB and verify a sample profile after each run. verified

Pipedrive: v2 API only (v1 sunsets 31 Jul 2026, confirmed). Upsert person by email, else by phone; phone goes to the native field, specialty/platform/insurance to custom fields (fields exist for profession already via sub 764125's mapping). No batch endpoint exists, so throttle to the burst window (40 req/2s on Growth) rather than the daily token budget. verified

Backfill is a deliberate later step, never the default: CIO attribute writes re-evaluate live segments, which can fire campaigns at backfill volume. Stage under shadow attribute names or audit segment triggers first. Forward-only at launch, same decision as the dropoff sync.

Where it runs

the part that was unsure

n8n Community Edition in queue mode on a small cloud VM (~$10–24/mo Hetzner/Lightsail/DO). Queue mode (Postgres + Redis + workers) is free in CE, and the sustainable-use licence explicitly permits internal business automation. verified

  • Webhook trigger from CIO → waterfall as visual nodes → HTTP nodes for NPPES/search/fetch → one LLM node for extraction → CIO + Pipedrive writes.
  • Error workflows + per-node retries cover the failure handling; failed leads land in a retry queue instead of vanishing.
  • Quim can read, modify and debug it without owning bespoke code; Carlos can inspect runs visually.
  • Hybrid variant (Codex's pick, and the likely end state): keep n8n as thin orchestration and put the fiddly logic (entity-resolution scoring, platform signature registry, SSRF-guarded fetching) in one code node or a small TypeScript service beside it. Canvas for flow, code for judgement.

Non-negotiables: pin a patched version (a CVSS 10.0 webhook RCE, CVE-2026-21858, affected everything ≤1.65.0); don't expose the editor publicly; set execution-data pruning on day one (default threshold is 10k executions, one month of our volume, and Postgres bloats fast). verified

Homelab vs cloud: the homelab runs production-ish services fine, but this pipeline writes into Customer.io and Pipedrive, which are shared systems other people depend on. It shouldn't share fate with homelab maintenance. Recommendation (Codex concurs): small cloud VM, ~$24/mo.

A single Node/Python worker (queue + cron, ~200 lines) on the same VPS. Maximum control, minimum moving parts, and the community's honest warning about visual tools is that big workflows degrade into "one giant script on a canvas" anyway.

  • Right choice if Quim prefers code ownership over canvas debugging, or if the LLM-reconcile step gets too conditional for nodes.
  • Costs the same to run; loses the visual run inspector and the plug-and-play retry/error workflows.

This is a taste decision for Quim more than an architecture decision. The pipeline design is identical either way; n8n is the default because both of you can see it.

Clay restructured its pricing in March 2026: a 5–6 step waterfall at 10k leads/mo lands on Growth (~$446/mo) or Enterprise, and its HIPAA/BAA posture could not be verified at all, which matters for a healthcare vertical. Cargo Professional is $1,190/mo. Persana is being sunset into Rox (do not build on it). FullEnrich's self-serve tiers are too small at this volume. pricing verified Clay HIPAA unverified

Managed platforms earn their fee on contact-data waterfalls (email/mobile lookup across 10+ vendors). Our problem is different: identity resolution + custom extraction on public healthcare data, where the paid data layer adds nothing over free NPPES + $6 of search. Wrong tool at ~20–40× the run cost.

Monthly cost at ~10k enrichmentsCoreWith optional add-ons
Search (DataForSEO/Serper) + fetch (Jina/Exa)$10–35
LLM extraction (Vertex Flash-Lite primary ≈$27.50–55; +$12 DeepSeek shadow lane; Haiku fallback on standby)$40–70
VPS for n8n + Postgres + Redis$10–20
Email verification (Bouncer/ZeroBounce)$40–100
Phone line-type (Telnyx $0.007/lookup)~$70
Total estimate — Codex's independent all-in figure: $225–300/mo (~$0.03/enriched signup)~$35–205/mo~$150–375/mo

Second opinion (Codex)

independent architecture review

Codex independently converged on the same shape (email-domain-first waterfall, free NPPES, cheap search, own extraction, n8n + small VM) and priced it at ~$225–300/mo all-in, about $0.03 per enriched signup. Three of its calls are upgrades this plan adopts:

  • Identity is deterministic, never an LLM decision. Weighted scoring: exact phone +45, email domain +35, name +20, geo +15, NPI taxonomy +10, conflicts −30 to −60. Auto-accept at ≥75, manual-review band 55–74, reject below. The LLM only extracts fields from an already-confirmed site.
  • Shadow mode before any live CRM write. Run the full pipeline for 1–2 weeks logging intended CIO/Pipedrive writes without executing, measure the false-match rate on the 55–74 band, then flip live. This also matches the standing house rule: new automated CIO actions start disabled, Carlos enables.
  • Don't scrape the directories. Psychology Today, Tebra and Yelp block scrapers and their terms prohibit it. Record the listing URL from search results as evidence; extract only what the practitioner's own site and NPPES give.

Where it differs, and the resolution: Codex prefers a TypeScript worker holding the logic with n8n as thin orchestration (the hybrid is now the recommended infra option); Gemini Flash-Lite as extraction model where this plan starts on Haiku 4.5 and validates down (superseded by the 27 Jul model deep-dive in stage 5: Haiku primary, 3.5 Flash-Lite fallback, DeepSeek shadow lane); and a cloud VM over the homelab, agreed here for isolation: this pipeline writes into shared production systems, so it shouldn't share fate with homelab maintenance.

Codex also flagged: SSRF protection on website fetches (block private/metadata IP ranges), idempotency keys + dead-letter queue per stage, partial enrichment is a valid result, abandoned-then-completed signups must upgrade one canonical record rather than create two, and abandoned signups are identifiable people so document the lawful basis and honour deletion.

Risks and guardrails

Wrong-entity matches poison the CRM.
A confidently wrong website on a Pipedrive record misleads sales worse than a blank. Guard: 2-signal auto-accept rule, ambiguous stays out of CRMs, provenance on every attribute.
Google Places TOS prohibits CRM storage of its data.
No Scraping + No Caching clauses cover business name, address, phone, website; only place IDs are storable. The plan routes around Places entirely.
Pipedrive v1 sunset 31 July 2026 (confirmed).
Four days away. Build v2-only (also 50% cheaper in tokens). Audit existing CDP subscriptions and any scripts for v1 endpoints.
CIO backfills can fire live campaigns.
Attribute writes re-evaluate segments; a bulk write to an attribute a live campaign keys on = sends at backfill volume. Forward-only at launch; any backfill gets a segment-trigger audit first.
Health-adjacent data caution.
Everything enriched is public business data about providers, not patient data, so HIPAA doesn't attach. Keep it that way: never enrich client/patient records, and keep the pipeline out of PHI-bearing systems.
n8n security surface.
It will hold CIO, Pipedrive and LLM keys behind a public webhook. Patched version, auth on the webhook path, editor not exposed, secrets in env vars.
SSRF on website fetches.
The pipeline fetches URLs derived from user-influenceable signup data. Block private, loopback, link-local and cloud-metadata IP ranges, before and after DNS resolution and redirects.
LLM extraction is ~83% right per field at best.
Valid JSON is solved; correct values are not (benchmark ceiling 0.830). Build a 200-lead hand-labelled golden set, measure per-field value accuracy before go-live, and run the $12/mo DeepSeek shadow lane as a continuous agreement signal.
Scrape etiquette.
Respect robots.txt, identify the crawler, cache pages in the enrichment doc so re-runs don't re-fetch. Practice sites are small; be a polite visitor.

Rollout

consumers in the agreed order: sales → lifecycle → product
Phase 1 · Quim's sprint: pipe + phonesweeks 1–2

Stand up n8n + Postgres, wire triggers, junk gate, email-domain + NPI + search waterfall, extraction, confidence scoring. Run in shadow mode first: log intended CIO/Pipedrive writes for 1–2 weeks without executing, validate the false-match rate, then flip live (matches the house rule: automated CIO actions start disabled, Carlos enables). First live consumer: recovered phones → Pipedrive. Success = phone coverage on new signups moves from 71% toward ~85% (estimate; ceiling is the ~55% findability floor).

Phase 2 · Lifecycle attributesweeks 2–4

enr_specialty, enr_current_platform, enr_accepting_insurance, enr_website into CIO. Re-feeds RCM targeting and switcher campaigns that v4 starved. Carlos owns which campaigns consume what.

Phase 3 · Product consumersweeks 4+

Brand auto-intake (logo/colours on workspace) and prefilled services from the stored enrichment docs. This is the Tron on-ramp: same docs, new consumer, no rebuild.

Later · Backfill decisionexplicitly deferred

Running the existing base (e.g. active trials, the 232k reactivation list) through the pipeline is powerful but needs the CIO segment audit and Pipedrive throttling plan first. Separate go/no-go.

Open decisions

0 of 7 decided · pick an option, saves locally
Orchestration style
Quim's call. Pipeline design is identical either way; the question is where the fiddly logic lives.
Where it runs
It writes into shared production systems, so it shouldn't share fate with homelab maintenance.
Search vendor
Trial the pick on 100 leads first, and confirm its terms permit storing derived attributes long-term (Brave's are ambiguous).
Email verification depth
The free blocklist ships in phase 1 regardless; this is about paying per-address on top.
Pipedrive owner for enriched dropoffs
Open since the dropoff sync went live: everything currently lands under Carlos.
LLM account
A company API account with billing alerts. Never the Claude subscription, never a personal key. Full comparison in stage 5.
Backfill of the existing base
Forward-only at launch is already decided. This is the later go/no-go, gated on the CIO segment audit.