Skip to content

Programs

A program is the rule applied to clicks → conversions for a given destination. It’s where you set:

  • The destination URL the click lands on
  • The commission rule (percent or fixed, recurring or one-time)
  • The attribution window + model
  • Optional start/end dates for promo periods

Each Link a partner shares belongs to exactly one program — that’s how the commission gets calculated.

Why programs aren’t always “one”

Most brands start with a single program called something like “Default 20% revshare” and never add another. That’s fine.

You’d add more programs when:

  • Different commission tiers — e.g. a “VIP affiliate” program with 30% recurring you only grant to a few hand-picked partners (see partner scoping)
  • Different products — a “Pro plan” program vs a “Basic plan” program with different destinations
  • Promo windows — a “Black Friday 2x commission” program that runs for 2 weeks then ends
  • Geographic targeting — different destinations for /us vs /eu

Creating a program

Admin → Programs → New program. Fields:

Name

Internal label — partners and creators don’t see this. Used in the admin UI.

Destination URL

Where the partner share-link lands when clicked. Required.

The router 302-redirects every click to this URL with a ?cref=<clickId> query param appended — that’s how the SDK on your site stitches the click back to the conversion.

Comma-separated host allowlist. When set, partners can override the destination on their share-link as long as their override matches one of these hosts.

Example: destination is https://acme.com/, allowed deep-link domains is acme.com,docs.acme.com. Partner can deep-link to https://acme.com/pricing or https://docs.acme.com/getting-started, but not https://blog.acme.com/post or anywhere else.

Leave blank to lock destinations to whatever you set above — no deep linking allowed.

Commission rules

A program carries an array of sub-rules that combine to produce the partner payout. Each sub-rule has a trigger, an optional event type filter, a type (percent or fixed), and a value. Recurring sub-rules can carry a months cap.

Triggers:

  • On every — fires on every event matching the filter (or every event with a value if no filter is set; the legacy single-rule shape).
  • On first — fires only on the FIRST event of that type for the (partner, customer) pair. Used for one-time signing bonuses.
  • On every subsequent — fires on every event of that type EXCEPT the first. Pairs with On first to express dual-rate offers without the rules double-firing on event #1.

Event types: standard set is signup, trial_started, subscription_created, invoice_paid. A “Custom event…” escape hatch accepts any string for brands sending custom event names through the SDK.

Recurring + months cap: mark a sub-rule recurring and optionally cap how many months it keeps firing — measured from the first attributed event of that type for the partner + customer pair. Past the cap, no more commissions accrue. Null/blank = no cap (indefinite, bounded only by the program’s end date).

Examples:

OfferSub-rules
Flat 20% recurringevery / invoice_paid / 20% recurring
20% recurring, 12-month capevery / invoice_paid / 20% recurring × 12mo
$200 first-sale bonus + 20% recurringfirst / subscription_created / $200 fixed   +   every / invoice_paid / 20% recurring
50% on first invoice, 20% on every subsequent invoicefirst / invoice_paid / 50%   +   subsequent / invoice_paid / 20% recurring
$50 flat finder feefirst / signup / $50 fixed

When an event lands, the engine walks every sub-rule and emits one Commission row per match. A subscription_created event matching both a “first sale bonus” and an “every event with value” rule produces two commissions on the same Attribution — the partner sees both in their dashboard.

Customer reward (dual-sided incentives, optional)

Toggle Offer customer-side discount to add a reward for the referred customer. When set, every coupon code minted for a partner on this program also provisions a matching Stripe Coupon + Promotion Code so the discount applies automatically when the customer enters the code at your checkout. The partner still gets attribution + commission via the existing flow.

Three reward shapes:

  • % off — e.g. 25% off for 6 months
  • $ off — e.g. $20 USD off (currency required)
  • Free months — e.g. 1 month free (delivered as a 100% repeating Stripe coupon)

Duration:

  • First invoice only — single-use discount
  • Every invoice — applies to every renewal indefinitely
  • First N months — applies to the first N invoices then drops off

Without Stripe configured: the OpenPartner coupon still works for partner attribution; the discount just doesn’t auto-apply at checkout. You’d honor it manually. With Stripe configured, no manual work — Stripe enforces the discount, partners get paid, you get the new customer.

Let partners customize their coupon code

Toggle Let partners customize their coupon code to give each partner an “Add another code” affordance in their portal. Off by default — every partner gets the auto-generated code (e.g. ADALOVELACE5F2A) and only you can change it.

When on:

  • Partners can mint vanity codes like GRACIE15 or TIKTOKVIP from their dashboard
  • They can run multiple codes side-by-side per program (capped at 5 active per partner per program to keep your Stripe dashboard sane). Useful for audience-specific tracking — IG15 for Instagram, YT15 for YouTube
  • Each partner-side code provisions its own Stripe Coupon + Promotion Code, so the discount terms you set above apply automatically — partners only choose the string, never the discount
  • Codes are append-only. Renaming is “add new + deactivate old” as two clicks; the old code keeps redeeming until the partner explicitly retires it, so links and posts they already shared don’t break the moment they iterate

You can always override on a per-partner basis from Admin → Partners → [partner] → Coupons regardless of this toggle. Admin sees every code (active and deactivated) and can re-mint freely.

Attribution window

How long after a click the conversion still counts. 60 days is the default and matches what most affiliate programs use. Longer windows (90, 180 days) attribute more conversions to partners but get more disputes and double-attribution edge cases. Shorter windows (7, 30 days) are stricter and pay less.

Attribution model

What happens when a conversion has multiple clicks in the window from different partners:

  • Last click — the most recent click gets 100%. Simple, predictable, the default for most programs. Most resembles “who closed the deal.”
  • First click — the very first click gets 100%. Rewards partners who introduced the brand, not the ones who closed it.
  • Linear — every click in the window splits the commission evenly. N clicks → 1/N each.
  • Position (40 / 20 / 40) — first + last click get 40% each, middle clicks split the remaining 20%. A compromise between first-click and last-click.

You can change the model later. Past commissions don’t recompute, but new conversions use the updated model.

Starts / Ends

Optional. Leave blank to run immediately and indefinitely.

  • Before Starts: program is hidden from partners (they can’t create new Links for it).
  • After Ends: existing Links keep redirecting (so already-shared posts don’t break), but no new commissions accrue for clicks past the end date. New Link creation is also blocked.

We email all participating partners + the brand admin 7 days before an end date so nobody gets surprised.

Editing a program

Each row has two per-row actions:

  • Edit — inline form with two sections:
    • Schedule: startsAt + endsAt. Useful for scheduling a program to start later, extending an end date past the original, or marking a program Ended at a specific past time.
    • Terms: the full commission rule editor (add/remove sub-rules, change triggers, set recurring caps), the customer reward toggle, the let partners customize their coupon code toggle, and holdbackDays. Behind a banner that explains the snapshot semantics — see below.
  • End now — sets endsAt to the current time after a confirm. Hidden once the program is already Ended. Existing share-links keep redirecting (so creators’ embedded posts don’t break) — only new commission accrual stops, so it’s safe to fire.

Editing terms is safe — here’s why

OpenPartner snapshots commission terms (rate, recurring flag, holdback days) onto each Partnership at the moment the brand approves the creator’s PartnershipRequest. The snapshot lives on a PartnerCommission row on the brand’s instance, and commission accrual reads that value, not the live Program rule. So when you edit the Program’s rate from 20% to 10%:

  • Already-approved partners keep accruing at the rate they were quoted (20%)
  • New approvals get the new rate (10%)
  • Existing partnerships stay whole; you can lower a rate for new applicants without alienating creators already promoting you

This matches how mature affiliate networks (Impact, Partnerize, ShareASale) handle grandfathering. The banner above the Terms section is a reminder of this contract — edit freely, no creators get re-priced.

Per-partner commission overrides

For one-off cases (a VIP creator on a higher cut than the program default), use the Commission link on each partner’s row in Admin → Partners. The page shows the current snapshot (rate, holdback, source) and lets you set or clear an override. Stamps a PartnerCommission row with source = 'amendment', which overrides both the program rule and any earlier approval-time / backfill snapshot. Clear override drops the row and falls the partner back to the live program rule.

Past commissions aren’t recomputed when you set or change an override — only future events accrue at the new rate.

What’s still NOT editable here

destinationUrl, attributionWindowDays, attributionModel, deepLinkAllowedDomains. Reasons:

  • Destination URL — changing it redirects existing share-links to the new place, which is sometimes what you want and sometimes catastrophic. Today: publish a new program with the new destination. We’ll add inline editing once we surface a “this will change where N existing share-links land” preview.
  • Attribution window / model — these affect which clicks get credit, not the dollar amount. They’re shared across all partnerships of a program; snapshotting per-partnership would create surprising attribution divergence for clicks happening after an edit. The current “edit affects future events only, past Attribution rows stay” semantic is the honest model. The underlying PATCH /programs/:id accepts these fields if you want to edit via API.

Listing on the marketplace

Brands connected to the OpenPartner Network get two extra fields on each program:

  • shareOnNetwork — flip-on toggle. When ON, every save auto-publishes (or updates) the marketplace listing tied to this program. Defaults ON for new programs when the brand is connected; OFF for VIP / private programs you don’t want creators to discover.
  • marketplaceDescription — public copy shown on the discover card. Optional — when empty, the card renders without a description block.

That’s the whole brand-side surface. Title comes from the program’s name. Commission line is auto-derived from the rule + customer reward (no freeform “make-up your own copy” input — the listing is always faithful to what the engine will actually pay). Attribution window, holdback, end date, and customer reward all snapshot from the program at save time. Toggle off later → the listing flips to unpublished but isn’t deleted, so flipping back on restores it intact.

The previously-separate “Network → Offerings” admin page is gone — there’s nothing to manage there that isn’t already on the program. The Offering row still exists on the Network’s database as the marketplace’s storage; it’s just no longer something brand admins interact with directly.

Lifecycle states

A program at any moment is one of:

  • ScheduledstartsAt is in the future. Hidden from partners, no Link creation, no attribution.
  • Active — running. Normal behavior.
  • EndedendsAt is in the past. Existing Links still redirect; no new commissions or Link creation.

The admin UI shows the state with a colored pill on each program row. We email all participating partners + the brand admin 7 days before an end date so nobody gets surprised; pushing endsAt further out clears that flag so the warning re-fires for the new window.

Per-partner programs

Sometimes a brand wants a special program for a single partner — say, a 30% revshare for a high-volume creator. Two ways:

  1. Create the program, leave “Grant to all existing partners” unchecked. Then on the partner’s row → Programs → tick the new program.
  2. Create the program first, invite the partner second. When inviting, uncheck “Grant access to all current programs” and pick only the new one.

See invite partners for the full scoping flow.