API · v1

Spinly Developer API

A small, signed REST API for pulling random picks and controlling live sessions from scripts, bots, Stream Deck, or your own apps. Every result includes a verifiable receipt code.

Get a key

Open profile → Developer → Create.

Base URL

https://[your-domain]/api/v1

Auth

Send X-Api-Key: spk_live_… on every request.

POST/api/v1/random

Pick a random item

Returns one item from the supplied list, plus a signed receipt that anyone can verify with the /verify endpoint. Pass an optional seed to make the pick deterministic.

Request

curl -X POST https://[your-domain]/api/v1/random \
  -H "X-Api-Key: spk_live_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"items":["alice","bob","carol","dave"]}'

Response

{
  "ok": true,
  "pick": "carol",
  "index": 2,
  "candidate_count": 4,
  "receipt": {
    "code": "K7QH3M9XJB2P",
    "signature": "f3a1...",
    "created_at": "2026-04-20T10:23:11.512Z"
  },
  "seeded": false
}

GET shortcut

curl "https://[your-domain]/api/v1/random?items=alice,bob,carol&seed=demo" \
  -H "X-Api-Key: spk_live_xxxxxxxxxxxx"

Limits: 2–500 items, each ≤200 chars. Rate limit: 60 req/min/key.

GET/api/v1/verify/:code

Verify a receipt

Public. Anyone holding a Spinly receipt code can confirm it's genuine and see the original candidate list. The server re-computes the HMAC signature on every call so a tampered DB row would be detected.

curl "https://[your-domain]/api/v1/verify/K7QH3M9XJB2P"

Response

{
  "ok": true,
  "valid": true,
  "receipt": {
    "code": "K7QH3M9XJB2P",
    "source": "api.random",
    "pick": "carol",
    "candidates": ["alice","bob","carol","dave"],
    "signature": "f3a1...",
    "created_at": "2026-04-20T10:23:11.512Z",
    "session_id": null
  }
}

Rate limit: 120 req/min/IP.

POST/api/v1/sessions

Create a live session

Creates a wheel/picker/team/raffle room programmatically. The response includes a host_token — keep it secret. You'll need it to spin or end the session via the API.

curl -X POST https://[your-domain]/api/v1/sessions \
  -H "X-Api-Key: spk_live_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"tool":"wheel","max_per_user":1}'

Response

{
  "ok": true,
  "session": {
    "id": "1c2e...",
    "code": "428193",
    "tool": "wheel",
    "created_at": "...",
    "expires_at": "..."
  },
  "host_token": "a1b2c3...",
  "join_url": "https://[your-domain]/join?code=428193"
}

Rate limit: 10 req/min/key.

POST/api/v1/sessions/:code/spin

Spin a live session

Picks a winner from the session's current entries (weighted by ticket count, same as the in-app raffle), writes it back so connected guests see the result in real-time, and returns a signed receipt.

curl -X POST https://[your-domain]/api/v1/sessions/428193/spin \
  -H "X-Api-Key: spk_live_xxxxxxxxxxxx" \
  -H "X-Host-Token: a1b2c3..."

Response

{
  "ok": true,
  "winner": { "name": "Jordan", "color": "#7c3aed" },
  "receipt": {
    "code": "K7QH3M9XJB2P",
    "signature": "f3a1...",
    "created_at": "..."
  },
  "candidate_count": 12
}

Errors: 404 if code unknown, 403 if host token wrong, 409 if no entries, 410 if the session has ended. Rate limit: 30 req/min/key.

Errors

  • 400 — bad input (zod validation message in error)
  • 401 — missing or invalid X-Api-Key
  • 403 — wrong host token
  • 404 — session or receipt not found
  • 409 — session has no entries to pick from
  • 429 — rate limited (check Retry-After)
  • 500 — server error