BTC Prediction Pools API
Closest-guess BTC price contest. Each pool runs on a fixed cadence — btc-5m settles every 5 minutes, btc-4h every 4 hours. Predict where BTC/USD will be at settlement; the prediction closest to the settlement price (P1) takes the whole pool. Stakes run $0.10 to $1,000,000 per round. One prediction per user per round (re-entering tops up your stake at your latest price).
Round Lifecycle
Every round moves through: entry (predictions accepted, and cancellable for a full refund) → locked (entries frozen at P0, measuring window running) → settled (P1 taken; the closest prediction wins the pool) or voided (index unavailable past the grace window — fail-closed, all stakes refunded in full). The /state endpoint returns all three views at once: the open entry_round, the measuring_round, and the last_round.
Authentication
Read endpoints are public. POST /api/v1/btc-pool/enter and GET /api/v1/btc-pool/me require a JWT.
curl -X POST https://cymetica.com/auth/login \
-H "Content-Type: application/json" \
-d '{"email": "you@example.com", "password": "…"}'
# → {"access_token": "…", "token_type": "bearer"}
# Then on every authenticated call:
# Authorization: Bearer <access_token>
Endpoints
/api/v1/btc-pool/state?pool=btc-5mPublic state of one pool: the open entry round (with the anonymized prediction tape), the locked measuring round, the last terminal round, and the live BTC/USD index. pool defaults to btc-4h.
curl "https://cymetica.com/api/v1/btc-pool/state?pool=btc-5m"
{
"pool": "btc-5m",
"enabled": true,
"now": "2026-07-21T04:20:00+00:00",
"entry_round": {
"pool": "btc-5m",
"round_epoch": 5948760,
"status": "entry",
"entry_opens_at": "2026-07-21T04:20:00+00:00",
"locks_at": "2026-07-21T04:25:00+00:00",
"settles_at": "2026-07-21T04:30:00+00:00",
"p0": null, "p1": null,
"winning_price": null, "winning_distance": null,
"winners_count": null, "void_reason": null,
"entries": 2,
"pool_usdc": "0.20",
"min_entry_usdc": "0.10",
"max_entry_usdc": "1000000",
"fee_pct": "0",
"predictions": [
{"price": "65476.59", "amount_usdc": "0.10"},
{"price": "65493.59", "amount_usdc": "0.10"}
]
},
"measuring_round": { "...": "same shape, status locked, p0 set" },
"last_round": { "...": "same shape, status settled or voided" },
"index": {"price": "65481.22", "at": "2026-07-21T04:19:58+00:00"}
}
/api/v1/btc-pool/enterEnter (or top up) a prediction in the currently-open round. Requires auth. Funds are debited from your USDC balance and escrowed until settlement. predicted_price must be > 0 and ≤ 100,000,000; amount_usdc must be between 0.10 and 1,000,000 (cumulative per user per round).
curl -X POST https://cymetica.com/api/v1/btc-pool/enter \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"predicted_price": "65450.00", "amount_usdc": "1.00", "pool": "btc-5m"}'
{
"pool": "btc-5m",
"round_epoch": 5948760,
"predicted_price": "65450.00",
"amount_usdc": "1.00",
"pool_usdc": "1.20",
"entries": 3
}
/api/v1/btc-pool/cancelCancel your entry in the currently-open round — full refund of the escrowed stake, allowed strictly until lock. Requires auth. After cancelling you may re-enter the same round (at any price) while it is still open.
curl -X POST https://cymetica.com/api/v1/btc-pool/cancel \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"pool": "btc-5m"}'
{
"pool": "btc-5m",
"round_epoch": 5948760,
"refunded_usdc": "1.00",
"pool_usdc": "0.20",
"entries": 2
}
/api/v1/btc-pool/me?pool=btc-5mYour ticket in the open round, your all-time net profit in this pool (profit_usdc — terminal rounds only, so it accumulates as rounds settle), plus your last 20 settled/voided outcomes. Requires auth.
{
"enabled": true,
"pool": "btc-5m",
"profit_usdc": "0.10",
"entry": {"predicted_price": "65450.00", "amount_usdc": "1.00"},
"history": [
{
"round_epoch": 5948683,
"status": "settled",
"predicted_price": "65493.59",
"amount_usdc": "0.10",
"payout_usdc": "0.20",
"refund_usdc": null,
"p1": "65493.51",
"winning_price": "65493.59"
}
]
}
/api/v1/btc-pool/history?pool=btc-5m&limit=24Recent terminal rounds (settled or voided), newest first. Public. limit 1–200, default 24.
{
"pool": "btc-5m",
"rounds": [
{
"pool": "btc-5m",
"round_epoch": 5948683,
"status": "settled",
"p0": "65488.10",
"p1": "65493.51",
"winning_price": "65493.59",
"winning_distance": "0.08",
"winners_count": 1,
"entries": 2,
"pool_usdc": "0.20",
"fee_pct": "0"
}
]
}
WebSocket
One socket streams every pool — no polling, no auth, public aggregates only. Each message is {"type": …, "data": …, "ts": …}; state-scoped messages carry data.pool, so filter on it client-side.
wss://cymetica.com/ws/btc-pool
| Type | When | Payload (data) |
|---|---|---|
state | On connect (one per pool) and every ~10s | Full public state — same shape as GET /state |
index_tick | ~1s, when the BTC/USD index changes | {"price", "at"} |
pool_update | Someone entered the open round | {"pool", "round_epoch", "entries", "pool_usdc"} |
round_update | A round locked / settled / voided | Round dict (same shape as rounds in /history) |
wins_recent | On connect | {"wins": […]} — recent anonymized wins (country-level, no PII) |
win_event | A round settles with a winner | One anonymized win — powers the global win map |
Keepalive: send the literal text ping → server replies pong. Idle sockets receive a JSON {"type": "ping"} every 60s.
Rate Limits
Standard platform rate limits apply per IP/account — see the X-RateLimit-* headers on REST responses. Entry is additionally bounded by the per-round cumulative stake cap ($1,000,000 per user per round).
Errors
Errors return {"detail": "…"} with a standard status code:
| Code | Meaning |
|---|---|
400 | Unknown pool, entries locked, stake outside $0.10–$1,000,000, insufficient balance, no entry to cancel |
401 | Missing/invalid JWT on /enter, /cancel, or /me |
503 | Pool not live ("This pool is not live yet") |