# Fair Draw

> Pick giveaway, raffle and contest winners in a way anyone can check. Fair Draw, from bettip.co.za, locks the entries to a future moment and lets the public drand randomness beacon decide the winners, then gives you a result link with a proof that anyone can re-check. Draw from a list of names or a range of numbers, and verify any result.

App · 4 actions. Web page: https://docs.lodol.com/docs/integrations/fair-draw

## Actions

### Create a draw

Set up a random draw that nobody can rig: a giveaway, a raffle, picking a winner or a team. Give a list of entries (or a range of numbers) and how many winners to pick. The draw is locked to a moment in the future, about 12 seconds from now unless you choose a time, and the public drand randomness at that moment decides the winners. Returns a draw ID for Pick the winners, and a link you can share beforehand to prove the entries were fixed in advance.

**Inputs**

- Draw from (`draw_from`, text): Pick winners from a list of entries or from a range of numbers. One of: `list` (A list of entries), `numbers` (A range of numbers). Default: `list`.
- Entries (`entries`, list): The names, emails or tickets to draw from, one per entry: at least 2, up to 50,000, each up to 200 characters. An entry listed twice has two chances. Only when Draw from is A list of entries.
- First number (`first_number`, number): The lowest number that can be drawn, for example 1. Only when Draw from is A range of numbers.
- Last number (`last_number`, number): The highest number that can be drawn, for example 500 for tickets 1 to 500. Only when Draw from is A range of numbers.
- Number of winners (`winners`, number): How many winners to pick. Nobody can win twice unless they are listed twice. From 1 to 10000. Default: `1`.
- Title (`title`, text): A name for the draw, shown on its result page, for example 'Friday giveaway'. Up to 120 characters.
- Draw time (`draw_at`, date and time): When the draw happens. Leave it empty to draw in about 12 seconds. Set a later time to announce the draw first; the winners can be picked once that time has passed.

**Outputs**

- `announcement_link` (text): Share this before the draw: it shows the fingerprint and round, so entrants can later confirm the list was fixed in advance.
- `beacon_round` (number): The drand beacon round whose randomness decides the draw.
- `commitment` (text): The draw's fingerprint: a SHA-256 hash of the draw description. Any change to the entries, the number of winners or the round changes it.
- `draw_from` (text): 'list' for a list of entries, 'numbers' for a range.
- `draw_id` (text): The draw's ID. It holds the whole draw description, so pass it to Pick the winners; Fair Draw stores nothing.
- `draw_link` (text): A page on bettip.co.za that makes this draw.
- `draw_time` (text): When the draw's beacon round lands (ISO 8601, UTC).
- `entry_count` (number): How many entries (or numbers) are in the draw.
- `seconds_until_draw` (number): How many seconds from now until the winners can be picked.
- `title` (text): The draw's title, if it was given one.
- `winners_to_pick` (number): How many winners will be drawn.

**Example output**

```json
{
  "announcement_link": "https://bettip.co.za/fair-draw/verify/#h=2dbd50596227aa78a185173a4eae92e92269cb655af4ee22d5de64731ce7d8b7&r=33094765",
  "beacon_round": 33094765,
  "commitment": "2dbd50596227aa78a185173a4eae92e92269cb655af4ee22d5de64731ce7d8b7",
  "draw_from": "list",
  "draw_id": "1.BcGxDsIgEAbgVzH_zEAL5Qqbi6NxcDMOVzjsRVNNrZrG-O5-3xdvpMYgj6wTErq2DHFgsmJztjUIV-qtK8WS98RN7TwRua4WV0NoKLYDRx-szb2XSA0M5vtrKkjO2egpdAYPzVek1mDR5SZI2M1aeN1c9C384RUGMi2zyhPphOPIwx0GW32ODIODyiIzDPZ8k6I4__4",
  "draw_link": "https://bettip.co.za/fair-draw/#c=1.BcGxDsIgEAbgVzH_zEAL5Qqbi6NxcDMOVzjsRVNNrZrG-O5-3xdvpMYgj6wTErq2DHFgsmJztjUIV-qtK8WS98RN7TwRua4WV0NoKLYDRx-szb2XSA0M5vtrKkjO2egpdAYPzVek1mDR5SZI2M1aeN1c9C384RUGMi2zyhPphOPIwx0GW32ODIODyiIzDPZ8k6I4__4",
  "draw_time": "2026-10-15T18:07:39.000Z",
  "entry_count": 4,
  "seconds_until_draw": 12,
  "title": "Friday giveaway",
  "winners_to_pick": 2
}
```

### Get beacon round

See the drand randomness beacon's latest and next round, and which round a given time maps to. A new round lands every 3 seconds; a draw is decided by the first round at or after its draw time.

**Inputs**

- Time (`at`, date and time): A time to find the round for. Leave it empty for just the latest and next round.

**Outputs**

- `beacon` (text): The randomness beacon draws are bound to.
- `current_round` (number): The latest beacon round.
- `current_round_at` (text): When the latest round landed (ISO 8601, UTC).
- `next_round` (number): The next beacon round.
- `next_round_at` (text): When the next round lands (ISO 8601, UTC).
- `relays` (list): The public relays the beacon is read from.
- `requested_time` (text): The time that was asked about, if any (ISO 8601, UTC).
- `round_for_time` (number): The first round at or after the requested time.
- `round_for_time_at` (text): When that round lands (ISO 8601, UTC).
- `seconds_between_rounds` (number): How often a new round lands, in seconds.
- `time_has_passed` (true/false): True when the requested time is in the past, so a new draw can't be bound to it.

**Example output**

```json
{
  "beacon": "drand quicknet",
  "current_round": 33094760,
  "current_round_at": "2026-10-15T18:07:24.000Z",
  "next_round": 33094761,
  "next_round_at": "2026-10-15T18:07:27.000Z",
  "relays": [
    "https://api.drand.sh",
    "https://drand.cloudflare.com"
  ],
  "requested_time": "2026-12-25T10:00:00Z",
  "round_for_time": 35129812,
  "round_for_time_at": "2026-12-25T10:00:00.000Z",
  "seconds_between_rounds": 3,
  "time_has_passed": false
}
```

### Pick the winners

Pick the winners of a draw made with Create a draw. If the draw time is less than a minute away, the step waits for it. Returns the winners in order, and a result link anyone can open to see the winners and check the draw was fair.

**Inputs**

- Draw (`draw`, text, required): The draw ID or draw link from Create a draw.
- Wait for the draw time (`wait`, true/false): If the draw time is up to 60 seconds away, wait for it rather than stopping with an error. Default: `true`.

**Outputs**

- `beacon_round` (number): The drand beacon round whose randomness decides the draw.
- `commitment` (text): The draw's fingerprint: a SHA-256 hash of the draw description. Any change to the entries, the number of winners or the round changes it.
- `drawn_at` (text): When the deciding beacon round landed (ISO 8601, UTC).
- `entry_count` (number): How many entries (or numbers) were in the draw.
- `randomness` (text): The beacon randomness that decided the winners (hex).
- `result_id` (text): The result's ID. It holds the full proof, so pass it to Verify a draw.
- `result_link` (text): A page on bettip.co.za that shows the winners and re-runs every check. Share it with entrants.
- `seconds_waited` (number): How long the step waited for the draw time.
- `title` (text): The draw's title, if it was given one.
- `winner_entries` (list): Just the winning entries, in the order they were drawn.
- `winners` (list): The winners, in the order they were drawn.

**Example output**

```json
{
  "beacon_round": 33094765,
  "commitment": "2dbd50596227aa78a185173a4eae92e92269cb655af4ee22d5de64731ce7d8b7",
  "drawn_at": "2026-10-15T18:07:39.000Z",
  "entry_count": 4,
  "randomness": "76536b78aa394015ca3af8bec7e09f2887190f447df878b197bfb5149f71b971",
  "result_id": "1.ZZI9bxsxDIb_SsBZcfRNSVuWjkWHTC0yUBIVC7XvjDslqRv4vxcXt2mBjgSf4eXz8g1eICkB64kLpLffU9lTnyCB0zXHTChZliKbZ2oYpKlVorVIqjmLiMa1apr3CqPOFK2XsgTLERUIWObnqUIyRkaL3gk49fIdkhYw-jgwJPi09Ernm6f-wvRKZxDA01g6r5C-wcOe8gwC7vu6JxDwpfPgBQR8pgPXDo8XAWU-Hvs48jQgga65Oumi1xqJMJAKTqEhy8RRc9Tax5K9c9Qss9bVVfYWjSqMNWQEAZmpzNNm47_wC011Pk68rpAAvTM-YyAy0UrlChlqIXNBlrHpEFBF2azF2gKGrCLmlp2ysaHKVztrf5poPC-bh4gsvZPMOtvgGzsO0TvHrWqZG1fVdNMVtck1ROs4SFe9D9KrJnPWwVgjlSwcFcpcVMkyNk-t6IB5ywIXAa99mnjZzL7BaV776NuhSkCfKv-AZK7yz5D-CL6If0n9Qcq_5LWjy6OAIw_avI15PkCCzGP0067Mu590Q6cOAupCr9P9e1FS-1slb5V7UCFJTFbuZMCv28_wgc7v9e_HOK3p7q5u4nflMD_XdqCFd2U-gvhY06nvrsi6h8fL5Rc",
  "result_link": "https://bettip.co.za/fair-draw/result/#p=1.ZZI9bxsxDIb_SsBZcfRNSVuWjkWHTC0yUBIVC7XvjDslqRv4vxcXt2mBjgSf4eXz8g1eICkB64kLpLffU9lTnyCB0zXHTChZliKbZ2oYpKlVorVIqjmLiMa1apr3CqPOFK2XsgTLERUIWObnqUIyRkaL3gk49fIdkhYw-jgwJPi09Ernm6f-wvRKZxDA01g6r5C-wcOe8gwC7vu6JxDwpfPgBQR8pgPXDo8XAWU-Hvs48jQgga65Oumi1xqJMJAKTqEhy8RRc9Tax5K9c9Qss9bVVfYWjSqMNWQEAZmpzNNm47_wC011Pk68rpAAvTM-YyAy0UrlChlqIXNBlrHpEFBF2azF2gKGrCLmlp2ysaHKVztrf5poPC-bh4gsvZPMOtvgGzsO0TvHrWqZG1fVdNMVtck1ROs4SFe9D9KrJnPWwVgjlSwcFcpcVMkyNk-t6IB5ywIXAa99mnjZzL7BaV776NuhSkCfKv-AZK7yz5D-CL6If0n9Qcq_5LWjy6OAIw_avI15PkCCzGP0067Mu590Q6cOAupCr9P9e1FS-1slb5V7UCFJTFbuZMCv28_wgc7v9e_HOK3p7q5u4nflMD_XdqCFd2U-gvhY06nvrsi6h8fL5Rc",
  "seconds_waited": 12,
  "title": "Friday giveaway",
  "winner_entries": [
    "Naledi",
    "Thabo"
  ],
  "winners": [
    {
      "entry": "Naledi",
      "entry_number": 4,
      "position": 1
    },
    {
      "entry": "Thabo",
      "entry_number": 1,
      "position": 2
    }
  ]
}
```

### Verify a draw

Check that a draw's result is genuine: that the entries match the fingerprint announced beforehand, that the randomness really came from the drand beacon at the promised moment, and that it gives exactly these winners. Each check comes back with what was found. A result that fails a check comes back as not verified rather than as an error.

**Inputs**

- Result (`result`, text, required): The result ID or result link from Pick the winners.

**Outputs**

- `beacon_round` (number): The drand beacon round whose randomness decides the draw.
- `checks` (list): Every check that was run, in order.
- `commitment` (text): The draw's fingerprint: a SHA-256 hash of the draw description. Any change to the entries, the number of winners or the round changes it.
- `failed_checks` (list): The checks that did not hold; empty when verified.
- `title` (text): The draw's title, if it was given one.
- `verdict` (text): The outcome in one sentence.
- `verified` (true/false): True when every check passed.
- `winner_entries` (list): Just the winning entries, in the order they were drawn.
- `winners` (list): The winners, in the order they were drawn.

**Example output**

```json
{
  "beacon_round": 33094765,
  "checks": [
    {
      "check": "The draw description is complete",
      "detail": "The draw description is well formed.",
      "passed": true
    },
    {
      "check": "The fingerprint matches the draw",
      "detail": "The commitment is the SHA-256 of the draw description: 2dbd50596227aa78\u2026",
      "passed": true
    },
    {
      "check": "The randomness is signed by drand",
      "detail": "The beacon signature verifies under the drand quicknet public key, and the randomness is its SHA-256.",
      "passed": true
    },
    {
      "check": "The winners follow from the randomness",
      "detail": "Recomputing the draw from the randomness gives the same 2 winners.",
      "passed": true
    }
  ],
  "commitment": "2dbd50596227aa78a185173a4eae92e92269cb655af4ee22d5de64731ce7d8b7",
  "failed_checks": [],
  "title": "Friday giveaway",
  "verdict": "This draw checks out.",
  "verified": true,
  "winner_entries": [
    "Naledi",
    "Thabo"
  ],
  "winners": [
    {
      "entry": "Naledi",
      "entry_number": 4,
      "position": 1
    },
    {
      "entry": "Thabo",
      "entry_number": 1,
      "position": 2
    }
  ]
}
```
