What it is

A raffle picker built on the /api/pick and /api/ints endpoints. You hand it the list of entries (or a count of numbered entries); it returns the winner, a deterministic seed trail, and a serverHash that anyone can paste into /verify to confirm the draw wasn't reshuffled after the fact.

Optional weights let you run weighted raffles (e.g. extra entries for paid tiers, loyalty multipliers) without inventing your own RNG or asking entrants to trust your math.

The pain point

"Congrats to @whoever!" is not a winner announcement people trust anymore. Communities want receipts: a public commitment before entries close, a clear rule for how the draw mapped entrants to numbers, and a way to re-run the calculation independently. Building that yourself is doable but tedious; the raffle picker API gives you all three out of the box.

Try it live — pick a winner from a list

curl "https://api.provable.io/api/pick?clientSeed=giveaway_2026_05_24&items=alice,bob,carol,dave,eve,frank"

Same call with weighted entries (paid tier gets 3× the odds):

curl "https://api.provable.io/api/pick?clientSeed=giveaway_2026_05_24_weighted&items=free_user,free_user_2,paid_user&weights=1,1,3"

Or pick by entry number

If you have thousands of entries, don't ship the whole list — number them 1..N and draw an integer:

curl "https://api.provable.io/api/ints?clientSeed=giveaway_2026_05_24_by_number&count=1&min=1&max=1750"

Integration snippet

// 1. Before entries open, fetch /api/commit and publish the serverHash
// (Discord post, X tweet, blog header). This pins the draw upfront.

// 2. When entries close, freeze the entrant list:
const entries = await db.entrants.findAll({ where: { campaignId } });

// 3. Use a deterministic, publicly known clientSeed.
//    Block hashes and tweet IDs work well — nobody controls them.
const clientSeed = `raffle_${campaignId}_${publicBlockHash}`;

// 4. Reveal the winner.
const url = new URL("https://api.provable.io/api/pick");
url.searchParams.set("clientSeed", clientSeed);
url.searchParams.set("items", entries.map((e) => e.id).join(","));

const res = await fetch(url, {
  headers: { "x-api-key": process.env.PROVABLE_KEY }
});
const { outcome: winnerId, serverHash, shortId } = await res.json();

// 5. Announce: "Winner is X — verify at https://provable.io/o/{shortId}"

Why this is fair

  1. The serverHash commitment goes out before the entries close, so the server can't shop seeds against the entrant list.
  2. The clientSeed is something nobody controls (a future block hash, a tweet ID at a future time, a Bitcoin block at a fixed height) — so entrants can't grind their own usernames against it.
  3. The mapping (uniform integer in [1, N] or weighted bucket lookup) is documented and re-derivable from the open-source provable-core library.

Common patterns

The full recipe

This page is the keyword-friendly intro to the raffle workflow. For the long-form walkthrough with commitment patterns, public-seed strategies, and post-draw publication tips, see the dedicated recipe: Building Fair Raffles.

Where it fits

Related