Developers
Automate your bets. Read markets and live odds, place bets with an API key, and follow everything as it happens on the event stream.
API keys
Sign in with your wallet to create keys. Bets placed with a key come out of that wallet's SOL balance.
Basics
- Base URL
https://api.cucumarket.xyz- Auth
Authorization: Bearer ck_…on bet and account endpoints. Market data and the stream are public.- Limits
- 120 requests and 30 bets per minute per key. Over the limit you get 429 with a Retry-After header.
- Errors
- JSON
{ error }with 400 bad input, 401 bad key, 404 not found, 409 bet refused (closed, not enough SOL, odds moved), 429 rate limited.
Endpoints
| Method | Path | Key | What it does |
|---|---|---|---|
| GET | /v1/markets | – | Markets with live odds and their token's live numbers (market cap, curve %, dev bag, launchpad, and stock: the ticker a coin is themed on, or null). Filters: status=open|settled|all, kind=bond|peak|dev_dump, mint, limit (≤500). |
| GET | /v1/markets/{id} | – | One market plus its most recent bets. |
| POST | /v1/bets | key | Place a bet: {marketId, side, amount, clientId?, maxOdds?}. Amount is in SOL. side is yes or no. |
| GET | /v1/bets | key | Your bets. Filter with status=open|settled. |
| GET | /v1/me | key | Your wallet, SOL balance and SOL riding on open markets. |
| GET | /v1/stream | – | Server-Sent Events: listed, bonded, bet, resolved, mcap. Optional ?mint= filter. |
Placing bets safely
- clientId: your own id for the bet. Send the same clientId again (say after a timeout) and you get the original bet back with
duplicate: true. It is never placed twice. - maxOdds: the most you'll pay for your side, from 0 to 1. If the market's odds for that side are above it when the bet arrives, it's refused with 409 and nothing is spent.
- odds on every market:
yesandnoare the live prices,modelis what the on-chain model alone says before bets pull it. Payouts are parimutuel: winners split the pool.
Examples
curl
# List open bonding markets
curl https://api.cucumarket.xyz/v1/markets?kind=bond
# Bet 0.25 SOL on YES, only if YES costs at most 60%
curl -X POST https://api.cucumarket.xyz/v1/bets \
-H "Authorization: Bearer $CUCU_KEY" \
-H "Content-Type: application/json" \
-d '{"marketId": 123, "side": "yes", "amount": 0.25, "clientId": "run-42", "maxOdds": 0.6}'A small bot (Node 18+)
// A tiny bot: back YES on bonding markets the curve model likes more than the crowd
const API = "https://api.cucumarket.xyz";
const KEY = process.env.CUCU_KEY;
const headers = { Authorization: `Bearer ${KEY}`, "Content-Type": "application/json" };
const markets = await fetch(`${API}/v1/markets?kind=bond`).then((r) => r.json());
for (const m of markets) {
if (!m.odds || m.odds.model - m.odds.yes < 0.1) continue; // model sees 10%+ more upside
const res = await fetch(`${API}/v1/bets`, {
method: "POST",
headers,
body: JSON.stringify({
marketId: m.id,
side: "yes",
amount: 0.1, // SOL
clientId: `edge-${m.id}`, // safe to retry: same clientId never bets twice
maxOdds: m.odds.model, // skip if the price moved past our fair value
}),
});
console.log(m.symbol, m.question, res.status, await res.json());
}Live events
const events = new EventSource("https://api.cucumarket.xyz/v1/stream");
events.addEventListener("listed", (e) => console.log("new token", JSON.parse(e.data)));
events.addEventListener("bet", (e) => console.log("bet", JSON.parse(e.data)));
events.addEventListener("resolved", (e) => console.log("settled", JSON.parse(e.data)));