Skip to main content
In a campaign where Prizerail draws from entries, your backend sends entrants to Prizerail as they enter, each with their number of entries. At each cutoff Prizerail locks the period’s list, commits its fingerprint, and draws the winners from it with the random value, each entrant in proportion to their entries. You don’t pick winners.
Each entrant is either:
  • a string, the entrant’s id, with one entry, or
  • an object with entrantId plus an optional entries, displayName (up to 40 characters) and avatarUrl (https, up to 2,048 characters). The name and avatar show on the campaign page if they win.
Send up to 1,000 entrants per request, and as many requests as you like. A drawing takes up to 100,000 entrants.

Which draw an entrant goes to

An entrant goes to the drawing whose cutoff is next when they arrive. After a cutoff, new entrants go to the following drawing. The response says which drawing they went to.

Entries

entries is a whole number from 1 to 4,294,967,295, the entrant’s number of entries. Leave it out and it’s 1, so if you never send it, every entrant has the same chance. An entrant with 3 entries is three times as likely to win as one with 1. Nobody wins twice in one draw, unless the campaign allows repeat winners. The proofs call this number the entrant’s weight.

Sending again

Sending an entrant again before the cutoff sets their entries, name and avatar to what you sent, so a retry before the cutoff is safe and you can send a running total. After the cutoff, a retry goes to the next drawing instead. Sending them without entries sets it back to 1, so if you use it, always send it. The response counts what happened:
added, updated and unchanged count the entrants in this request. entrantCount and totalEntries are the drawing’s totals so far.

Adding instead of setting

If you’d rather add entries as users earn them than keep a running total, send "mode": "increment". Each entrant is then one event, with the entries it earns and an eventId:
Prizerail adds each event’s entries to what the entrant has in the drawing taking entries, so 1,104 entries plus 10 makes 1,114. An entrant new to the drawing starts from 0. The eventId makes this safe to repeat. Prizerail records each one for the campaign and ignores it if it comes again, so a retry after a lost response, or a queue that delivers the same event twice, never adds twice. That holds across cutoffs too: an event already counted in one drawing is ignored in the next. So:
  • Use the id of the thing that happened: an order id, a referral id, a transaction hash. With none to hand, make a UUID when the event happens and store it with the event.
  • Set it once, and send the same one every time. An id made fresh on each attempt, such as the time of sending, would add the entries again.
  • Never reuse an id for a different event. The same eventId with another entrant or number of entries is a 409 event_conflict, and nothing in that request is stored.
The response has duplicates too, the events Prizerail had already seen, in an earlier request or earlier in this one, and ignored. A name or avatar sent with an event replaces the one stored, and leaving them out, or sending them empty, keeps it. A repeated event changes nothing, its name and avatar included. To change a name with no new event, or to clear one, send the entrant in set mode with their total. An event that arrives after a cutoff goes to the next drawing, like any entry.

Checking what Prizerail has

It returns the drawing’s entrantCount, totalEntries and its entrants in arrival order, the order the list locks in, each with its entries. Without drawing, it’s the drawing taking entries now. Pass the response’s next as after for the following page, until next is null. Each entrant shows its position in the list once it has locked.

Code

Each example reads your API key from PRIZERAIL_API_KEY and the campaign’s slug from PRIZERAIL_CAMPAIGN. The SDK tab uses the prizerail package (npm install prizerail), with batching, retries and the cutoff rule built in. The others use plain HTTP: fetch in TypeScript (Node 18 or later) and requests in Python, with a 30-second timeout on every request. Make entrant ids as in Make entrant ids with an HMAC.

Send a list

Splits the list into requests of 1,000 and retries a 429, a 5xx, a timeout or a network error with a growing, jittered wait, honoring Retry-After. Before the first batch it reads which drawing is taking entries and when its cutoff is, and every batch must land in that drawing. A request is safe to repeat only until that cutoff, since sending an entrant again just sets their entries. After the cutoff, a repeat would go to the next drawing, and a request whose answer was lost may already have been stored. So the helper sends no batch and starts no retry within 30 seconds of the cutoff, its request timeout: it stops and says so, and you check where the entries went with GET /entries?drawing=<id>. Send well before the cutoff. Other errors, like a 409 for an ended campaign, stop the run.

Add entries to an entrant

Adds entries when a user earns them, with the event’s id, as in Adding instead of setting. Every retry sends the same eventId, so it’s always safe to retry.

Set one entrant’s entries

Sends a single entrant with their total, for example when one user’s count changes between your regular sends. It sets the entrant’s entries to the number you give, so send their new total, not the change. To add instead, see Add entries to an entrant.

Check what Prizerail has

Pages through the drawing taking entries now, to reconcile its entrants and total entries with your own records. Every page after the first asks for that same drawing, so a cutoff mid-way can’t mix two lists. Entrants sent while it pages can change the totals, so it also returns consistent: whether the entrants it read add up to entrantCount and totalEntries. If that’s false, page again when you’ve stopped sending.

Entrant ids

Every locked list is published, hashed, so anyone can check a draw. Use an entrant id that can’t be guessed or linked back to a person: an of your user id with a secret key, or a random id you store. A plain hash of a sequential or public user id can be reversed by trying ids. Keep the key fixed for the life of the campaign, and never use emails or usernames.The same person must have the same entrant id in every draw. The guarantee draw counts each person once by their id across a whole period. Never rotate the key mid-campaign, and never use an id made per draw, per session or per device.

Errors