The problem

Picking a raffle winner with Math.random() on your server is asking your community to trust you. Even if you're honest, you can't prove it.

The recipe

  1. Commit ahead of time. Before entries close, publish the serverHash you'll use. Most teams pin it in a Discord or X post with a timestamp.
  2. Collect entries. Lock the list when the draw closes. Number each entry 1..N.
  3. Use a public client seed. Use something deterministic and observable — for example, the SHA-256 of the next Bitcoin block at a known height, or a tweet ID from your account at a fixed time.
  4. Draw the winner.
    curl "https://api.provable.io/api/ints?clientSeed=PUBLIC_SEED&count=1&min=1&max=N"
  5. Publish the proof. Share the clientSeed, the serverHash, and the outcome. Anyone can hit /verify to confirm the result.

Why this works

Because the serverHash was committed before entries closed and the clientSeed couldn't be known in advance, you couldn't have steered the outcome. Independent verification turns the raffle from "trust me" to "check for yourself."

Next steps

FAQ

How do I run a provably fair raffle?

Pre-commit a serverHash before entries close, freeze the entrant list at the close time, use a public deterministic clientSeed (a future block hash or tweet ID), and call /api/pick or /api/ints to draw the winner. Publish the seed trio so anyone can re-derive the result.

When should I publish the serverHash?

Before entries close. Publishing the hash up front (in the campaign post or pinned tweet) means the server cannot shop seeds against the entrant list — the commitment is locked in.

What should I use as the clientSeed?

Something nobody controls and that becomes known after entries close: a future block hash, a Bitcoin block at a fixed height, a tweet ID scheduled for a specific time. That prevents both server-side seed shopping and entrant-side input grinding.

How do entrants verify the winner?

They paste the clientSeed and serverHash into /verify (or call /api/verifyServerHash) and re-run the same /api/pick or /api/ints call. The same inputs always produce the same winner — the math is reproducible by anyone.