# Stripe

> Connect Stripe to atrby so each Stripe payment is matched to the visit that brought it, including subscription renewals and refunds.

Canonical: https://atrby.site/docs/integrations/stripe
Last updated: 2026-10-21

Attribute every Stripe payment to the visit that brought it.

## Connect

1. In the Stripe dashboard, open Developers → Webhooks → Add endpoint. After you save it, reveal the **Signing secret**; it starts with `whsec_`.
2. In atrby, open Revenue → Payment processors → Connect, choose Stripe and paste the secret.
3. atrby shows your webhook URL. It looks like `https://app.atrby.site/api/webhooks/stripe/…`. Add it in Stripe and send these events: `checkout.session.completed`, `invoice.paid`, `charge.refunded`.

The connection shows as active once the first webhook arrives. Webhooks with a wrong signature are rejected.

## Pass the visit ids

Where they go: Checkout Session `metadata`. For subscriptions, also `subscription_data.metadata`, which Stripe copies to every renewal invoice. Read them in the browser with `atrby.ids()` and send them to your server with the checkout request.

*Browser*

```js
const ids = window.atrby?.ids(); // { atrby_sid, atrby_site }
```

*Server · Stripe Checkout*

```js
await stripe.checkout.sessions.create({
  mode: "subscription",
  line_items: [{ price: "price_growth_monthly", quantity: 1 }],
  success_url: "https://acme.io/welcome",
  metadata: { ...ids, atrby_uid: user.id },
  subscription_data: { metadata: { ...ids, atrby_uid: user.id } },
});
```

`atrby_uid` is your user id, from [identify](https://atrby.site/docs/identify). It's optional, but it credits payments made long after the first visit.

## What gets recorded

- Each payment once, however often Stripe retries the webhook.
- Full and partial refunds are subtracted from the source of the original payment.
- The first payment comes from `checkout.session.completed` once it's paid; `invoice.paid` is only used for renewals, so nothing is counted twice.

> **Not covered.** Payments made outside Checkout and invoices, such as a bare PaymentIntent, aren't read. Use the [Payment API](https://atrby.site/docs/payment-api) for those.

## Related
- [Lemon Squeezy](https://atrby.site/docs/integrations/lemon-squeezy)
- [Polar](https://atrby.site/docs/integrations/polar)
- [Payment API](https://atrby.site/docs/payment-api)
