Vertical SaaS Platform

8 component deliveries, 339 customer accounts auto-synced from Stripe to Attio with zero data loss

A 400+ customer vertical SaaS platform needed Attio to become the single source of revenue truth across product, billing, support, and sales. Over 12 weeks we shipped 8 components — duplicate cleanup, real-time auto-dedup, full Stripe revenue sync, sales engagement tracking, lifecycle orchestration across Lemlist + Intercom, and the entire reporting layer.

12-week retainer ·

8

Component deliverables shipped

339

Stripe customers backfilled into Attio

10+

Live n8n workflows in production

9,000+

Person records under real-time dedup

The situation

A 400+ customer vertical SaaS platform operating with 10K+ records in Attio across companies, contacts, and deals. Their core problems were the structural ones every scaling B2B SaaS hits between Series A and Series B:

  • Duplicate contacts at scale. A person could exist 3 times — once from a signup, once from a sales import, once from a support ticket. Reporting was unreliable because none of them knew about each other.
  • Stripe and Attio knew different things about the same customer. The MRR, plan, churn state, and lifetime value lived in Stripe; everything else lived in Attio; nobody had the merged view.
  • Sales engagement was happening in Lemlist + WhatsApp but the activity wasn’t being written back to Attio, so the sales pipeline view was missing the actual outbound state of every account.
  • No clear lifecycle orchestration. A contact could be in a Lemlist sequence and an Intercom support conversation and a sales pipeline stage all at once, with no clean ownership rule.

What we built

8 component deliveries across a 12-week retainer.

Foundation (Weeks 1–2)

Duplicate cleanup — Python tooling: detect (Levenshtein fuzzy match + completeness scoring), CSV export for review, batch merge with the highest-quality master record kept. One-time pass across the entire 9,000+ contact database.

Automatic dedup — A real-time n8n workflow listens to Attio’s record.created webhook, fuzzy-matches every new person against the existing 9,000+ database (≥90% Levenshtein, 3-char prefix filter for performance), and merges immediately if a duplicate is found. Every new record self-cleans the moment it’s written. Zero manual review needed.

Revenue layer (Weeks 3–6)

Stripe integration — 4 n8n workflows + a one-time backfill:

  • Subscription lifecycle: Stripe customer.subscription.created/updated/deleted → Attio Company subscription_status, current_plan, MRR, stripe_customer_id
  • Payment sync: payment_intent.succeeded → resolves the customer ID → Attio Company total_lifetime_value, last_payment_date
  • Trial activation: trial subscription created → corresponding Deal moved to “In Trial” stage
  • Churn detection: subscription canceled → Client record client_status flipped to “Churned”
Stripe event                  →  Attio Company field updated
─────────────────────────────────────────────────────────────
subscription.created          →  subscription_status, current_plan, MRR
subscription.updated          →  subscription_status, current_plan, MRR
subscription.deleted          →  subscription_status, Client.client_status
payment_intent.succeeded      →  total_lifetime_value, last_payment_date
subscription (status=trial)   →  Deal.stage = "In Trial"

Backfill: 372 Stripe subscriptions processed → 339 Attio Companies updated, 33 skipped (cleanly, missing identifier), 0 errors.

The trickiest part: the business identifier (gymId) lives on Stripe subscription metadata, not on customer metadata. Payment events don’t carry it directly — they need a resolution chain.

payment_intent.succeeded
  └─ extract customer_id
       └─ stripe.list_subscriptions(customer_id)
            └─ first sub.metadata.gymId
                 └─ patch Attio Company WHERE gymid = {gymId}

Reporting & dashboards — Built natively inside Attio’s reporting tool. No external BI, no extra subscriptions, no third-party data flow. The whole pipeline + revenue picture lives where the team already works.

Engagement layer (Weeks 5–7)

Sales engagement sync — 2 n8n workflows write Lemlist + WhatsApp activity back to the Attio Company record (last_outreach_date, last_outreach_channel, current_sequence, sequence_ended, last_whatsapp_date). System of engagement (Lemlist, WhatsApp) stays separate from system of record (Attio); only what matters for pipeline visibility crosses the line.

Lifecycle orchestration — 3 n8n workflows enforce “one contact, one owner, one inbox at a time”:

  • Lifecycle stage router (18-node workflow): when an Attio lifecycle stage changes, route to the right action — enroll/remove from Lemlist sequences, assign/close Intercom conversations, update the system-owner field.
  • Deal owner sync: when a deal owner changes, reassign open Intercom conversations to match.
  • Mutual exclusion guard: scheduled workflow runs every 6h, alerts Slack if any contact ends up in a forbidden state (e.g. active in both Lemlist and Intercom simultaneously).
Attio lifecycle change → n8n router
                          ├─ Demo Booked   → remove Lemlist, alert sales in Slack
                          ├─ Customer      → remove Lemlist, assign CSM in Intercom
                          ├─ Churned       → close Intercom, optional win-back enroll
                          └─ Lost          → archive across all systems

every 6h: mutual_exclusion_guard()
            for contact in all:
              if active_in(Lemlist) AND active_in(Intercom):
                slack.alert("forbidden state", contact)

Support layer

Intercom ticketing — Custom Tickets object in Attio + an 8-node n8n sync workflow. Tickets created, closed, reopened, snoozed, replied — every state change writes back to Attio, linked to the right Company. Skeleton built and ready to activate when Intercom production goes live.

Outcome

  • 8 component deliverables shipped across 12 weeks, on time, every week.
  • 339 customer Companies in Attio now carry live Stripe revenue data — MRR, subscription_status, current_plan, LTV, last_payment_date — kept current by webhook on every Stripe event.
  • 9,000+ person database under real-time duplicate protection.
  • 10+ n8n workflows in production orchestrating Stripe, Lemlist, WhatsApp, Intercom, and Attio together.
  • Native Attio reports replacing what would have been a BigQuery + Looker setup at 5x the cost.

Why this matters for vertical SaaS at scale

Once a SaaS hits a few hundred customers, the cost of not having clean Stripe ↔ CRM sync isn’t measured in hours of manual work — it’s measured in deals you don’t follow up on, churns you don’t see coming, and reports you can’t trust enough to act on. The fix is not a 6-figure RevOps stack with Salesforce + DataLoader + Tableau. It’s Attio + a handful of well-designed n8n workflows + a real-time dedup loop. Built right, it costs an order of magnitude less and the ownership stays with you, not a Salesforce admin contractor.

Vertical SaaS Stripe Integration Lifecycle Orchestration Real-time Dedup Long Engagement

Stack: Stripe · Intercom · Lemlist · WhatsApp · n8n

Want this for your team?

30-minute CRM audit, free. We'll tell you exactly what your Attio should look like.

Let's chat