Connect Stripe (Stripe App)
On the hosted plan, Admin → Integrations → Connect Stripe installs the OpenPartner Stripe App on your own Stripe account. From then on OpenPartner reads your payments from Stripe itself, so your server forwards nothing:
- Checkout and Payment Link purchases credit the partner who sent the buyer.
- Invoices and renewals for a referred customer are recorded as they’re paid.
- Refunds, full or partial, reverse or reduce the commissions on that payment.
- Disputes are recorded against the customer. They reverse nothing, because a dispute can be won.
- Partner promo codes entered at Stripe Checkout credit that partner.
- Customer-reward promo codes are created in your Stripe for you, when the program offers its customers a discount.
The app can read your payments but never moves money. Its only write access is to coupons and promotion codes.
Beta. The app is in Stripe’s external test while Stripe reviews it for the Stripe App Marketplace. It installs on live Stripe accounts and records real payments today. Until the review is done, it isn’t listed on the Marketplace, and Stripe’s install screen labels it Test version.
Self-hosting? You don’t need the app: your instance runs with your own Stripe key and listens to your Stripe webhooks. See Stripe Billing.
Connect your Stripe account
- Sign in to OpenPartner and open Admin → Integrations.
- Under Stripe, click Connect Stripe. Stripe opens.
- Pick the Stripe account to connect, review the permissions below, and accept.
- Stripe sends you back to Integrations, which now shows the connected account, a Live badge and when the last event arrived.
Then tell OpenPartner how your customers pay, on the same card, and do the one step it shows you. That step is getting the partner click into Stripe.
Good to know:
- The install starts in OpenPartner. The link Stripe opens is tied to your signed-in admin session, so an install started anywhere else can’t connect your Stripe account to someone else’s program.
- One Stripe account, one brand. A Stripe account that’s already connected to another OpenPartner brand is refused.
- Switching accounts. Connecting a different Stripe account replaces the one you had. Payments already recorded stay.
- Test mode. If Integrations also offers Connect a test-mode account, use it to try the flow with Stripe test payments before you connect your live account.
Permissions
The app asks for read access to the payment objects it records, and write access only to coupons and promotion codes. These are the purposes Stripe shows you at install:
| Permission | Why the app needs it |
|---|---|
event_read | Receive the checkout, invoice, refund and dispute events that credit your partners. |
checkout_session_read | Read completed Checkout Sessions and Payment Link purchases to match them to the partner link the buyer clicked. |
customer_read | Read a customer’s metadata to match their payments to the user your app identified. |
subscription_read | Record new subscriptions for referred customers. |
invoice_read | Record paid invoices for referred customers so partners earn commission on them, including the promo code used. |
charge_read | Read refunds and disputed charges so commissions on refunded revenue are reversed or flagged. |
dispute_read | Flag commissions on disputed payments for your review. |
promotion_code_read | Match promotion codes used at checkout to your partners’ codes. |
promotion_code_write | Create each partner’s customer-discount promotion code in your account, and deactivate it when the code is retired. |
coupon_read | Check that a new partner code doesn’t collide with one of your own coupons. |
coupon_write | Create the coupon behind each partner’s customer discount. |
What the app can’t do: charge a customer, issue a refund, create a payout, read your balance, or change a customer, subscription or price. OpenPartner never holds money: partners are still paid by you, the same way as before you connected.
If a later version of the app needs more access, Integrations says so and offers Reconnect. Until you reconnect, the app keeps working with what you granted.
Get the partner click into Stripe
Stripe never sees your website, so it can’t know which partner sent a buyer unless the partner click reaches Stripe. It only has to happen once per customer: after that, their invoices, renewals and refunds are recorded on their own.
Integrations asks how your customers pay and shows only the step that fits:
| How customers pay | What you do |
|---|---|
| A partner link goes straight to a Stripe Payment Link | Nothing to install. Put ?client_reference_id={click_id} on the program’s destination URL. |
| Payment Links, a Pricing Table or a Buy Button on your site | Paste one script tag into your site’s <head>. |
| Your app creates the Stripe Checkout Session | The same script tag, plus one line where you create the session. |
| Customers type a partner’s promo code at checkout | Nothing to install, when the program offers a customer discount. |
A partner link straight to a Payment Link
In Admin → Programs → Edit, set the program’s Destination URL to your Payment Link with the click id on the end:
https://buy.stripe.com/<your-link>?client_reference_id={click_id}Write {click_id} exactly like that: single braces, lower case. Each partner’s link fills in
its own click. A buy.stripe.com destination without it still saves, with a warning,
because no purchase through it can be credited. More on the macro in
Programs.
Payment Links, a Pricing Table or a Buy Button on your site
Paste this into the <head> of every page, above Stripe’s own embed script. Integrations
shows it with your workspace’s API URL filled in:
<script src="https://app.openpartner.dev/op.js" data-api-url="https://app.openpartner.dev/api/t/<your-workspace>"></script>That’s all. When a visitor came from a partner link, the script adds the click to every
buy.stripe.com link on the page and to every <stripe-pricing-table> and
<stripe-buy-button> embed, including ones added after the page loads. A link or embed that
already carries a reference keeps it.
Optional attributes on the tag:
data-stripe-hosts="pay.yourbrand.com": your Payment Links use a custom domain.data-cookie-domain=".yourbrand.com": visitors land on one subdomain and check out on another.
On a white-label domain, load the script and the API from that domain:
https://portal.yourbrand.com/op.js with data-api-url="https://portal.yourbrand.com/api".
The SDK page lists every attribute.
Your app creates the Checkout Session
Paste the same script tag into your site’s <head>. It keeps the partner click in a
first-party cookie on your own domain, op_ref. Then add one line where your server creates
the session:
const session = await stripe.checkout.sessions.create({ // ...your existing options client_reference_id: req.cookies.op_ref, // the partner click, if the visitor had one});When the visitor didn’t come from a partner link, there’s no cookie and nothing is sent.
Creating Stripe customers yourself, outside Checkout? Set metadata.openpartner_user_id on
the Customer to the same user id you pass to
identify(), before the customer’s first payment.
Partner promo codes
Nothing to install, as long as the program offers a customer discount (Admin → Programs → Edit → Offer customer-side discount). Each partner’s code is then created in your Stripe, and a purchase that uses it credits that partner. See Customer reward.
Make sure your checkout accepts promotion codes: turn on Allow promotion codes on the
Payment Link, or pass allow_promotion_codes: true when you create the Checkout Session.
Stop forwarding Stripe payments
Once Stripe is connected, Stripe’s record of a payment is the one OpenPartner keeps. If your
server forwards Stripe payments today, with trackEvent,
POST /attribution/conversions, a postback or POST /coupons/redeem, turn that off:
- A conversion keyed on a Stripe invoice or Checkout Session id (
in_…,cs_…) is refused with409 recorded_from_stripe, so a forwarder left running can’t pay a partner twice. Treat the409as final: log it and don’t retry. - A conversion forwarded under your own order id can’t be matched to the Stripe payment, so it would be counted twice. Stop sending those for Stripe payments.
Keep trackEvent for everything that isn’t a Stripe Checkout or invoice payment: signups,
trials, CRM stages such as demo_booked, payments you take elsewhere, and payments your
backend charges directly with a PaymentIntent.
If the connection stops working (see Reconnect), the 409
stops too and nothing is recorded from Stripe until you reconnect.
Refunds and disputes
A refund in Stripe is applied to the payment’s commissions for you. Each commission ends up worth its original amount times the share of the payment the customer kept, and several partial refunds add up.
- Accrued or approved commissions are reversed. On a partial refund, a replacement for the kept share is accrued with the same status and date, so its holdback doesn’t restart.
- Paid commissions stay paid. OpenPartner records a clawback for the refunded share and takes it off the partner’s next manual payout. Stripe Connect payouts on hosted OpenPartner don’t deduct it, so for those partners recover it yourself, if your terms allow. See Commissions.
- A payment that paid several invoices, or part of one, is recorded but reverses
nothing, because Stripe doesn’t say how much of which invoice was given back. Report it
with
POST /attribution/refundsand the amount.
A dispute is recorded and reverses nothing, because you can win it. If you lose, report
the chargeback with POST /attribution/refunds
and "kind": "chargeback", against the invoice id or Checkout Session id of the payment.
If Stripe needs a reconnect
If Stripe stops accepting OpenPartner’s access, Integrations shows Reconnect needed, we’re alerted, and new Stripe payments aren’t recorded. Click Reconnect to pick up from there.
Payments made while the connection was broken aren’t picked up later. To credit one, report it
with POST /attribution/conversions and the click id, under an
externalEventId of your own: the Stripe id is refused again once you’ve reconnected.
Disconnect or uninstall
Disconnect in OpenPartner. Admin → Integrations → Stripe → Disconnect stops OpenPartner reading your Stripe account and deletes its access tokens. Payments already recorded, and the commissions on them, stay.
Uninstall in Stripe. An app can’t remove itself from a Stripe account, so after disconnecting, uninstall it in the Stripe Dashboard under Settings → Installed apps → OpenPartner. Uninstalling there first works too: OpenPartner sees it and shows Stripe as disconnected. Uninstalling from a test-mode account leaves a live connection running.
Partner promotion codes already created stay in your Stripe account. Deactivate them there if you’re retiring the program.
The app’s settings page in the Stripe Dashboard has nothing to configure: everything is set up in OpenPartner.