Contents

Your product team just dropped a new referral program on your sprint: when a user invites a friend and that friend pays their first invoice, the referrer gets a $20 reward. The ticket's on you. What do you do?

The catch: the reward should only fire when the referred user actually pays, not just when they sign up. And it must only pay out once per referral, even if your webhook fires twice or your server retries the request.

We'll build this end to end with Blnk Finance, from crediting the reward when a referred user converts, all the way to processing the payout.

Mental model

Let's say you're building Flowly, a SaaS product with a subscription model. Your referral program works like this: Claire refers James, James signs up and pays for a subscription, and Claire gets $20 credited to her balance. The reward only fires after James pays, not when he signs up.

Before you touch any code, you need to define how money should move when a referral converts. For Flowly, there are two movements:

  • Pay-in: @ReferralExpensereferrer_wallet. When a referred user converts, Blnk credits the reward into the referrer's wallet.
  • Pay-out: referrer_wallet@Payout. When you're ready to settle, Blnk moves the earned balance out to your payout provider for processing, e.g. Stripe, Adyen, Paystack, etc.

@ReferralExpense is a system balance that records every reward as an expense, giving you a real-time view of your Customer Acquisition Cost (CAC). Because it starts at zero and isn't pre-funded, you'll set allow_overdraft: true on each reward transaction.

The money movement map shows the pay-in flow (@ReferralExpense → referrer wallet) and the pay-out flow (referrer wallet → @Payout). Try it in our Money Movement Map tool.

Structuring your flows this way means you can query each balance to show your users exactly what they care about: total referrals earned, total paid out, and total pending payout.

Step 1: Setting up the referral ledger

Before you record any reward transactions, you need three things in place. Make sure you have a running Blnk instance before continuing.

  1. Create a ledger to group all referrer wallets separately from the rest of your financial activity. We'll call it "Referral Ledger."
  2. Create an identity for each referrer. This represents a real person in your ledger, so you can assign balances to them.
  3. Create a balance and link it to the identity. This is the referrer's wallet — every reward credit and payout debit is recorded against it.
The Blnk Cloud dashboard showing our Referral Ledger with two referrer wallets created under it.

The ledger groups the wallets, the identity ties each wallet to a user, and the balance tracks every credit and debit. Together, they give you the structure to record reward transactions.

Step 2: Recording the referral reward

When James signs up using Claire's referral code, your app logs the relationship and tracks whether a reward should fire:

```

--CODE language-javascript--

if (referral.status === "converted") {
 return fire_reward
} else {
 return no_reward
}

```

When James pays, record the reward to Claire's wallet in Blnk:

```

--CODE language-bash--

curl -X POST http://localhost:5001/transactions \
 -H "Content-Type: application/json" \
 -H "X-blnk-key: YOUR_API_KEY" \
 -d '{
   "precise_amount": 2000,
   "precision": 100,
   "reference": "reward-claire-referral-james",
   "currency": "USD",
   "source": "@ReferralExpense",
   "destination": "referrer-wallet-claire",
   "allow_overdraft": true,
   "description": "Referral reward: james converted",
   "meta_data": {
     "referral_code": "FLOWLY-CLAIRE",
     "referred_user": "james",
     "trigger": "subscription_payment_confirmed"
   }
   }'

```

A successful response looks like this:

```

--CODE language-json--

{
 "transaction_id": "txn_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
 "status": "APPLIED",
 "precise_amount": 2000,
 "precision": 100,
 "currency": "USD",
 "source": "@ReferralExpense",
 "destination": "bln_referrer_wallet_claire_123",
 "reference": "reward-claire-referral-james"
}

```

Here's what happens:

  • precise_amount: 2000 with precision: 100 is $20
  • @ReferralExpense sends out $20
  • referrer-wallet-claire receives $20
  • The reference must be unique. Blnk discards any transaction that reuses an existing reference, so duplicate webhooks or server retries won't pay out twice.
The transactions table shows the referral commission transaction — $20 (USD) debited from @ReferralExpense and credited to Claire Chen's wallet, with status Applied.

Step 3: Processing the payout

When you're ready to settle, retrieve all referrer balances greater than zero:

```

--CODE language-bash--

curl -X POST http://localhost:5001/balances/filter \
 -H "Content-Type: application/json" \
 -H "X-blnk-key: YOUR_API_KEY" \
 -d '{
   "filters": [
     {"field": "balance", "operator": "gt", "value": 0}
   ]
 }'

```

For each one, process a payout transaction that moves the full amount to @Payout, zeroing out the balance. For Claire's payout:

```

--CODE language-bash--

curl -X POST http://localhost:5001/transactions \
 -H "Content-Type: application/json" \
 -H "X-blnk-key: YOUR_API_KEY" \
 -d '{
   "precise_amount": 2000,
   "precision": 100,
   "reference": "payout-claire-2026-02-24",
   "currency": "USD",
   "source": "referrer-wallet-claire",
   "destination": "@Payout",
   "description": "Referral payout: scheduled",
   "meta_data": {
     "payout_provider_id": "po_stripe_98765xyz"
   }
 }'

```

A successful response looks like this:

```

--CODE language-json--

{

 "transaction_id": "txn_f9e8d7c6-b5a4-3210-fedc-ba9876543210",
 "status": "APPLIED",
 "precise_amount": 2000,
 "precision": 100,
 "currency": "USD",
 "source": "bln_referrer_wallet_claire_123",
 "destination": "@Payout",
 "reference": "payout-claire-2026-02-24"
}

```

Here's what happens:

  • referrer-wallet-claire sends out $20
  • @Payout receives $20
  • Your payout provider transfers the $20 to Claire's actual bank account

Once the money hits @Payout, it's out of your ledger. With this setup, your finance team can query @Payout to see how much was paid out in total and compare it against your payment provider statements to catch any drift.

The Blnk Cloud dashboard after the payout transaction — $20 (USD) debited from Claire Chen's referrer wallet and credited to @Payout, with status Applied.

What else can you build?

You now have a working referral system: reward on conversion, payout on schedule, full audit trail. The same building blocks can take you further:

  • Double-sided rewards. Credit both the referrer and the referred user when a conversion happens. Two transactions, same trigger.
  • Tiered rewards. Bump the reward amount after 5, 10, or 20 successful referrals. Your app checks the referrer's conversion count before setting the amount on the transaction.
  • Reward expiry. Set a deadline for referrers to claim their balance. If it lapses, move the unclaimed amount back to @ReferralExpense.
  • Commission-based rewards. Instead of a flat $20, pay a percentage of the referred user's subscription for N months. Calculate the amount per billing cycle and fire a reward transaction each time.

Ready to start building? Create a free Blnk Cloud account and follow along with the Blnk docs.