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.
- 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.MRR from Stripe
Zudo computes monthly recurring revenue by normalising every billing cadence to a month:- 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.
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 sourcestripe, 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.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 Endis within the next 7 days - Payment problems —
Stripe Delinquentis true, orStripe Current Subscription Statusispast_due - Leaving at period end —
Stripe Cancel At Period Endis true - Annual contracts —
Stripe Subscription Intervalisyear
In smart traits
In a formula, a Stripe trait istraits.stripe.<field>:
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.
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 nostripe.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.
