ripllo.referral.fulfilled.v1

Fires when a pending referral attribution turns into a real reward — the referee made a qualifying purchase and the referrer's discount code has been minted.

Reserved — not currently emitted in v1. Ripllo records fulfilment internally (visible via GET /referrals/rewards/:accountId/:customerId) but the outbox event isn't wired up yet. Subscribe defensively to handle the event when it ships; for now, poll the rewards endpoint or react to discount_code.redeemed once the referrer actually uses the minted reward.

When it will fire

When POST /api/v1/referrals/attributions/fulfill transitions an attribution from pending to fulfilled for the first time. The endpoint is idempotent — retried partner-platform calls don't re-emit.

Fulfilment requires three things to be true at the moment the partner platform posts the payment-success webhook:

  1. A pending attribution exists for (accountId, refereeCustomerId).
  2. The payment status is succeeded (not pending, not failed).
  3. The cart amount meets program.minPurchaseAmount and currency matches program.currency.

If any of those fails, the attribution stays pending (or expires later) and no event fires.

Anticipated payload

{
  "id": "evt_01HX...",
  "type": "ripllo.referral.fulfilled.v1",
  "createdAt": "2026-05-13T10:43:22.187Z",
  "accountId": "acc_01HX...",
  "data": {
    "attribution": {
      "id": "rat_01HX...",
      "referrerCustomerId": "cus_01HX...",
      "refereeCustomerId": "cus_02HX...",
      "linkCode": "ALICE-A1B2",
      "checkoutSessionId": "cs_storlaunch_01HX...",
      "status": "fulfilled",
      "fulfilledAt": "2026-05-13T10:43:22.140Z"
    },
    "reward": {
      "discountCodeId": "dc_01HX...",
      "code": "REWARD-CD3F",
      "type": "percent",
      "value": 1000,
      "currency": "IDR",
      "expiresAt": "2026-08-13T10:43:22.000Z"
    },
    "trigger": {
      "purchaseAmount": 250000,
      "currency": "IDR"
    }
  }
}

The exact shape may evolve before emission ships — consume defensively. The fields above are what's available in the corresponding API response today, so handlers written against this shape should work.

What to do (when it ships)

  • Notify the referrer. "Your friend just bought! Here's your reward code: REWARD-CD3F". The whole point of the referral program.
  • Update commission tracking. If you accrue affiliate commissions, fulfilment is the trigger.
  • Track conversion-to-fulfilment rate. Compare referral.created and referral.fulfilled counts over the same window to measure how many attributions actually convert.

Until then

Two options for getting the same signal today:

Option A: Poll the rewards endpoint. When you record a referral.created event, schedule a poll of GET /referrals/rewards/:accountId/:customerId for the referrer to see when a new reward appears. Inefficient but reliable.

Option B: React on the partner side. Storlaunch's payment-success webhook is what triggers fulfilment in Ripllo. Mirror that — whenever you see a Storlaunch order complete for a customer who was the referee of an attribution, treat it as fulfilment.

// Option B pseudo-code
storlaunch.on('order.completed', async (order) => {
  const pendingAttribution = await ripllo.referrals.attributions.findPending({
    accountId: order.merchantId,
    customerId: order.customerId,
  });
  if (pendingAttribution) {
    await notifyReferrer(pendingAttribution.referrerCustomerId);
  }
});

Neither workaround is great. Until the event ships, the simplest pattern is just to react to discount_code.redeemed when the referrer eventually uses their reward — you'll know which discount codes are reward codes by their pattern (REWARD-* by Ripllo convention).

Next