Appearance
Challenge Purchase
Challenges are purchased through your sportsbook's payment flow. FAST does not handle money - your backend collects payment first, then notifies FAST to create the challenge.
Flow
- User selects a challenge tier in your UI.
- Your backend collects payment through your payment system.
- On successful payment, call FAST to create the challenge.
- If FAST returns an error, refund the user.
Endpoint
POST /v1/challenges/purchaseRequest
bash
curl -X POST https://api.fundedfast.eu/v1/challenges/purchase \
-H "X-API-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"userId": "your-user-id",
"challengeTierId": "d3eebc99-9c0b-4ef8-bb6d-6bb9bd380a11",
"timestamp": "2026-01-15T10:00:00Z"
}'| Field | Type | Required | Description |
|---|---|---|---|
userId | string | yes | Your sportsbook user identifier |
challengeTierId | string (UUID) | yes | ID from GET /v1/challenge-tiers |
timestamp | string (ISO 8601) | no | Purchase timestamp (defaults to now) |
Responses
201 Created
Challenge created successfully. FAST dispatches a challenge.activated webhook.
json
{
"challenge": {
"id": "a1b2c3d4-...",
"userId": "your-user-id",
"challengeTierId": "d3eebc99-...",
"status": "active",
"ownStake": 100.0,
"bonusAmount": 900.0,
"startingBalance": 1000.0,
"currentBalance": 1000.0,
"targetBalance": 2000.0,
"startedAt": "2026-01-15T10:00:00Z",
"expiresAt": "2026-02-04T10:00:00Z"
},
"correlationId": "uuid"
}The full object also carries tenantId, rulesetId, refundableOwnStake, peakBalance, bet counters, activeDays, dailyLoss and timestamps.
409 Conflict
The user cannot start a new challenge right now. The error field says why:
error | Cause |
|---|---|
active_challenge_exists | User already has an active challenge |
challenge_awaiting_choice | User passed a challenge and has not chosen continue or refund yet |
active_funded_account_exists | User has an active funded account |
tier_not_found | No such challenge tier for your tenant |
tier_disabled | The tier exists but is disabled |
user_self_excluded | User is self-excluded |
monthly_challenge_limit_reached | Your plan's monthly challenge limit is used up |
json
{
"error": "active_challenge_exists",
"message": "User already has an active challenge",
"correlationId": "uuid"
}429 Purchase Cooldown
After a challenge fails or is cancelled, the user cannot buy again until midnight UTC of that day. The response says when the cooldown ends:
json
{
"error": "purchase_cooldown",
"message": "Please wait 312 minute(s) before purchasing a new challenge (cooldown expires at midnight UTC)",
"cooldownUntil": "2026-01-16T00:00:00.000Z",
"correlationId": "uuid"
}402 / 403 Approval
If the purchase comes from the widget, your approval URL must approve it. 403 approval_required means no approval URL is configured (production tenants only; staging auto-approves). 402 purchase_declined means your approval URL declined it. Purchases from your server with a server API key skip the 403 and only call the approval URL if one is set.
400 Bad Request
Missing or invalid required fields.
json
{
"error": "validation_error",
"message": "userId and challengeTierId are required",
"correlationId": "uuid"
}One Active Challenge Per User
FAST enforces a strict one-active-challenge-per-user constraint. A user cannot purchase a new challenge while they have:
- An active challenge in progress
- A passed challenge awaiting the continue/refund choice
- An active funded account
The user can purchase again after a challenge fails, expires or is cancelled, or a funded account is revoked. After a failed or cancelled challenge, the next purchase opens at midnight UTC (see the 429 above).
Fetching Available Tiers
List enabled challenge tiers to display in your shop:
bash
curl -H "X-API-Key: your-api-key" \
https://api.fundedfast.eu/v1/challenge-tiersjson
{
"challengeTiers": [
{
"id": "d3eebc99-...",
"name": "Starter",
"ownStake": 100.0,
"bonusAmount": 900.0,
"targetBalance": 2000.0,
"durationDays": 20,
"fundedAccountBalance": 5000.0,
"profitSplitPercent": 80
}
],
"correlationId": "uuid"
}Each tier also carries its ruleset limits (minOdds, maxOdds, maxStakePercent, maxAccumulatorSelections, minBetsRequired, minActiveDays, dailyDrawdownPercent, totalDrawdownPercent, luckyBetMaxProfitPercent) for rules disclosure. Only enabled tiers are returned.