Appearance
FAST Rewards Guide
Rewards are the bonus/incentive engine. Users receive tangible benefits (bonus balance, discounts, better profit splits) either from achievement links, standalone reward rules, or manual operator grants.
The rewards system operates independently from achievements. See Achievements Guide for the badge system.
Table of Contents
- Quick Start
- Availability
- Architecture
- Two Ways to Trigger Rewards
- Reward Types
- Apply Modes
- Expiry and Stacking
- How Rewards Are Consumed
- Criteria Types (for Reward Rules)
- API Reference
- Widget Display
- Cookie Recipes
- Webhooks
- Limitations
Quick Start
With Challenges (full mode)
- Create reward rules in the backoffice (Reward Rules page)
- Users earn rewards automatically when criteria are met
- Rewards apply on next challenge purchase or funded account creation
- Widget shows pending rewards in the Rewards tab
Without Challenges (engagement-only mode)
- Create reward rules with standalone types (
free_bet,bonus_credit,cashback_credit,loyalty_points,custom) - Users earn rewards from bet activity (missions, achievements, rules)
- FAST emits
reward.grantedwebhook to your backend - Your backend credits the reward in your sportsbook (free bet, bonus balance, etc.)
- Widget shows earned rewards in the Rewards tab
No code changes needed for either mode. No achievement required.
Availability
Rewards are available on Growth and Enterprise plans. Independent from achievements - you can have rewards without badges, or both.
| achievements | rewards | What happens |
|---|---|---|
| off | off | Nothing |
| on | off | Badges only. Achievement-linked rewards are NOT granted. |
| off | on | Reward rules fire. No badges. Pure bonus engine. |
| on | on | Full: badges + reward rules + achievement-linked rewards |
How It Works
Reward rules are evaluated on every lifecycle event (bet placed, settled, challenge completed, etc.). When a user meets the criteria for a rule, a pending reward is granted and a reward.granted webhook fires.
Pending rewards are consumed automatically at the next relevant action:
- On challenge purchase: balance bonuses, discounts, and extended duration are applied.
- On funded account creation: profit split boosts and payout cap boosts are applied.
When rewards are consumed, a reward.applied webhook fires. Reward consumption is atomic - if the purchase or creation fails, rewards remain pending.
Two Ways to Trigger Rewards
1. Reward Rules (standalone, no achievement needed)
Reward rules have their own criteria. When criteria are met, the reward is granted directly. No badge, no points. Just the bonus.
json
POST /v1/admin/reward-rules
{
"name": "10 Bets Bonus",
"criteria": { "type": "bets_placed", "threshold": 10 },
"rewardType": "balance_bonus",
"rewardValue": 10,
"applyMode": "auto",
"maxGrantsPerUser": 1
}This means: "When a user places 10 bets, give them 10 EUR bonus on their next challenge. One time only."
2. Achievement-linked rewards
Add a reward field to an achievement. When the achievement is earned, the reward is auto-granted.
json
POST /v1/admin/achievements
{
"code": "streak_7",
"criteria": { "type": "streak_days", "threshold": 7 },
"reward": { "type": "balance_bonus", "value": 10, "apply_mode": "auto" }
}3. Manual grants (promotions, support, campaigns)
json
POST /v1/admin/rewards/grant
{ "userId": "player-42", "rewardType": "purchase_discount_percent", "value": 20, "expiresInDays": 7 }Or bulk:
json
POST /v1/admin/rewards/bulk-grant
{ "userIds": ["p1","p2","p3"], "rewardType": "balance_bonus", "value": 5, "applyMode": "claim" }Reward Types
Challenge-Coupled (require challenges module)
| Type | Effect | Value meaning | Consumed when |
|---|---|---|---|
balance_bonus | +EUR to starting balance | EUR (e.g., 10 = +10 EUR) | Next challenge purchase |
balance_boost_percent | +% to current active balance | % (e.g., 5 = +5%) | Immediately on grant/claim |
purchase_discount_percent | % off purchase price | % (e.g., 15 = 15% off) | Next challenge purchase |
purchase_discount_fixed | Flat EUR off purchase | EUR (e.g., 5 = -5 EUR) | Next challenge purchase |
profit_split_boost | Better user share on funded account | % points (e.g., 2 = 80/20 becomes 82/18) | Next funded account |
extended_duration | Extra days on challenge | Days (e.g., 5 = +5 days) | Next challenge purchase |
payout_cap_boost_percent | Higher payout cap | % points (e.g., 10 = 50% becomes 60%) | Next funded account |
payout_bonus_percent | Bonus on top of a payout, paid by you | % of the payout (e.g., 10 = +40 EUR on a 400 EUR payout) | Next executed payout (a rejected one leaves it pending) |
payout_bonus_percent does not touch the balance or the profit split: the user receives userPayout + ownStakeReturned + rewardBonus, and rewardBonus appears in the payout response, the funded_account.payout webhook and the payout request record.
If challenges are disabled or user has no challenge: these rewards accumulate as pending and apply when/if a challenge is eventually purchased. They never expire (unless expiresInDays is set).
Standalone (no challenge dependency)
These work without the challenges module. FAST grants the reward and emits a reward.granted webhook. The operator fulfills it on their side (credits the free bet, adds balance, etc.).
| Type | Effect | Value meaning | Fulfillment |
|---|---|---|---|
free_bet | Free bet credit | EUR amount (e.g., 5 = 5 EUR free bet) | Operator via webhook |
bonus_credit | Bonus added to sportsbook balance | EUR cents (e.g., 1000 = 10 EUR) | Operator via webhook |
cashback_credit | Cashback returned to player | EUR cents (e.g., 500 = 5 EUR) | Operator via webhook |
loyalty_points | Points added to loyalty balance | Points count (e.g., 500 = +500 pts) | FAST loyalty engine |
custom | Operator-defined (merch, VIP, etc.) | Operator-defined meaning | Operator via webhook |
Example webhook for standalone reward:
json
{
"eventType": "reward.granted",
"userId": "player-42",
"data": {
"rewardId": "uuid",
"rewardType": "free_bet",
"rewardValue": 500,
"applyMode": "auto",
"achievementId": null
}
}The operator receives this and credits the free bet in their sportsbook. FAST marks the reward as consumed immediately (auto mode) since fulfillment is external.
Apply Modes
| Mode | Behavior | Best for |
|---|---|---|
auto | Silent. Applies on next action. For balance_boost_percent, applies immediately. | Background loyalty perks |
claim | User sees it in widget, must click "Claim". | Engagement, visible incentives |
Expiry and Stacking
Expiry: Set expiresInDays (or expires_in_days in rule). null = never expires.
Stacking: Multiple rewards of the same type accumulate. Two purchase_discount_percent rewards (10% + 15%) = 25% off. Total discount capped at purchase price.
How Rewards Are Consumed
During challenge purchase (atomic, same transaction):
- Pending rewards are loaded and locked
- Applied: add to balance, subtract from price, extend duration
- Each reward is marked as consumed (with reference to the challenge)
reward.appliedwebhook fires
During funded account creation (atomic, same transaction):
- Pending rewards are loaded and locked
- Applied: boost profit split, boost payout cap
- Each reward is marked as consumed
reward.appliedwebhook fires
If the purchase or creation fails (rollback), rewards are NOT consumed. The operation is atomic.
Criteria Types (for Reward Rules)
Same as achievements. Full list:
| Type | Measures | Threshold | Triggered by |
|---|---|---|---|
bets_placed | Total accepted bets | Count | Every bet |
bets_won | Won bets | Count | Settlement |
streak_days | Current consecutive days | Days | Bet placement |
longest_streak | Best-ever streak | Days | Bet placement |
challenges_completed | Completed challenges | Count | Completion |
challenges_failed | Failed challenges | Count | Failure |
first_withdrawal | Has withdrawn | 1 | Withdrawal |
total_wagered | Cumulative stake (cents) | Cents | Every bet |
odds_above | Highest odds placed | Decimal | Every bet |
odds_won_above | Highest odds of a winning slip | Decimal | Settlement |
win_streak | Winning slips in a row, in the order FAST recorded the results; a loss resets it, a void is skipped | Count | Settlement |
clean_days | Distinct betting days after the day whose losses last triggered a cooldown (all betting days if there never was one) | Days | Every bet |
active_days | Distinct active days | Count | Every bet |
funded_account | Has funded account | 1 | Creation |
win_rate | Win % (min 10 bets) | 0-100 | Settlement |
total_profit | Total EUR withdrawn | EUR | Withdrawal |
comeback | Failed N then completed | Failures | Completion |
API Reference
Reward Rules (operator)
| Method | Endpoint | Purpose |
|---|---|---|
| GET | /v1/admin/reward-rules | List all reward rules |
| POST | /v1/admin/reward-rules | Create a rule |
| PUT | /v1/admin/reward-rules/:id | Update a rule |
| DELETE | /v1/admin/reward-rules/:id | Delete a rule |
Reward Management (operator)
| Method | Endpoint | Purpose |
|---|---|---|
| GET | /v1/admin/rewards?userId=X | Pending rewards for user |
| GET | /v1/admin/rewards/history?userId=X | Applied reward history |
| POST | /v1/admin/rewards/grant | Grant single reward |
| POST | /v1/admin/rewards/bulk-grant | Grant to multiple users (max 500) |
| DELETE | /v1/admin/rewards/:id | Revoke pending reward |
Public (widget key)
| Method | Endpoint | Purpose |
|---|---|---|
| GET | /v1/users/:userId/rewards | Pending + claimable rewards |
| POST | /v1/users/:userId/rewards/:id/claim | Claim a claim-mode reward |
Widget Display
"Rewards" tab (gift icon):
- Claimable - gold border, claim button, expiry countdown
- Active - auto-mode rewards pending next action, "Auto" badge
- Rewards you can earn - enabled rules the user has not yet earned, with progress (e.g. 3/5)
When a reward is granted while the widget is open, it announces it: confetti and a card naming the reward, with a button to the Rewards tab (above the closed launcher, or at the top of the open panel). It listens for the reward.granted SSE event, so nothing needs wiring; onEvent also receives reward.granted with rewardType and rewardValue.
The funded account card says what rewards did there: "Includes +3% from a reward" when a profit_split_boost raised its split, "+10% reward bonus on the next payout" while a payout_bonus_percent waits, and the bonus amount on a pending and an executed payout. The progress endpoint carries these as profitSplitRewardBoost, payoutBonusPercent and lastPayoutRequest.rewardBonus.
Cookie Recipes
"10 bets = 10 EUR bonus" (no achievement needed)
json
POST /v1/admin/reward-rules
{
"name": "10 Bets Welcome Bonus",
"criteria": { "type": "bets_placed", "threshold": 10 },
"rewardType": "balance_bonus",
"rewardValue": 10,
"applyMode": "auto",
"maxGrantsPerUser": 1
}User places 10th bet. Next challenge purchase: starts with 60 EUR instead of 50 EUR.
"7-day streak = 15% off next purchase"
json
POST /v1/admin/reward-rules
{
"name": "Streak Discount",
"criteria": { "type": "streak_days", "threshold": 7 },
"rewardType": "purchase_discount_percent",
"rewardValue": 15,
"applyMode": "claim",
"expiresInDays": 14,
"maxGrantsPerUser": null
}maxGrantsPerUser: null = repeatable. Every time user hits a 7-day streak, they get 15% off. Must claim within 14 days.
"Complete a challenge = better profit split"
json
POST /v1/admin/reward-rules
{
"name": "Champion Split",
"criteria": { "type": "challenges_completed", "threshold": 1 },
"rewardType": "profit_split_boost",
"rewardValue": 2,
"applyMode": "auto",
"maxGrantsPerUser": 1
}First challenge completion: funded account gets 82/18 instead of 80/20.
"High roller bonus"
json
POST /v1/admin/reward-rules
{
"name": "High Roller Boost",
"criteria": { "type": "total_wagered", "threshold": 100000 },
"rewardType": "balance_boost_percent",
"rewardValue": 10,
"applyMode": "auto",
"maxGrantsPerUser": 1
}1000 EUR wagered total: immediate +10% boost to current balance.
"Comeback kid bonus"
json
POST /v1/admin/reward-rules
{
"name": "Comeback Bonus",
"criteria": { "type": "comeback", "threshold": 2 },
"rewardType": "purchase_discount_fixed",
"rewardValue": 25,
"applyMode": "claim",
"expiresInDays": 30,
"maxGrantsPerUser": 1
}Failed 2 challenges but completed one: 25 EUR off next purchase. Rewards persistence.
"Sharpshooter bonus"
json
POST /v1/admin/reward-rules
{
"name": "Sharpshooter Perk",
"criteria": { "type": "win_rate", "threshold": 65 },
"rewardType": "extended_duration",
"rewardValue": 5,
"applyMode": "auto",
"maxGrantsPerUser": 1
}65%+ win rate (after 10+ bets): +5 extra days on next challenge. Rewards skill.
"Summer promo for all users" (manual, no criteria)
json
POST /v1/admin/rewards/bulk-grant
{
"userIds": ["player-1", "player-2", "player-3"],
"rewardType": "purchase_discount_percent",
"value": 20,
"applyMode": "claim",
"expiresInDays": 7
}20% off for 7 days. Claim required. No rule, no achievement - just a campaign.
Webhooks
reward.granted
Fires when a reward is created (rule trigger, achievement link, or manual):
json
{
"eventType": "reward.granted",
"userId": "player-42",
"data": {
"rewardId": "uuid",
"rewardType": "balance_bonus",
"rewardValue": 10,
"applyMode": "auto",
"expiresAt": "2026-07-03T14:30:00Z"
}
}reward.applied
Fires when rewards are consumed during purchase/creation:
json
{
"eventType": "reward.applied",
"userId": "player-42",
"data": {
"appliedTo": "challenge-uuid",
"context": "challenge_purchase",
"rewards": [
{ "rewardType": "balance_bonus", "rewardValue": 10, "effect": "+10 EUR starting balance" }
],
"adjustedStartingBalance": 60,
"adjustedDurationDays": 25
}
}Use reward.granted to notify users ("You earned a bonus!"). Use reward.applied to adjust your payment collection if discounts were applied.
Limitations
- Reward rules evaluate on every lifecycle event. With unlimited
maxGrantsPerUser, a rule fires on every event once criteria are met. UsemaxGrantsPerUser: 1for one-time bonuses. payout_cap_boost_percentis NOT consumed if the funded account has no cap. It stays pending.balance_boost_percentin auto mode applies immediately if there's an active account. If not, stays pending.- Consumed rewards cannot be revoked. Only pending (unconsumed) rewards can be deleted.
- Total discount (percent + fixed) is capped at the purchase price. No negative prices.
win_raterequires 10+ bets before it fires. Prevents false positives on 2/2 wins.
Support
- API docs: https://docs.fundedfast.eu/api/endpoints
- Email: support@fundedfast.eu
- Phone: +385 99 371 341