Skip to content

Raffle Games

Raffle games are single-draw prize reveals: the player buys a ticket, one outcome is drawn, and a prize (or "No Win") is revealed. Like every KINGSTONE game, the outcomes are pre-determined — the full prize pool is generated and sealed before the raffle opens, and each ticket simply consumes the next position in the sealed sequence.

Two things make raffles different from slots:

  1. The presentation is a prize reveal, not reels. The response carries a type: 'raffle' presentation block with a prize name instead of symbols and reel stops.
  2. The pool is finite. When every ticket has been sold, the raffle closes permanently and further spin requests return KS-4218 (HTTP 410).

The Spin Request

The request is identical to a slot spin — same endpoint, same fields:

POST /api/partner/v1/spin
FieldTypeRequiredDescription
gameIdnumberYesGame configuration ID from registration
playerIdstringYesYour external player identifier
wagerUsdnumberYesThe ticket price in USD
requestIdstringNoIdempotency key (echoed back in response)

Raffles are fixed-wager games: the wager is the ticket price, and the game is configured with minimum = maximum = increment = ticket price. Sending any other wagerUsd value is rejected with KS-4103.

With curl

bash
curl -X POST https://sandbox.kingstone.dev/api/partner/v1/spin \
  -H "X-API-Key: ks_sandbox_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "gameId": 9,
    "playerId": "player-abc-123",
    "wagerUsd": 1.00
  }'

With the SDK

The SDK call is the same spin() you already use for slots:

typescript
import { KingstoneClient } from '@kingstoneapp/sdk';

const client = new KingstoneClient({
  apiKey: 'ks_sandbox_your_key_here',
  sandbox: true,
});

const result = await client.spin({
  gameId: 9,
  playerId: 'player-abc-123',
  wagerUsd: 1.00,
});

console.log(`Spin ID: ${result.spinId}`);
console.log(`Prize tier: ${result.outcome.prizeTier}`);
console.log(`Payout: $${result.outcome.payoutUsd.toFixed(2)}`);

The Raffle Response

json
{
  "spinId": "12345",
  "outcome": {
    "prizeTier": 3,
    "payoutUsd": 500,
    "isBonusTrigger": false
  },
  "presentation": {
    "type": "raffle",
    "prizeName": "$500 Gift Card",
    "prizeTier": 3,
    "celebrationTier": "large"
  },
  "balance": {
    "balanceUsd": 42.5
  },
  "communityBonus": null
}

The outcome and balance blocks are identical to slot spins — see the spin response reference. Only the presentation block differs.

The presentation Block

FieldDescription
typeAlways "raffle" for raffle games. Narrow on this field to pick your renderer — slot games send type: "slot".
prizeNameHuman-readable prize name to display, e.g. "$500 Gift Card". No-win outcomes carry "No Win".
prizeTierPrize tier number (0 = no win). Duplicates outcome.prizeTier for renderer convenience.
celebrationTierCelebration intensity: none, small, medium, large, or jackpot.

A no-win ticket looks like this:

json
{
  "type": "raffle",
  "prizeName": "No Win",
  "prizeTier": 0,
  "celebrationTier": "none"
}

Finite Pool Lifecycle

A raffle has a fixed number of tickets — exactly as many as the advertised prize table. Once the last ticket is drawn, the raffle is permanently closed:

json
{
  "status": "error",
  "message": "This raffle has closed — all tickets have been sold",
  "errorCode": "KS-4218"
}

KS-4218 (HTTP 410) is a terminal state — the raffle will never reopen:

  • Do not retry. Unlike the slot-side BLOCK_UNAVAILABLE (503, temporary queue exhaustion — retryable), a 410 will never succeed later.
  • Render "raffle closed" in your UI and stop sending spin requests for this gameId.
  • To keep selling, launch a new raffle — a new game registration with a fresh prize pool.

Idempotency

Raffle spins use the same requestId idempotency mechanism as slots — pass a unique requestId per ticket purchase and reuse it only to retry the exact same request. See the spin request reference and error codes KS-4110 / KS-4111 on the error codes page.

Common Errors

Error CodeHTTP StatusMeaning
KS-4218410Raffle closed — all tickets sold. Terminal; do not retry.
KS-4103400Wager does not match the ticket price.
KS-4201404Game not found. Check the gameId.
KS-4291429Spin rate limit exceeded. Back off and retry.

Next Steps

KINGSTONE by Predigy Inc.