> ## Documentation Index
> Fetch the complete documentation index at: https://docs.zudo.so/llms.txt
> Use this file to discover all available pages before exploring further.

# Stripe

> Bring subscriptions, invoices and customer metadata into Zudo, and optionally let Stripe decide each account's MRR.

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](/settings/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. Zudo never writes to Stripe, so a read-only key is enough. A standard secret key also works.

<Note>
  Zudo verifies the key with Stripe before saving it, so a revoked or under-permissioned key fails immediately rather
  than silently syncing nothing.
</Note>

## Connect

<Steps>
  <Step title="Add the connection">
    Go to **Settings → Connections**, click **Add Connection**, and select Stripe. Paste your API key.
  </Step>

  <Step title="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](#creating-accounts-from-stripe-customers).
  </Step>

  <Step title="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](#trait-name-conflicts).
  </Step>

  <Step title="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.
  </Step>
</Steps>

## How customers match to accounts

By default Zudo matches a Stripe customer to the account whose **contact email** matches the customer's email.

| Strategy            | Matches on                                                | Use when                                             |
| ------------------- | --------------------------------------------------------- | ---------------------------------------------------- |
| **Email** (default) | The customer's email against your contacts' emails        | Most orgs                                            |
| **Metadata key**    | A Stripe metadata field against the account's external ID | Your Stripe customers already carry your account IDs |
| **Customer ID**     | The Stripe customer ID against the account's external ID  | Your external IDs are already Stripe customer IDs    |

Two rules matter:

* **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 email shared by contacts on two different 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.*`

<Note>
  Customer metadata is kept exactly as Stripe stores it — as text. A metadata field holding `enterprise` stays
  `enterprise` rather than being turned into a number.
</Note>

## MRR from Stripe

Zudo computes monthly recurring revenue by normalising every billing cadence to a month:

```
sum of (unit amount x quantity) / months in the billing period, less discounts
```

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](/settings/mrr-sources).

## Creating accounts from Stripe customers

Off by default. Turn it on when your customer list lives in Stripe and Zudo should follow it.

When on, a Stripe customer that matches no existing account becomes one — but only if it has a subscription that is **active, past due or trialing**. That filter exists because a Stripe account also accumulates every one-off payer, abandoned signup and test customer you have ever had, and importing those distorts account counts, average MRR and health score distributions.

Created accounts are marked with source `stripe`, named after the company (falling back to the billing email), and set active based on their 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.

<Steps>
  <Step title="Copy the URL">
    Expand the Stripe connection under **Settings → Connections** and copy the webhook URL.
  </Step>

  <Step title="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.
  </Step>

  <Step title="Paste the signing secret">
    Stripe shows a signing secret starting with `whsec_`. Paste it back into Zudo and save.
  </Step>
</Steps>

<Warning>
  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.
</Warning>

## 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.
