Run competitions
Prizes and competitions
Run competitions from your own tools: describe a prize, put a competition on it, open it, and cancel it if you must.
Create the prize
A prize needs a retail value and either a name, or a brand and model. Its photos and category are what competitions on it show, and the category picks the entry question.
curl -X POST https://www.bitraffle.io/api/v1/prizes \ -H "Authorization: Bearer $BITRAFFLE_SECRET_KEY" \ -H "Content-Type: application/json" \ -d '{ "category": "electronics", "brand": "Apple", "model": "MacBook Pro 14-inch (M5)", "condition": "new", "retailValueUSDCents": 199900, "imageUrls": ["https://your-cdn.com/macbook-pro-14.png"] }'const res = await fetch("https://www.bitraffle.io/api/v1/prizes", { method: "POST", headers: { Authorization: `Bearer ${process.env.BITRAFFLE_SECRET_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ category: "electronics", brand: "Apple", model: "MacBook Pro 14-inch (M5)", condition: "new", retailValueUSDCents: 199900, imageUrls: ["https://your-cdn.com/macbook-pro-14.png"], }), }); const { data: prize } = await res.json();Create the competition
Price tickets in USD cents. It is created as a
draft.cURLcurl -X POST https://www.bitraffle.io/api/v1/competitions \ -H "Authorization: Bearer $BITRAFFLE_SECRET_KEY" \ -H "Content-Type: application/json" \ -d '{ "prizeId": 66, "title": "Win a MacBook Pro 14", "ticketPriceUSDCents": 100, "maxTickets": 3000, "startDate": "2026-10-02T12:00:00Z", "endDate": "2026-11-06T12:00:00Z", "paymentToken": "USDC" }'Open it
Set its status to
active. It starts selling at its start date.cURLcurl -X PATCH https://www.bitraffle.io/api/v1/competitions/70 \ -H "Authorization: Bearer $BITRAFFLE_SECRET_KEY" \ -H "Content-Type: application/json" \ -d '{ "status": "active" }'
Competitions on the blockchain
Send createOnChain: true to create the competition on the raffle contract as well, so crypto entries are recorded and drawn on-chain. It goes live once the contract transaction is confirmed, which can include an approval on our side; until then it stays a draft. The end time on the contract is exactly your endDate.
Lifecycle
status is what is stored; state is what it means right now. Use state to decide whether to show an entry button: only open competitions sell.
state | Meaning |
|---|---|
draft | Created, not open yet. |
scheduled | Open, but its start date is in the future. |
open | Selling. |
closing | Its end time has passed; the draw is due. |
drawn | A winner was drawn. |
retired | Closed without a draw. |
cancelled | Cancelled. Buyers can claim refunds. |
Payment methods
A competition accepts your organisation's payment methods unless you narrow them with payment: crypto and fiat switch each on or off, and fiatCurrency sets the one currency a card payment charges. Leave a field out, or set it to null, to follow your organisation's settings. A change that would leave no way to pay is refused.
Cancelling
POST /competitions/{id}/cancel is final. It stops sales, reverses affiliate commissions, and for on-chain competitions lets buyers claim their refunds from the contract. A competition whose draw has started or finished cannot be cancelled.