What it is
A lottery-grade RNG built on /api/ints. You pick the range (1–49 for a classic 6/49, 1–69 for Powerball-style main balls, 1–90 for bingo), the API returns a verifiable draw, and every player can re-derive the numbers from the published seed pair.
No more "the wheel sometimes lands on 7" conspiracy threads. Every ball is a deterministic function of HMAC_SHA256(serverSeed, clientSeed + cursor + nonce).
The pain point
Traditional lotteries solve trust with televised mechanical drums. Online and community-run lotteries don't have that option, so they're stuck between two bad alternatives: trust a closed-source RNG, or roll your own and hope nobody asks how. A verifiable lottery API gives you a third option — show the math.
Try it live — draw 6 numbers from 1–49
curl "https://api.provable.io/api/ints?clientSeed=lottery_draw_2026_05_25&count=6&min=1&max=49"
Powerball-style: 5 main balls (1–69) plus a bonus ball (1–26):
curl "https://api.provable.io/api/ints?clientSeed=powerball_2026_05_25_main&count=5&min=1&max=69"
curl "https://api.provable.io/api/ints?clientSeed=powerball_2026_05_25_bonus&count=1&min=1&max=26"
Integration snippet
// 1. When ticket sales open, fetch /api/commit and publish the serverHash
// on the draw page header. This pins the draw before any ticket is sold.
// 2. Use a public, unguessable clientSeed when sales close.
// A future block hash from a public chain works beautifully.
const clientSeed = `lottery_${drawId}_block_${blockHash}`;
// 3. Draw the 6 main numbers + bonus ball.
const main = await fetch(
`https://api.provable.io/api/ints?clientSeed=${clientSeed}_main` +
`&count=6&min=1&max=49`,
{ headers: { "x-api-key": process.env.PROVABLE_KEY } }
).then((r) => r.json());
// 4. Dedupe (a real lottery draws without replacement).
const numbers = [];
for (const n of main.outcome) if (!numbers.includes(n)) numbers.push(n);
while (numbers.length < 6) numbers.push(await drawAnother(numbers));
// 5. Publish: numbers, serverHash, clientSeed, and the /o/{shortId} permalink.
Drawing without replacement
Real lotteries don't draw the same ball twice. Two clean ways to handle that with this API:
- Over-draw and dedupe. Request more numbers than you need (e.g. 12 for a 6-ball draw) and keep the first 6 unique values. Simple, fully verifiable.
- Use
/api/shuffle. Shuffle the full pool[1..49]in one call and take the first 6 entries — exactly equivalent to a Fisher-Yates draw on a physical drum.
Why this is fair
- Commit before sales close. The
serverHashis published while tickets are still being sold, so the operator can't pick a seed that favors any specific entry. - Public
clientSeed. Anchor it to a future block hash or a verifiable public event — neither operator nor player can grind it. - Open algorithm. The mapping is documented in the open-source provable-core library, so anyone can replay the draw locally.
Where it fits
- Community lotteries and DAO treasury draws that want public auditability.
- Bingo halls and bingo apps — ball draws with a verifiable trail.
- Charity raffle-lotteries where donors expect proof their numbers were drawn fairly.
- Promotional lotteries attached to product launches or loyalty programs.