Two ways to integrate: a read-only REST API for your raffle data, and a drop-in widget that renders your live raffles on any site.
sk_…) are issued per organisation by your account manager.
A key resolves your organisation on every call — you only ever see your own data.
Keys are shown once at creation; store them in your server's secrets, never in a browser.
Send your secret key as a bearer token on every request:
Authorization: Bearer sk_live_your_key
| Response | Meaning |
|---|---|
401 missing_api_key | No Authorization header. |
401 invalid_api_key | Key unknown or revoked. |
403 insufficient_scope | Key lacks the scope named in required. |
404 not_found | The resource isn't yours (or doesn't exist). |
Scopes: competitions:read, winners:read. Keys default to both.
https://www.bitraffle.io/api/v1
Use the same host your key was issued for. Machine-readable spec: /api/v1/openapi.json (OpenAPI 3.0 — import it into Postman, Insomnia or an SDK generator).
curl -H "Authorization: Bearer sk_live_your_key" \
https://www.bitraffle.io/api/v1/competitions
{
"data": [
{
"id": 42,
"title": "Win a Rolex Submariner Date",
"description": "…markdown…",
"ticketPriceUSDCents": 2500,
"paymentToken": "USDC",
"maxTickets": 500,
"ticketsSold": 103,
"status": "active",
"endDate": "2026-08-01T12:00:00.000Z",
"imageUrl": "https://…",
"payment": { "acceptedTokens": ["USDC"], "fiat": true, "fiatCurrency": "VND" }
}
]
}
payment tells you how this raffle can be paid for right now — which crypto tokens, whether card/bank checkout is on, and the single fiat currency it charges. Use it to render the right checkout options.
curl -H "Authorization: Bearer sk_live_your_key" \
https://www.bitraffle.io/api/v1/competitions/42
Same shape, single object under data. Returns 404 for ids outside your organisation.
curl -H "Authorization: Bearer sk_live_your_key" \
https://www.bitraffle.io/api/v1/winners
{
"data": [
{
"competitionId": 42,
"competitionTitle": "Win a Rolex Submariner Date",
"winnerWalletAddress": "0x1234…abcd",
"wonAt": "2026-07-20T09:15:00.000Z",
"draw": { "blockNumber": 6512233, "blockHash": "0x…", "winnerIndex": 87, "totalTickets": 500 }
}
]
}
Every draw is provably fair: we commit to a future block before it exists, then
winnerIndex = keccak256(blockHash · competitionId) mod totalTickets. The draw object is everything an
entrant needs to re-compute the result independently.
| Rule | Detail |
|---|---|
| Money | Integers, never floats. ticketPriceUSDCents is USD cents (2500 = $25.00). |
| Dates | ISO 8601 UTC strings. |
| Envelope | Success payloads are always under data; errors carry error (+ message). |
| Method | Reads only (GET). Entry creation isn't exposed — buyers check out on the hosted raffle pages. |
Each API key gets its own budget — one partner's traffic can never slow another's:
| Header | Meaning |
|---|---|
X-RateLimit-Limit | Requests allowed per window. |
X-RateLimit-Remaining | Requests left right now. |
X-RateLimit-Reset | Unix seconds when your budget is fully restored. |
Retry-After | Only on 429 — seconds to wait. |
HTTP/1.1 429 Too Many Requests
Retry-After: 12
{ "error": "rate_limited", "message": "Too many requests …", "retryAfter": 12 }
The budget refills continuously rather than resetting on a fixed boundary, so steady traffic is never cliff-blocked. Cache responses for a minute where you can — raffle data doesn't change faster than that. Need a higher ceiling for a launch? Ask your account manager.
Drop your live raffles onto any page with one script tag. It injects a responsive iframe; nothing else on the host page is touched.
<script src="https://www.bitraffle.io/widget.js" data-org="house"></script>
| Attribute | Required | Value |
|---|---|---|
data-org | yes | Your organisation slug — house. |
data-competition | no | A competition id. Present → single-raffle mode (below); absent → the grid of all your active raffles. |
The widget inherits your brand colour automatically, so embeds match your portal.
Exactly what the snippet above renders, running right now with BitRaffle's live raffles. Cards update themselves as raffles sell and close.
…your page content…
…rest of your page…
Add data-competition to feature exactly one raffle: a bigger image, ticket price, a live
countdown to the draw, sold progress and a branded call-to-action. Ideal for a landing page, a blog post
or a campaign email's landing page.
<script src="https://www.bitraffle.io/widget.js"
data-org="house"
data-competition="68"></script>
…your campaign copy…
Visitors pick a quantity in the widget and hit Enter raffle — checkout then opens in a secure popup on our domain: sign-in (email or wallet), the skill question, and payment (card/bank, QR or crypto). Your page never navigates away. When the purchase completes, the widget updates in place with a confirmation.
Nothing to implement — it's built into the widget. Fulfilment, notifications and the draw are handled for you.
Prefer your own frame? Embed https://www.bitraffle.io/embed/house (or
/embed/house/competition/{id}) directly — set any width/height you like:
<iframe src="https://www.bitraffle.io/embed/house"
style="width:100%;border:0;min-height:520px" loading="lazy"
title="Raffles"></iframe>
Every raffle has a generated 1200×630 social card at https://www.bitraffle.io/og/competition/{id}.png — usable as an
og:image on your own pages.
Tell us about your integration and we'll issue a key. The widget needs no key — you can embed that today.
Already a partner? Contact your account manager. Spec: openapi.json.