A reward rule can give more than money, and to either side. "You both get a free month", "Give 20% off, get 10.00 in credit", "A tote bag for every friend who joins": each is a rule, set up exactly like a cash rule (see Reward rules), with two more fields.
reward_type: what it gives.cash(the default) is a commission, paid out as before;credit,free_period,discount,perkandgift_cardare grants, given in your own system or through your Stripe.beneficiary: who receives it.promoter(the default) is the person who shared;refereeis the friend who arrived through the link.
Both are fixed once the rule exists, like its event and audience: "the same reward for someone else" is a different rule. Every rule written before is cash for the promoter, and pays exactly as it did.
reward_type |
Its fields | For |
|---|---|---|
cash |
kind, percent_bps or amount_minor, duration |
the promoter only |
credit |
kind, percent_bps (of the sale) or amount_minor |
either side |
free_period |
period_count, period_unit (day 1–365 or month 1–36) |
either side |
discount |
kind, percent_bps or amount_minor, discount_duration (once, months with discount_months 1–36, forever) |
the friend only, on a sale, once per customer |
perk |
perk_text, your words, at most 120 characters |
either side |
gift_card |
kind, percent_bps (of the sale) or amount_minor |
either side |
curl -X POST https://api.boltclaw.ai/v1/referrals/programs/$PROGRAM_ID/rewards \
-H "Authorization: Bearer $BOLTCLAW_KEY" -H "Content-Type: application/json" \
-d '{"event": "sale", "reward_type": "free_period", "period_count": 1, "period_unit": "month", "duration": "once"}'
curl -X POST https://api.boltclaw.ai/v1/referrals/programs/$PROGRAM_ID/rewards \
-H "Authorization: Bearer $BOLTCLAW_KEY" -H "Content-Type: application/json" \
-d '{"event": "sale", "beneficiary": "referee", "reward_type": "discount", "kind": "percent", "percent_bps": 10000, "discount_duration": "months", "discount_months": 1}'
Those two rules are the "Refer a friend" template: you both get one free month. A rule's conditions, scope, priority and per-customer ceiling work as for cash, and each side picks its rule the same way (the most specific match wins). A milestone bonus stays cash. Cash and grants are counted apart: a program's monthly ceiling counts commissions only.
Grants
What a rule that is not cash gives is a grant: one row per person per reward, which says what it is, whose it is and where it stands.
status |
Means |
|---|---|
pending |
Waiting out the program's hold, in case the sale is refunded. |
ready |
Past the hold. Yours to give, or Bolt Claw gives it through your Stripe. |
fulfilled |
Given, with a reference. |
failed |
Could not be given yet, with your reason. You can still give it later. |
cancelled |
The sale was refunded or disputed before it was given. |
reversed |
The sale was refunded or disputed after it was given. Take it back if your own terms allow; Bolt Claw never does. |
GET /v1/referrals/programs/{id}/grants lists them (filter by status,
type or recipient), and the program's Grants tab shows the same with
a CSV export. Each names its recipient as you know them: one of your own users
by your external_id, an affiliate by their name in the program, or the friend
by your own id for the customer.
A grant for a sale reported through the API (by your server, or by an AI
assistant) is always yours to give: Bolt Claw gives automatically only for a sale
your Stripe itself reported. While Bolt Claw is giving one through Stripe, marking it
given or failed answers 409 for a few minutes, so it is never given twice.
Give it, then say so. When referral.grant.ready arrives, add the month or
the credit in your own system, then record it with your reference:
curl -X POST https://api.boltclaw.ai/v1/referrals/grants/$GRANT_ID/fulfil \
-H "Authorization: Bearer $BOLTCLAW_KEY" -H "Content-Type: application/json" \
-H "Idempotency-Key: grant-$GRANT_ID" \
-d '{"reference": "CN-20931"}'
The same reference again answers the grant as it is and changes nothing, so a
retry is safe; a different reference for a grant already given is 409. If it
cannot be given, POST /v1/referrals/grants/{id}/fail with a reason (shown to
you, not to the person) leaves it failed until you can. Both are recorded in
the activity log, and an AI assistant must always ask a person first.
Or let Stripe give it. With a restricted Stripe key set, for a sale your own
Stripe reported, a ready credit becomes a balance credit on the customer and a
ready free_period a free month
on their subscription, each called once (see
Stripe codes and credits). Anything Stripe cannot
do comes back to your list as ready, with the reason.
The friend's discount is the one grant you never give by hand: it is applied
at your checkout. Bolt Claw records it as fulfilled with the sale, and only
when the sale shows it was used: a discount code, a Stripe coupon or promotion
code on the payment, or referral.discount_applied: true in your conversion.
What stops a reward
- A refund or a dispute. Any refund of the sale cancels its grants not yet
given and marks the given ones
reversed: a free month cannot be split. - Self-referral. When the customer is the promoter themselves (your id for them, or the same email), neither side gets a grant and the conversion is flagged for you to look at.
- Signups alone. A rule on
leadis held like a sale's, and the program gives at mostlead_grant_daily_capof them a day (100 by default), so invented signups cannot farm credit. - The rule's own ceiling,
cap_minor, for credit and gift cards: the most one customer earns from it in total.
What people see
The promoter sees their grants in words on their page or in the
referral panel: "1 month free, on its way: ready on
3 Nov", then "given on 5 Nov". The friend sees their side in the
welcome. A webhook event marks each step:
referral.grant.ready, referral.grant.fulfilled, referral.grant.cancelled
and referral.grant.reversed (see Webhooks).