How it works

Provably fair.
Cryptographically sealed.

RFWIN doesn't ask you to trust us. Every draw is a mathematical proof you can recompute yourself. Here's exactly how.

Commit-reveal: the core fairness model

The fundamental problem with any random draw is: how do you know the organiser didn't pick their friend after seeing the list? RFWIN solves this with a two-phase protocol.

  1. Commit — Before any draw happens, RFWIN generates a secret server seed and publishes a cryptographic commitment (SHA-256 hash of the seed + entrant list). This is your receipt.
    The commitment is published to the permanent ledger before any randomness is applied. Cheating at this point would require finding a different input that hashes to the same output — computationally impossible.
  2. Lock to a future beacon round — The draw locks to a specific upcoming round of the drand public randomness beacon. This round hasn't been broadcast yet, so neither you nor RFWIN knows its value.
    This is what prevents us from cherry-picking a beacon value we like. The round number is fixed in the commitment; only one beacon value will ever match it.
  3. Reveal — Once the beacon broadcasts, RFWIN fetches the value, derives the winner using SHA-256(server_seed + drand_value + entrant_list), and publishes the full proof bundle.
    Anyone can download the bundle and recompute the exact winner — no software installation required, just a SHA-256 calculator and the published values.

Instant draw vs. step-by-step. The quick draw on the home page uses the current drand round for better UX. It's still cryptographically auditable, but the organiser could theoretically know the beacon value before submitting — so the trust model is weaker. Step-by-step via the API locks to a future round, providing the strongest guarantee.

drand: the public randomness beacon

RFWIN uses drand quicknet — a decentralised, publicly verifiable randomness beacon operated by a global consortium of independent nodes including universities, research labs, and infrastructure operators.

Why drand and not just Math.random()?

What a beacon round looks like

{
  "round":     12345678,
  "randomness": "a8f3c2...64 hex chars",
  "signature":  "92b1e0...BLS sig over SHA-256(prev_sig || round)",
  "prev_sig":   "f4d8a1...previous round signature"
}
// Verify: SHA-256(prev_sig || round_as_bytes) → BLS verify(signature, public_key)

RFWIN records the round and randomness value in every proof bundle. You can fetch the same data from any public drand league node (e.g. api.drand.sh) and compare.

Winner derivation: the exact math

Once the beacon value is available, RFWIN derives winners deterministically from a single formula. No randomness is introduced after the commit phase.

// 1. Build the entrant list (submitted order, lowercased emails)
entrants = ["alice@example.com", "bob@example.com", ...]

// 2. Hash each entrant for the ledger (one-way, no originals stored)
entrant_hash[i] = SHA-256(email_lowercase)

// 3. Derive a draw seed
draw_seed = SHA-256(server_seed + "|" + drand_randomness)

// 4. For each prize slot (unique-winners mode removes used indices)
winner_index = BigInt(SHA-256(draw_seed + "|" + prize_index)) % entrant_count

// 5. Winner is entrants[winner_index]

The full proof bundle from GET /api/draws/:id includes every value you need to re-run this yourself: server_seed, drand_value, entrant_hashes, and winners. The in-browser verifier on each certificate page runs this derivation client-side.

The permanent verification ledger

Every draw is written to an append-only distributed database at the time of creation. Records are permanent by design — this is not a feature you can opt out of, because permanence is what makes verification meaningful.

The verification URL rfwin.uk/d/:id is permanent — it will show the same result five years from now as it does today.

MCP: running draws from AI agents

RFWIN exposes a Model Context Protocol (MCP) server that lets AI agents run and verify draws as native tool calls — no web scraping, no manual steps.

MCP is an open standard that lets LLMs call structured tools with typed inputs and outputs, the same way a developer calls an API. An agent with RFWIN tools connected can run a complete verifiable draw in a single turn.

Available MCP tools

rfwin_instant_draw

Run a complete draw in one call. Pass a title, list of contestants, and prizes. Returns a drawId and public verification URL instantly.

rfwin_get_draw

Fetch the full proof bundle for any draw by ID. Returns winners, entrant hashes, drand values, server seed, and draw digest for independent verification.

Connecting to the MCP server

// Claude, Cursor, or any MCP-compatible client
{
  "mcpServers": {
    "rewards-fuel": {
      "url": "https://rewards-fuel-api.rewardsfuel.workers.dev/api/mcp"
    }
  }
}

// Agent prompt example
"Pick 3 winners from this list fairly. Here are 200 contestants: [...]
Run the draw and give me the verification URL to share with entrants."

Why agents need verifiable draws

When an AI agent picks a winner autonomously, the question "did it cheat?" becomes unanswerable — unless the draw is cryptographically sealed. RFWIN gives agents the ability to produce a proof that neither they nor the organiser could have manipulated. The rfwin_get_draw tool returns a proof that a separate verifier agent can check independently.

REST API reference

All API calls return the standard envelope: {"ok": bool, "data": ..., "error": null | {"code": string, "message": string}}

Instant draw (one call)

POST https://rfwin.uk/api/draws/instant
Content-Type: application/json

{
  "title":        "June Podcast Giveaway",
  "contestants":  ["alice@ex.com", "bob@ex.com", ...],
  "prizes":       ["AirPods Pro", "$50 Gift Card"],
  "uniqueWinners": true   // optional, default true
}

// Response
{
  "ok": true,
  "data": {
    "id":      "young-mink-09c5bf",
    "url":     "https://rfwin.uk/d/young-mink-09c5bf",
    "winners": [
      { "prize": "AirPods Pro", "entrant": "a••••e@ex.com" }
    ]
  }
}

Fetch proof bundle

GET https://rfwin.uk/api/draws/{drawId}

// Returns full proof: server_seed, drand_value, entrant_hashes, winners

Step-by-step (strongest fairness)

POST /api/draws              // create, get drawId
POST /api/draws/:id/entrants  // add contestants
POST /api/draws/:id/close     // lock to a FUTURE drand round
POST /api/draws/:id/draw      // execute once beacon round arrives
POST /api/draws/:id/reveal    // publish server_seed, finalize proof

Authentication for step-by-step: Authorization: Bearer HOST_API_KEY (available on paid plans).

Try it now — no account needed

Run a free draw on the home page. Your result is permanently stored and independently verifiable in seconds.