Stripe affiliate program software with Connect payouts
Stripe at a glance
Does Stripe have a built-in affiliate program?
Stripe has no affiliate feature for merchants in its docs as of November 2026. Affiliate tools connect to Stripe through its webhooks and its API. OpenPromoter is one of them and adds the tracking, the partner portal and the payouts that Stripe leaves to you.
That split keeps Stripe as the record of every payment. The affiliate tool listens to Stripe webhooks and never touches your prices or plans. If you remove it later, your billing keeps working.
You need three things to run the program. A Stripe account, one script on your site and a way to pay partners. OpenPromoter covers the last two.
How Stripe affiliate tracking works
OpenPromoter gives each visitor from a partner link a click id. That id travels into Stripe Checkout as client_reference_id or as op_click metadata. When Stripe sends invoice.paid, OpenPromoter finds the partner and books the commission on what the customer paid.
Payment Links and the Pricing Table
Payment Links need no code. op.js adds client_reference_id to every buy.stripe.com and checkout.stripe.com link on the page. It also sets it on the Pricing Table and Buy Button elements, including ones added after the page loads.
Stripe documents the client_reference_id parameter in its Payment Links URL parameters guide.
Checkout Sessions from your server
If your server creates Checkout Sessions, send window.openpromoter.clickId from the browser with the request. Pass it to Stripe as client_reference_id and as op_click in the subscription metadata. The SDK helper stripeCheckoutParams builds both fields for you.
Coupon codes and promotion codes
Enter a Stripe coupon id on a partner's page and OpenPromoter creates the matching promotion code in your account. A sale that uses the code is credited to that partner with or without a click. That covers podcasts and videos where people type a code they heard.
The order of signals
OpenPromoter checks five signals in a fixed order. A coupon code wins over the click id and the click id wins over an op_ref partner code. The cookie window click and the signup email come last, as the tracking docs explain.
const session = await stripe.checkout.sessions.create({
// ...your existing options
client_reference_id: req.body.opClickId, // window.openpromoter.clickId
subscription_data: { metadata: { op_click: req.body.opClickId } },
});Set up Stripe affiliate program software in four steps
Setup takes four steps and changes nothing in your prices or plans. You connect Stripe, add op.js to your site and pass the click id if your server creates Checkout Sessions. Then you pick how partners get paid and try the whole flow in test mode.
- 1
Connect Stripe
On Cloud, click Connect Stripe and approve access. On your own server, paste a restricted key.
- 2
Add op.js
Paste one script tag in the head of your site and your app. It is about 2 KB.
- 3
Pass the click id
Payment Links need nothing. Server-created Checkout Sessions take client_reference_id.
- 4
Pick payout methods
Turn on Stripe Connect, PayPal, Wise or manual payouts for your partners.
| Resource | Permission | Why OpenPromoter needs it |
|---|---|---|
| Customers | Read | Match referred customers and import history |
| Subscriptions | Read | Recurring commissions and cancellations |
| Invoices | Read | Commissions are booked on paid invoices |
| Charges and Disputes | Read | Refunds and chargebacks |
| Checkout Sessions | Read | client_reference_id attribution |
| Products and Prices | Read | Program designer and import |
| Promotion codes | Write | Create partner coupon codes |
| Webhook Endpoints | Write | Register the OpenPromoter endpoint |
| Accounts and Transfers | Write | Only for payouts through Stripe Connect |
On your own server, OpenPromoter checks the key and registers the webhook endpoint at /api/webhooks/stripe/<workspaceId>. Keys are stored encrypted with your ENCRYPTION_KEY. Stripe's own API keys guide recommends restricted keys wherever possible.
Connect payouts also need Write on Account Links. The Stripe setup guide lists every field with copy-ready values.
Stripe webhook events and what each one does
OpenPromoter subscribes to nine Stripe webhook events. Two link a customer to a partner, one books the commission, three handle refunds and disputes and three follow the subscription. Each event is checked against the Stripe-Signature header with a five-minute tolerance and processed once.
| Event | What OpenPromoter does |
|---|---|
| customer.created | Links the customer to a partner from metadata or the lead email |
| checkout.session.completed | Reads client_reference_id and any promotion code |
| invoice.paid | Books the commission for the first payment and each renewal in the window |
| charge.refunded | Reduces or reverses the commission and claws back a paid one |
| charge.dispute.created | Holds the commission |
| charge.dispute.closed | Releases a won dispute and reverses a lost one |
| customer.subscription.created | Tracks the trial and the plan |
| customer.subscription.updated | Updates MRR on upgrades and downgrades |
| customer.subscription.deleted | Stops recurring commissions |
Commissions are booked on invoice.paid because it also covers invoices marked paid outside Stripe. Events can arrive twice or out of order. Duplicates are ignored.
Stripe retries a failed delivery for up to three days in live mode. Source: Stripe webhooks docs (November 2026).
Refunds and disputes and subscription changes
A refund before payout reduces the commission in proportion and a full refund reverses it. A refund after payout adds a clawback to the partner's next payout. An opened dispute holds the commission until Stripe closes it, and a lost dispute reverses it.
Refunds
charge.refunded carries the total refunded so far. OpenPromoter compares it with the charge and adjusts the commission to match. A second partial refund on the same charge is handled the same way.
Set the hold period to at least your refund window. The default is 30 days.
Disputes
When charge.dispute.created arrives, the commission moves to held. A won dispute returns it to pending. A lost one reverses it and claws it back if you already paid it.
Trials and renewals
A trial is tracked from customer.subscription.created and earns nothing until the first invoice is paid. Each renewal inside the commission duration books its own line. The duration can be one payment, a number of months or the lifetime of the subscription.
Test a Stripe affiliate program in test mode
Stripe test mode works from end to end. Test-mode events are processed like live ones and every referral and commission they create carries a Test badge. One click on Delete test data in Settings > Integrations removes them before you launch.
Buy through a test-mode Payment Link with a Stripe test card after opening a partner link. The commission shows up in the dashboard with its Test badge.
Stripe cannot reach localhost. Automatic webhook registration fails on a local install. Use the Stripe CLI to forward events and paste the whsec_ secret it prints into Settings > Integrations.
stripe listen --forward-to localhost:3000/api/webhooks/stripe/<workspaceId>Common Stripe affiliate setup mistakes
Most missed commissions come from a click id that never reaches Stripe. The next most common causes are a hold period shorter than the refund window and a webhook secret from the wrong mode. Each one below has a quick fix.
Your own id in client_reference_id
OpenPromoter reads the field only when it starts with clk_. Put op_click in metadata if you use the field.
No script on the page with the link
op.js must load on the page that links to checkout. Add it to your marketing site and your app.
A short hold period
Set the hold period to at least your refund window. The default is 30 days.
A secret from the wrong mode
Test and live endpoints have different signing secrets. Paste the one that matches the mode you use.
Promotion codes made by hand
Enter the coupon id on the partner's page. OpenPromoter then creates the code and links it to the partner.
Missing Connect permissions
Connect payouts need Write on accounts, account links and transfers in the restricted key.
Pay partners with Stripe Connect and handle tax
Your Stripe account acts as the Connect platform. A partner finishes Stripe's hosted Express onboarding in the portal and an approved payout becomes a Transfer from your Stripe balance. Stripe charges its own Connect fees for each transfer and OpenPromoter adds nothing on top.
Payouts wait for a signed-in owner, admin or finance member to approve them. A batch above $1,000 needs a fresh two-factor code by default. Each payout carries an idempotency key and a retry never pays twice.
Payouts use Stripe Connect Express accounts. Stripe lists its fees on the Connect pricing page.
The commission base excludes tax and uses what the customer paid after discounts. Stripe Connect collects partner tax details during its own onboarding. PayPal, Wise and manual payouts are covered on the payouts page.
Partners paid by PayPal, Wise or by hand submit a W-9 or a W-8BEN in the portal. EU VAT ids are checked against the VIES service. Every payout gets a self-billed invoice with a sequential number.
US partners need a W-9 before their payouts for the year pass the 1099-NEC threshold. That threshold is $2,000 for payments made in 2026. The 1099 guide for affiliates covers the filing.
Questions
Does it work with Stripe Payment Links?
Can I import my existing Stripe customers?
Does OpenPromoter add a fee to Stripe Connect payouts?
How long does the referral cookie last?
Can I use Stripe and Paddle in one program?
What if a partner refers themselves?
Related

[ openpromoter ]
Try it with your own Stripe account
Free on Cloud up to $1k a month in partner revenue or free forever on your own server.