Connect RevenueCat

RevenueCat reports what the App Store, Google Play and the other stores charged, so one connection covers every app in your project. You create the webhook in your own RevenueCat project, switch on its signing, and paste the signing secret into Klibon. Klibon also needs a read-only key, used for one thing: listing your products, so each can pay its own rate. A program activates only once one of its products pays, so the key is part of setup — you can save the secret first and add the key afterwards.

Create the webhook

  1. In RevenueCat, open your project and go to Integrations → Webhooks → Add new configuration.
  2. Paste the URL shown on your program's Setup page:
    webhook URL
    https://klibon.com/api/webhooks/revenuecat/<program_id>
  3. Send both production and sandbox purchases, for all apps in the project. Leave the authorization header empty: Klibon does not read it.
  4. If you filter by event type, keep the four events below. Sending every event works too: Klibon ignores the rest.
  5. Save, open the webhook again and switch on HMAC webhook signing. RevenueCat shows the signing secret once: copy it and paste it into Klibon.

Signing is what lets Klibon tell a real event from a forged one, and it is off by default. A webhook without it is refused, and your Setup page says so. Webhooks are part of RevenueCat's Pro plan.

Add the read-only key

  1. In RevenueCat, go to API keys and create a new secret API key, with V2 as the version.
  2. Set Project configuration to Read only, and leave everything else on No access.
  3. Generate it, copy the key — it starts with sk_ — and paste it into Klibon.

Klibon reads the project the key belongs to and the products in it, and nothing about your customers. The appl_ and goog_ keys your app ships with are public SDK keys and cannot list products.

A plan sold by two apps — the same premium_monthly on iOS and on Android — is one line on your Rates page, with one rate. Products are named by their store identifier, which is how RevenueCat names a purchase on its webhooks. The price shown next to each is RevenueCat's indicative US price, there to help you tell plans apart: commissions are computed on what each customer actually paid.

Getting the referral code to RevenueCat

A web checkout carries the code with the payment. An in-app purchase cannot: the visitor clicks an affiliate's link, lands on your site, installs the app from a store, and the store forgets where they came from. So the code travels on the customer instead. RevenueCat repeats a customer's attributes on every event, which means the first purchase and every renewal arrive attributed.

Save the code on the account, set it in the app

The sturdy way, for an app whose users have an account. Keep the code when the user signs up on your website:

browser
// On your website, where the tracking script runs.
// The referral code it is holding for this visitor, or null.
const code = window.Klibon?.referral() ?? null

// Send it with your signup request and save it on the account.
await fetch('/api/signup', {
  method: 'POST',
  body: JSON.stringify({ email, password, referralCode: code })
})

Then, in the app, set it as the customer attribute klibon once the user is logged in. Set nothing for an account with no code.

swift
// Once the user is logged in, before any purchase.
if let code = account.referralCode {
    Purchases.shared.attribution.setAttributes(["klibon": code])
}
kotlin
// Once the user is logged in, before any purchase.
account.referralCode?.let { code ->
    Purchases.sharedInstance.setAttributes(mapOf("klibon" to code))
}
javascript
// React Native and Flutter. Once the user is logged in, before any purchase.
if (account.referralCode) {
  await Purchases.setAttributes({ klibon: account.referralCode })
}

Set it before the purchase, not after. The SDK sends attributes to RevenueCat when the app starts, when it goes to the background and when a purchase is made, so an attribute set at login is there in time. If the first purchase did leave without it, the next renewal carries it and is credited then.

Or match by email

If you would rather not store the code yourself, report the signup on your website and give RevenueCat the same email. A purchase made under that address is credited to the affiliate behind the signup, whichever device it is made on (Klibon.signup()).

browser and app
// On your website, right after the account is created.
window.Klibon?.signup(email)

// In the app, with the same address (Swift shown; every SDK has setEmail).
Purchases.shared.attribution.setEmail(email)

Klibon never stores the address: it compares salted hashes, and drops every customer attribute but klibon before an event is saved.

Offer codes

RevenueCat names the offer a customer redeemed on the App Store or Google Play (offer_code on the event). Create an offer for an affiliate, add its name to one of their coupon codes as a processor id, and a purchase that redeemed it is credited to them with nothing to set in the app. Check the exact name on a first event in your Events tab: the stores report the offer's reference, which is not always the code the customer typed.

Web purchases

Links to a RevenueCat web purchase link on your site are decorated by the tracking script on the way out, with the referral code as metadata and the affiliate's discount code when the visitor has one:

purchase link
https://pay.rev.cat/<token>/<app_user_id>?metadata[klibon]=<code>&discount_code=<coupon>

With RevenueCat's Web SDK, pass the code yourself:

browser
const code = window.Klibon?.referral() ?? null

await Purchases.getSharedInstance().purchase({
  rcPackage: pkg,
  // RevenueCat puts this on the first event of the purchase.
  metadata: code ? { klibon: code } : undefined
})

RevenueCat sends metadata with the first event of a purchase only. Renewals are credited through the customer the first payment was recorded for.

Check it works

  1. The webhook. Send a test event from the webhook's page in RevenueCat, or make a sandbox purchase in your app. The conversion source on your Setup page turns to Verified as soon as a signed event arrives.
  2. Tracking. Your Setup page shows your test link and the code at the end of it. Set that code as the klibon attribute in a development build, and buy once in the sandbox. The tracking step turns green when the code reaches Klibon.

A sandbox purchase never earns a real affiliate anything. Your own test link is the exception, which is what makes it a test link.

What each event becomes

RevenueCat eventIn Klibon
INITIAL_PURCHASEA sale. A free trial is recorded at no amount, and keeps the referral for the payment that follows.
RENEWALA renewal, including the first payment after a free trial.
NON_RENEWING_PURCHASEA sale: a lifetime unlock, a consumable, anything that does not renew.
CANCELLATIONA refund, when its reason is CUSTOMER_SUPPORT. A customer switching off auto-renewal changes nothing.

Everything else is ignored. A PRODUCT_CHANGE moves no money by itself: the purchase or renewal RevenueCat sends alongside it is what counts, at the new product's price and rate. A promotional entitlement you grant yourself is not a purchase, and neither is a purchase shared with a family member.

What the commission is calculated on

The price the customer paid, in the currency they paid in, less the share of it the store collected as tax. RevenueCat estimates that share for each purchase, and where it reports none, the whole price counts.

The store's own commission is not deducted — 15 to 30% on the App Store and Google Play — exactly as a card processor's fee is not deducted on a web checkout. Set your rates with it in mind: a 30% commission on a purchase Apple keeps 30% of leaves you 40%.

Refunds

RevenueCat has no refund event. It sends a CANCELLATION whose reason is CUSTOMER_SUPPORT, carrying the amount given back, and Klibon reverses the commission of that payment. Two limits come from RevenueCat itself:

  • It reports the refund of a subscription's latest period only. A refund of an earlier period never reaches Klibon: adjust that commission by hand.
  • A refund the store later reverses arrives as REFUND_REVERSED, which Klibon logs and does not act on. The commission stays reversed.

Selling through Stripe or Paddle as well

RevenueCat can also report purchases made through your own Stripe or Paddle account. Connect each of those to Klibon once: through RevenueCat or directly, not both, or the same payment arrives twice under two different ids.

Troubleshooting

Signature failures

Klibon shows "Error" on your Setup page when an event does not verify. Either HMAC webhook signing is switched off on the webhook, or the secret has been rotated since you pasted it: rotating invalidates the old one at once. Rotate it again, and paste the new one.

Events arrive but nothing is attributed

Open the event in the Events tab. Not referred means the customer carried no klibon attribute and no email Klibon knows. Look the customer up in RevenueCat: if the attribute is missing there, the app never set it, or set it after the purchase.

The key is refused

It has to be a V2 secret key: a V1 key cannot call the API Klibon reads. And Project configuration has to be at least Read only.