Merchant integration
Install tracking, bind a customer, and verify a commission safely.
Merchant integration
Use a test program first. The setup screen shows program, integration, click and attributed-sale checks from persisted records. A completed form alone does not mark the integration verified.
Browser and server boundary
Install /sdk/v1.js from your tracking domain asynchronously; the exact attributes and consent API
are documented in packages/tracker/README.md and apps/tracking/README.md.
Use only program-registered destination origins. The SDK receives a signed reference containing no PII.
Never put a secret API key in a browser. When consent is denied, do not create durable visitor identity.
Before checkout, send the reference from your backend to POST /api/v1/referrals/claim:
{
"programId": "your-program-id",
"customerId": "stable-customer-id",
"reference": "signed-referral-reference",
"destinationOrigin": "https://your-store.example"
}Authenticate with a test/live API key scoped to referrals:write. Use the same stable customer ID in
payment metadata or custom events. Cookie availability is browser-dependent; server claims survive
later cookie deletion. Cross-domain handoff requires an explicitly allowed destination.
Provider connections
Each connection has an independent webhook URL and encrypted credentials. Configure the provider to
send events to POST /api/v1/webhooks/{provider}/{connectionId}. Supported IDs are stripe, paddle,
lemonsqueezy, moyasar, tap, paytabs, and custom.
The SDK has no authority to declare revenue or a commission. Provider native capabilities are returned
by /api/v1/capabilities; the UI shows those capabilities. See packages/affiliate/README.md for
signature algorithms, canonical financial keys and unsupported reconciliation cases.
| Provider | Confirmed sale source | Notes |
|---|---|---|
| Stripe | Paid invoice or independent successful payment intent | Invoice-backed payment intents are not double-counted |
| Paddle | Completed transaction | Refund and chargeback adjustments |
| Lemon Squeezy | Subscription invoice or one-time order | Initial-payment aliases prevent duplicate credit |
| Moyasar | Trusted API payment with paid/captured status | JSON secret_token plus retrieval; custom lifecycle supplements |
| Tap | Trusted CAPTURED charge | hashstring plus retrieval of unsigned fields |
| PayTabs | Successful Sale/Capture | Raw-body signature; refund links to original transaction |
| Custom | Authenticated canonical event | Stable customer/payment/adjustment identities required |
Custom events
POST /api/v1/events requires a scoped events:write API key and Idempotency-Key header.
The full contract is served at /api/v1/openapi.json. Example sale:
{
"id": "evt_sale_001",
"connectionId": "your-custom-connection",
"type": "payment.succeeded",
"occurredAt": "2026-09-22T12:00:00Z",
"customerId": "stable-customer-id",
"paymentId": "stable-payment-id",
"currency": "USD",
"amountMinor": "4900",
"taxMinor": "0",
"eligibleMinor": "4900"
}All amounts are decimal integer strings in minor units. Do not submit a commission amount.
For refunds include a stable adjustmentId and explicit refundMode (incremental or cumulative).
For recurring commission duration and MRR include subscription identity, paid period and cadence.
Unknown tax/attribution data leaves the sale pending; it must not silently produce an inaccurate commission.
Replaying the same event/key with a different payload is a conflict. Retry network failures with the same
stable key. A 202 response means durable reception, not necessarily a completed commission.
Verify the result
- Open a real affiliate link in the test program and grant tracking consent when appropriate.
- Bind the reference on the merchant server before checkout.
- Complete a provider sandbox payment or send a signed custom test event.
- Verify the conversion, recorded attribution evidence, rule version, fraud decision and ledger.
- Repeat the event; totals must stay unchanged. Send a partial refund and verify the reversal.
- Prepare a payout with one account, approve it with another authorized account, export it and record an external confirmation. Exporting alone never marks money paid.
First/last touch uses server-recorded touch order. Renewal attribution is pinned to the original eligible subscription association. MRR is unavailable without valid paid subscription data; CTR is unavailable without impressions; ROI requires program cost records. Currencies remain separate.