Skip to main content
The Stripe integration reads your billing data into Zudo as account traits, so subscription status, plan names, renewal dates and customer metadata are all usable in segments, smart traits, filters and reporting. Connecting Stripe does not change any MRR figure. Revenue moves only when you decide it should, by reordering your MRR sources — a separate setting you can change back.

What you need

A Stripe restricted API key with read access to Customers, Subscriptions and Invoices. Each organization can connect one Stripe account. Zudo never writes to Stripe, so a read-only key is enough. A standard secret key also works.
Zudo verifies the key with Stripe before saving it, so a revoked or under-permissioned key fails immediately rather than silently syncing nothing.

Connect

1

Add the connection

Go to Settings → Connections, click Add Connection, and select Stripe. Paste your API key.
2

Decide whether Stripe creates accounts

Leave Create accounts from Stripe customers off if your accounts already come from somewhere else. Turn it on if your customer list lives in Stripe — see Creating accounts.
3

Review the trait-name warning

If another connection already syncs Stripe-named traits, Zudo lists which names are affected before you save. Nothing you have already built changes — see Trait name conflicts.
4

Set up the webhook (optional)

Expand the connection and follow the two steps under Webhook. Without it, Stripe changes appear within twelve hours instead of within minutes.

How customers match to accounts

Set this under Customer matching on the Stripe connection, in Settings → Connections. It decides which account each Stripe customer’s billing data lands on, so it is worth getting right before you lean on that data. A metadata field is the strict answer. An identifier you write yourself means exactly one account by construction, and it keeps one-off payers and test customers out of your roster. Zudo offers the metadata keys it has actually seen on your customers, so you pick one rather than typing it — a key that doesn’t exist matches nothing at all, and says nothing about it. Email is a guess. Shared billing addresses, accounts@ and invoices@ aliases and +tag addresses all point at more than one customer. Measured against a billing system’s own links on a real book of 115 accounts, email matching disagreed about which Stripe customer the account is on 19 of them — silently, because a wrong match looks exactly like a right one. Email remains the default for a connection nobody has configured, because a fresh Stripe account has no identifier of yours in it.

Matching by email as a fallback

When you pick an identifier, you can also allow Zudo to try email for the customers that identifier cannot place:
  • Off (default) — a customer with no value in that metadata field is reported for you to link, not attached to whichever account happens to share its email address.
  • On — Zudo tries the contact email for those customers only. Every link still records which pass made it, so a guess is never mistaken for your own identifier.
An identifier held by two accounts is never resolved by guessing either way: two accounts already claim that customer, and answering that with an email match would turn a reported problem into a silent wrong link. Changing any of this takes effect on the next sync. Nothing is re-matched when you save, so you can set it and then run Sync Now when you are ready. Two rules hold whatever you pick:
  • A customer that matches nothing is reported, not created — unless you turn on account creation. An account appearing from nowhere in an established roster is worse than a customer that needs a manual link.
  • An identifier shared by two accounts is ambiguous, not a match. Zudo reports it rather than guessing, because picking either one would attach that customer’s revenue to a coin flip.

What syncs

Around forty Stripe fields arrive as account traits, named to match what Vitally’s Stripe integration produces so existing segments and smart traits keep working:
  • Customer — ID, email, name, created date, account balance, delinquent flag, country, currency, invoice prefix
  • Subscription — ID, status, current period start and end, trial start and end, cancel-at-period-end, interval and interval count
  • Amounts — subscription amount as billed, monthly-normalised amount, both before and after discounts, and total MRR
  • Plans — plan IDs, names and amounts
  • Discounts — ID, name, percent off, duration
  • Last invoice — ID, amount and timestamp
  • Card — last four digits and expiry month
  • Metadata — one trait per customer metadata key, under stripe.metadata.*
A metadata field holding a number arrives as a number, so it can be compared, ranged and summed like any other numeric trait. Figures written the way people write them count: 9041.66, 5,250 and $1,200 all arrive as numbers. Anything else is kept exactly as Stripe stores it — a field holding enterprise stays enterprise, and so does one holding 1,2, because that is a list or a decimal comma rather than a figure, and reading it as 12 would invent a number.
A key that holds numbers on some customers and words on others is treated as numeric, and the odd non-numeric value stays text on the account that has it. Zudo never switches a key back to text once it has seen a number in it — the type belongs to the field, not to whichever customer synced last.

MRR from Stripe

Zudo computes monthly recurring revenue by normalising every billing cadence to a month:
A $12,000/year subscription is **$1,000** of MRR, not $12,000. Quarterly billing divides by three. Some deliberate choices:
  • A trial is worth zero, not its eventual price. Counting it would inflate MRR for every signup and then show a churn when the trial converts to the same number.
  • A past-due subscription still counts. Dropping revenue the moment a card fails makes involuntary churn look like a decision the customer made.
  • A canceled subscription is $0 — a real answer, so it correctly drops the account’s MRR.
  • Mixed currencies are refused, not summed. Zudo will not add €100 to $100. The account keeps its current figure and the condition is reported.
None of this becomes your account’s MRR until you say so. See MRR sources.

Creating accounts from Stripe customers

Off by default, under Create accounts from Stripe customers on the Stripe connection. Leave it off if your accounts come from somewhere else; turn it on when your customer list lives in Stripe and Zudo should follow it. Either way, a customer that matches no account is reported so you can link it by hand. Turning this on is about whether Zudo may also add it.

The filter is the feature

A Stripe account accumulates every one-off payer, abandoned signup and test customer you have ever had. Importing all of them produces a roster nobody wants and quietly moves account counts, average MRR and health-score distributions. So the rule answers something narrower than “does this customer exist”: The default statuses are deliberate. A trial is not revenue, but it is a company someone should be looking after — that is the job. And past due still counts, because dropping a customer the moment a card fails makes involuntary churn look like a decision they made.

Check before you trust it

What would this create? runs the rule against a sample of your Stripe customers and reports how many would become accounts and why the rest were skipped, without creating anything. It is worth using: the answer scales, and “412 would be created” is much better learned before the sync than after. Saving the rule creates nothing either. The next sync applies it.

What a created account looks like

Marked with source stripe, named after the company (falling back to the billing email), and set active based on its subscription rather than defaulted to active. A customer that matches two accounts is never created — the roster already holds two candidates for it.

Webhooks

Optional. Webhooks make Stripe changes appear within minutes; the twelve-hourly sync keeps running either way and is what catches anything a webhook missed. Without a webhook, Stripe data refreshes on a schedule — every 12 hours. The webhook brings that down to minutes.
1

Copy the URL

Expand the Stripe connection under Settings → Connections and copy the webhook URL.
2

Add the endpoint in Stripe

In the Stripe dashboard, add that URL as a webhook endpoint. Subscribe it to the customer.*, customer.subscription.* and invoice.* events.
3

Paste the signing secret

Stripe shows a signing secret starting with whsec_. Paste it back into Zudo and save.
Until the signing secret is saved, Zudo rejects everything Stripe sends to that URL. That is deliberate — an endpoint that cannot verify who is calling it should not act on what it receives. The connection card shows Not receiving until the secret is in place.

Using Stripe data

Everything Stripe syncs becomes an ordinary account trait, so it works anywhere traits work — no separate Stripe-flavoured UI to learn.

In segments and filters

Stripe traits appear in the trait picker on the accounts list and in the segment builder, listed under their labels (Stripe Current Subscription Status, Stripe Trial End, and so on). Useful ones to start with:
  • Trials ending this week — Stripe Trial End is within the next 7 days
  • Payment problems — Stripe Delinquent is true, or Stripe Current Subscription Status is past_due
  • Leaving at period end — Stripe Cancel At Period End is true
  • Annual contracts — Stripe Subscription Interval is year

In smart traits

In a formula, a Stripe trait is traits.stripe.<field>:
The formula builder’s variable list offers every one of them as a clickable chip, so you rarely need to type the name.
If another connection already syncs a trait with the same name, that one keeps the short name and Stripe’s version moves to traits.stripe.stripe.<field>. The builder shows you which name resolves to which. See Trait name conflicts.

In reporting

Stripe traits are available as columns and groupings in custom reports, and as fields in the account API.

Switching MRR to Stripe

Connecting Stripe does not change any MRR figure. Moving revenue onto Stripe is a separate, deliberate step you can reverse.
1

Compare first

With Stripe connected but MRR untouched, look at Stripe Mrr next to your current MRR on a few accounts. Both are visible on the account page. This is the whole point of connecting without switching.
2

Add the source

Go to Settings → Organization → MRR sources and add Stripe — computed from subscriptions. Each source shows how many accounts it can actually answer for; check that number before you promote it.
3

Put it first

Move it to the top of the list and save. MRR updates on the next sync.
MRR weights the health score, so reordering these sources can move scores. Stripe normalises annual billing to a monthly figure — if your current source does not, expect annual accounts to drop by roughly 12×. That is a change in what the number means, not an error.
To go back, move the source down again or remove it. Nothing is destroyed.

If you record contracted revenue in Stripe metadata

Some teams keep a hand-agreed figure in a Stripe customer metadata field rather than deriving it from subscriptions. Add Stripe metadata as a source and pick the key — Zudo lists the keys it has actually seen, with how many customers carry each. Put it above Stripe — computed from subscriptions so the hand-set figure wins and the computed one fills the gaps.

Reference: what each trait holds

stripe.subscriptionAmount and stripe.subscriptionMonthlyAmount differ on anything that is not billed monthly. Confusing them is the most common mistake when writing a revenue formula.

Troubleshooting

Accounts show no Stripe traits. The sync reports customers it could not place. Check How customers match to accounts above — by default Zudo matches on contact email, so a Stripe customer whose email is not on any contact in Zudo has nowhere to land. One account is missing traits that its neighbours have. That customer probably matched two accounts and was reported as ambiguous rather than guessed at. Two accounts sharing a contact email causes this. A trait exists but is empty on some accounts. Stripe does not populate every field for every customer — a customer with no card on file has no stripe.cardLastFour, one who has never been invoiced has no stripe.lastInvoiceAmount. MRR did not change after connecting. That is by design. See Switching MRR to Stripe. The webhook shows “Not receiving”. The signing secret is missing or wrong. Zudo rejects unsigned deliveries, so the twelve-hourly sync is doing all the work until you paste it in.

Trait name conflicts

If you already have a connection that syncs Stripe-named traits — Vitally’s Stripe integration does — then both connections want the same short names in smart trait formulas. Zudo resolves this predictably: the connection you had first keeps the name, so connecting Stripe never silently changes what an existing formula reads. Stripe’s version stays reachable at its full path, and you can hand the names over afterwards under Settings → Organization → Trait name precedence. The connect dialog lists exactly which names are affected before you save.

Disconnecting

Removing the Stripe connection removes its traits. If your MRR sources reference Stripe, MRR falls through to the next source in the chain, or keeps its current value if nothing else can answer — Zudo never zeroes an account because a source disappeared.