Custom Checkout
Overview
If you're not using Stripe or Paddle — or need custom attribution logic — you can create commissions directly via the Affihub API. This works with any payment provider, custom checkout, or billing system.
When to use this
- Payment providers other than Stripe or Paddle (e.g., Razorpay, Lemonsqueezy, Gumroad)
- Internal billing systems
- Marketplace transactions
- Manual sales or invoicing
- Complex multi-step checkout flows
Step 1: Capture the referral
The tracking script works the same regardless of your payment provider. Install it on your site and read the referral at checkout:
const ref = window.AffiHub.getRef();
// { ref: "partner-slug", program: "prog_xxx" }Send this data to your server alongside the transaction:
fetch("/api/checkout", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
// ... your checkout data
affihub_ref: ref?.ref || null,
}),
});Step 2: Look up the partner
On your server, after a successful payment, resolve the partner slug to a partner ID:
curl -X GET "https://api.affihub.com/api/v1/partners?search=partner-slug" \
-H "Authorization: Bearer YOUR_API_KEY"Response:
{
"data": [
{
"id": "par_abc123",
"slug": "partner-slug",
"email": "partner@example.com",
"status": "active"
}
]
}Step 3: Evaluate commission (optional)
If you want to use your flow rules to determine the commission amount, you can query your flows and evaluate them in your application logic. Alternatively, calculate the commission yourself based on your business rules.
The standard formula:
const txnAmountCents = 9900; // $99.00
const commissionPct = 20; // 20%
const commissionCents = Math.floor(
(txnAmountCents * Math.round(commissionPct * 100)) / 10000
);
// commissionCents = 1980 ($19.80)Step 4: Create the commission
Use the events endpoint to log the transaction. The webhook handler uses the same internal attribution function, but for custom integrations you'll create the event directly:
curl -X POST "https://api.affihub.com/api/v1/events" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "transaction_completed",
"payload": {
"partner_slug": "partner-slug",
"txn_amount_cents": 9900,
"customer_email": "customer@example.com",
"provider_event_id": "your-unique-transaction-id"
}
}'Always include a unique provider_event_id to prevent duplicate commissions if you retry the request.
Full server-side example (Node.js)
const AFFIHUB_API_KEY = process.env.AFFIHUB_API_KEY;
const BASE_URL = "https://api.affihub.com";
async function createCommission({ partnerSlug, txnAmountCents, customerEmail, txnId }) {
// Look up partner
const partnerRes = await fetch(
`${BASE_URL}/api/v1/partners?search=${partnerSlug}`,
{ headers: { Authorization: `Bearer ${AFFIHUB_API_KEY}` } }
);
const { data: partners } = await partnerRes.json();
const partner = partners.find((p) => p.slug === partnerSlug);
if (!partner || partner.status !== "active") {
console.log("Partner not found or inactive");
return;
}
// Create event for attribution
const eventRes = await fetch(`${BASE_URL}/api/v1/events`, {
method: "POST",
headers: {
Authorization: `Bearer ${AFFIHUB_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
type: "transaction_completed",
payload: {
partner_slug: partnerSlug,
txn_amount_cents: txnAmountCents,
customer_email: customerEmail,
provider_event_id: txnId,
},
}),
});
const result = await eventRes.json();
console.log("Commission created:", result);
}
// After a successful payment:
createCommission({
partnerSlug: "john",
txnAmountCents: 4900,
customerEmail: "buyer@example.com",
txnId: `txn_${Date.now()}`,
});Deduplication
Use the provider_event_id field to ensure idempotency. If you send the same provider_event_id twice, the second request will be ignored. Use your payment system's transaction ID for this field.
Differences from webhook integrations
| Feature | Stripe/Paddle Webhooks | Custom Checkout |
|---|---|---|
| Commission creation | Automatic | You call the API |
| Signature verification | Built-in | Not applicable |
| Flow rule evaluation | Automatic | Manual or via API |
| Deduplication | By event ID | By provider_event_id |
| Refund handling | Automatic (Paddle) | You handle it |