Conversions API
For everything Klibon has no connector for. You tell Klibon a payment happened; Klibon does the attribution and the commission. One endpoint, idempotent on your own event id.
Endpoint
POST https://klibon.com/api/v1/conversions, with a JSON body and an API key in the Authorization header.
Authentication
Create a key on your program's Setup page. It starts with klb_ and is shown once — Klibon only stores a hash of it. Send it as a bearer token: Authorization: Bearer klb_….
A key belongs to a product, not to a program, so a leaked key can only ever write events for that one product. Creating a key also connects the generic processor to your program, which counts against your plan's processors-per-program limit — the same as adding Stripe.
Body
Two combinations are enforced:
- A refund must carry
payment_id. - A sale or renewal must carry at least one of
referral_code,discount_code,customer_idorcustomer_email— something to attribute it by.
Example
curl -X POST https://klibon.com/api/v1/conversions \
-H "Authorization: Bearer klb_your_key" \
-H "Content-Type: application/json" \
-d '{
"event_id": "inv_9f21c4",
"type": "sale",
"amount": 1999,
"currency": "USD",
"referral_code": "ada",
"customer_id": "cus_8817",
"customer_email": "[email protected]",
"payment_id": "pay_44120"
}'A new event answers 201:
{
"received": true,
"duplicate": false,
"event_id": "inv_9f21c4",
"outcome": "commission"
} The same event_id again answers 200 and does nothing. This is what makes a retry safe:
{
"received": true,
"duplicate": true,
"event_id": "inv_9f21c4"
}Outcomes
outcome says what the event turned into. It is informational — the event is stored either way, and none of these values mean you should send it again.
commission— A commission was written.reversed— A refund reduced or reversed an existing commission.duplicate_payment— This payment already reached Klibon through another event.no_attribution— Nothing tied this payment to an affiliate. Most sales are simply not referred.no_commission— Attributed, but nothing earned — a zero amount, terms past their duration, a product you set to earn nothing, or a test-mode payment on a live affiliate. The Events tab says which.deferred— Stored, decided later: a refund that overtook its sale, or a program not activated yet. Nothing is lost, and nothing needs re-sending.
Refunds
Send the amount of that refund, not a running total. Klibon adds up the refunds it has already seen for the payment and reverses the commission in proportion. Two partial refunds of 1000 on a 2000 payment are two calls of 1000, not 1000 then 2000.
{
"event_id": "rfnd_2210",
"type": "refund",
"amount": 1999,
"currency": "USD",
"payment_id": "pay_44120"
}A refund that arrives before the sale it reverses is held and retried for three days rather than dropped. A refund on a commission already paid out becomes a negative line on the affiliate's next statement.
Errors
400— the product runs several programs and the body named none.401— the key is missing, unknown or revoked.404— thatprogram_iddoes not belong to this key's product.409— the product has no active program.422— the body did not validate, or one of the two required combinations above is missing. The message says which.
Every error is safe to retry with the same event_id once you have fixed the cause.
In code
async function reportConversion(body) {
const response = await fetch('https://klibon.com/api/v1/conversions', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.KLIBON_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(body)
})
// Retry with the SAME event_id. A repeat is ignored; a call never made is a lost commission.
if (!response.ok) {
throw new Error(`Klibon ${response.status}: ${await response.text()}`)
}
return await response.json()
}
await reportConversion({
event_id: invoice.id,
type: 'sale',
amount: invoice.total_cents,
currency: invoice.currency,
referral_code: referralCode, // window.Klibon.referral(), carried through your checkout
customer_id: customer.id,
customer_email: customer.email,
payment_id: payment.id
}) Call it from the same place you already fulfil an order — your processor's own webhook is usually the right spot, because it is the point where the money is confirmed. Get referral_code there by carrying window.Klibon.referral() through your checkout; see Install the script.