Selling through Polar, Paddle, Creem, or Dodo

Connect non-Stripe billing platforms so sales and refunds attribute to your partners automatically — webhook setup, click-id passing, and what stays Stripe-only.

Partli's deepest integration is Stripe (automatic checkout injection, coupon-code attribution, Connect payouts). If you sell through Polar, Paddle, Creem, or Dodo Payments, Partli listens to their webhooks instead: paid orders become attributed sales, refunds claw commissions back, and renewals keep earning recurring commissions. Partner payouts still run through Stripe Connect regardless of how you bill customers.

Setup (any provider)

  • Open Settings → Billing integrations in your workspace.
  • Click Connect on your provider and paste its webhook signing secret.
  • Copy the webhook URL Partli shows you and add it as an endpoint in the provider's dashboard.
  • Send a test event (all three dashboards can) — the integration card shows last event when it arrives.

Passing the click id

Attribution needs the visitor's Partli click id to reach the order. Hosted payment links are handled automatically: with the tracking snippet installed, clicks on Polar checkout links and Creem payment links are decorated with the click id, and Paddle's Paddle.Checkout.open gets it merged into customData — no code needed. Only API-created checkout sessions (built on your server) need you to pass Partli.getClickId() yourself as metadata under partli_click_id:

Polar

// API-created checkout sessions:
await polar.checkouts.create({
  products: ["prod_..."],
  metadata: { partli_click_id: clickIdFromYourFrontend },
});

// Hosted checkout links: automatic — partli.js appends ?reference_id=<clickId>.

Webhooks to enable: order.paid and order.refunded. Commissions are computed on the order's post-discount amount.

Paddle

// Automatic — partli.js wraps Paddle.Checkout.open and merges
// customData.partli_click_id. Explicit form (if you prefer):
Paddle.Checkout.open({
  items: [{ priceId: "pri_..." }],
  customData: { partli_click_id: Partli.getClickId() },
});

Webhooks to enable: transaction.completed and the adjustment events (approved full refunds claw back). The secret is the endpoint's pdl_ntfset_… key from Developer tools → Notifications.

Creem

// API-created checkout sessions:
await creem.createCheckout({
  product_id: "prod_...",
  metadata: { partli_click_id: clickIdFromYourFrontend },
});

// Hosted payment links: automatic — partli.js appends
// ?metadata[partli_click_id]=<clickId> on click.

Webhooks to enable: checkout.completed, subscription.active, subscription.paid, and refund.created. Subscription checkouts are credited from the subscription events (never double-counted with the checkout event).

Dodo Payments

// API-created checkout sessions:
await dodo.checkouts.create({
  product_cart: [{ product_id: "prod_...", quantity: 1 }],
  metadata: { partli_click_id: clickIdFromYourFrontend },
});

// Static payment links (checkout.dodopayments.com/buy/...): automatic —
// partli.js appends ?metadata_partli_click_id=<clickId> on click.

Webhooks to enable: payment.succeeded (covers one-time purchases and every subscription charge) and refund.succeeded (full refunds claw back). The secret is the endpoint's key from Developer → Webhooks.

What stays Stripe-only

  • Coupon-code attribution — per-partner discount codes are provisioned on your Stripe account. On other providers, attribution is link-based (click id).
  • Automatic checkout injection — partli.js auto-fills Stripe Checkout; for the providers above you pass partli_click_id yourself as shown.
  • Partner payouts aren't affected: they always run via Stripe Connect from your payout balance, whatever you bill with.

No click id? Nothing is credited — but nothing is lost

If an order arrives without a click id, no commission is created (the miss is logged server-side). When a partner tells you about a referral you can credit it manually with the "Attribute sale" action on their page — it's deduped by the same order id, so a later webhook retry can't double-count it.