For the complete documentation index, see llms.txt. This page is also available as Markdown.

Bonus Lifecycle & Chunk Model

State machine

The lifecycle applies at the chunk level. A bonus is the aggregate of its chunks; the grant carries a derived status (e.g. PARTIALLY_RELEASED) summarizing them.

Release trigger event fires (deposit, registration, …)
    │  code validated earlier via POST /validate-code (read-only)
    ▼
GRANT created — split into no_of_chunks chunks, all PENDING ──────┐
    │  release trigger fires and/or wagering                       │ chunk_expiry_days /
    ▼  progress meets the chunk requirement                        │ bonus_expiry_days reached
RELEASE (per chunk — spendable)  ─────────────┐                    ▼
    │  consumed against wagers                │                EXPIRED (terminal)
    ▼                                         ▼
CONSUMED (terminal)                  EXPIRED / FORFEITED (terminal)

Chunk status values (transaction-detail API): PENDING → RELEASE → CONSUMED / EXPIRED. A chunk must be in RELEASE status before it can be consumed. Ledger event type values: grant, released, consumed, expiry, forfeited.

State-to-wallet mapping (PAM client wallet)

Chunk transition
Ledger event
PAM Bonus Wallet effect

grant → PENDING

grant

Increment Pending

PENDING → RELEASE

released

Move chunk amount Pending → Available

RELEASE → CONSUMED

consumed

Decrement Available (PAM debits first; ledger confirms)

→ EXPIRED

expiry

Remove from the relevant bucket

→ forfeited

forfeited

Remove remaining from Pending and/or Available

Wynta's authoritative per-chip-type view (GET /{user_id}/summary): bonus_balance (available = released − consumed), pending_bonus, and wagering_required (remaining wagering to release all pending chunks).

Chunk configuration

Chunking is configured per bonus on the configure node (bonus_create_configure) and snapshotted onto each grant (visible in transaction detail):

Field
Default
Meaning

no_of_chunks

1

Number of equal chunks the granted bonus is split into

wager_multiplier

0

Wagering requirement multiplier; 0 = no wagering — chunks release on trigger alone

wager_chip_type

CASH

Chip type whose wagers count toward release progress (may be BONUS)

credit_chip_type

CASH

Chip type the bonus is credited in

chunk_expiry_days

—

Days before an unreleased chunk expires

bonus_expiry_days

—

Days before the entire bonus expires

release_bucket

—

Optional release bucket identifier

Chunk attributes (transaction detail API)

GET /api/v1/user-bonuses/{user_id}/transactions/{txn_id} returns each grant with its chunks:

Field
Description

id / chunk_ref

Chunk record ID / human-readable reference (e.g. CHUNK_001)

chunk_amount

Bonus amount in this chunk = grant_amount / no_of_chunks

wager_multiplier

Wagering multiplier for this chunk

status

PENDING | RELEASE | CONSUMED | EXPIRED

wager_amount

Wagering progress toward release, tracked per chunk

created_at / updated_at

Creation / last status-change timestamps

Grant-level rollups: grant_amount, release_amount, bonus_consumed, derived status.

How a chunk releases

Two mechanisms move a chunk PENDING → RELEASE, per the bonus configuration:

  1. Release trigger events — configured rules (trigger_type = DEPOSIT, LOGIN, BET_PLACED, TOURNAMENT_WON, …) that fire when a matching PAM event arrives and its conditions pass (occurrence, amount band, payment_method, product, trigger_config_json).

  2. Wagering progress — when wager_multiplier > 0, each qualifying bet_placed event adds its wager_amount to the current chunk's progress; the chunk releases when progress meets the chunk requirement:

Rules:

  • Serialization — progress updates are serialized per player-bonus; concurrent bet_placed events cannot double-release a chunk.

  • Overshoot — a large wager can complete several chunks at once; the webhook may batch them in a chunks[] array.

  • Monotonic release — voided wagers reduce progress but already-released chunks are never clawed back.

  • wager_multiplier = 0 — no wagering requirement; chunks release on their trigger conditions alone.

  • Multiple active bonuses — if a player holds several active wagering bonuses, contribution is attributed to the oldest active bonus first; the recommended policy is to enforce a single active wagering bonus per chip type to avoid attribution disputes (open question — see Operations).

Worked example

₹500 grant, 3 × ₹166.67 chunks, 3× multiplier (₹500 wagering per chunk):

Cumulative qualifying wagered

Chunks in RELEASE

pending_bonus

bonus_balance

wagering_required

₹0

0

500.00

0.00

1,500.00

₹500

1

333.33

166.67

1,000.00

₹1,100

2

166.67

333.33

400.00

₹1,500

3

0.00

500.00

0.00

Consumption across chunks

The consume endpoint auto-selects the user's next available released chunk — the client never chooses chunks. Every consumption is recorded per chunk under its consume_txn_id, so transaction detail shows exactly which chunks funded which rounds — this is what makes reversal and reconciliation exact.

Expiry & forfeit at chunk level

Two independent clocks:

  • Chunk expiry (chunk_expiry_days) — an unreleased chunk expires on its own; recorded as an expiry event with type: "CHUNK_EXPIRY".

  • Bonus expiry (bonus_expiry_days) — the whole bonus expires; non-terminal chunks transition together, recorded with type: "BONUS_EXPIRY".

Forfeits carry a type (MANUAL, RULE_VIOLATION) and the triggering operator. On expiry or forfeit the webhook carries per-chunk detail so the PAM decrements Pending and Available by the correct split.

Last updated

Was this helpful?