Draw service
Draw service
Pick winners from any list (giveaway entrants, prize-draw tickets, a jury pool) and get a proof that anyone can check without trusting you or us.
Picking at random is easy. Proving you did not re-run the draw until you liked the answer is not. The draw service fixes its own random seed before you supply yours, so neither side can steer the result, and it hands back everything needed to recompute it.
| Price | $0.01 per revealed draw, paid from a prepaid USDC balance. GET /draws/info always has the current price. |
| List size | Up to 10,000 candidates of up to 512 characters each. |
| Winners | Any number up to the list size, distinct, in the order drawn (first place first). |
| Proof | A JSON receipt. Check it on the verify page in a browser, or in a few lines of your own code. |
| Access | A key with the draws:create scope. Commit, reveal, deposit and key rotation also need a signed BitRaffle-Proof header. |
Set up, once
- Get a key with the
draws:createscope. - Create an Ed25519 key pair and register its public half with
POST /draws/register-key. See Signed requests. - Fund your balance with USDC. See Funding your balance.
Run a draw
Assuming the proof() signing helper from Signed requests:
Node.js
const API = "https://www.bitraffle.io/api/v1";
const auth = { Authorization: `Bearer ${process.env.BITRAFFLE_SECRET_KEY}` };
async function call(method, path, body) {
const url = API + path;
const res = await fetch(url, {
method,
headers: { ...auth, "BitRaffle-Proof": proof({ method, url }), "Content-Type": "application/json" },
body: body && JSON.stringify(body),
});
if (!res.ok) throw new Error(`${res.status} ${JSON.stringify(await res.json())}`);
return res.json();
}
// 1. Commit: we publish a hash of our secret seed. Save it.
const { drawId, serverSeedHash } = await call("POST", "/draws/commit");
// 2. Only now choose your seed: anything we could not have predicted.
const clientSeed = `weekly-giveaway-${new Date().toISOString()}`;
// 3. Reveal: your seed + the list -> winners and a proof.
const { result, proof: drawProof } = await call("POST", `/draws/${drawId}/reveal`, {
clientSeed,
candidates: ["alice@example.com", "bob@example.com", "carol@example.com"],
pick: 1,
});
console.log(result.winners); // ["bob@example.com"]
console.log(drawProof.serverSeedHash === serverSeedHash); // true: the seed was fixed firstRules worth knowing
- Choose
clientSeedafter you receive the commitment. A seed chosen first, or one we could predict, weakens the proof. - Keep your list in a fixed order and publish it, or its hash, with the result. The proof binds the exact list.
- Revealing again with identical inputs returns the same result at no charge. Different inputs on an already revealed draw are refused with
409. - A draw belongs to your organisation. Another organisation's key cannot reveal or read it.