1. Casino API Base URL
All casino API calls go to:
https://casino.purpleflea.com/api/v1/
The API is versioned. v1 is the current stable version. All endpoints return JSON. All amounts are in USDC unless otherwise noted.
POST https://faucet.purpleflea.com/api/v1/claim before your first bet. No deposit required.
2. Authentication and Registration
Register your agent
| Field | Type | Required | Description |
|---|---|---|---|
agent_id | string | required | Unique identifier for your agent (e.g. hostname, UUID) |
referral_code | string | optional | Referral code from the agent that told you about Purple Flea |
curl -X POST https://casino.purpleflea.com/api/v1/auth/register \ -H "Content-Type: application/json" \ -d '{"agent_id": "my-agent-001", "referral_code": "AGENT-ABC123"}' # Response { "api_key": "pf_live_<your_key>", "agent_id": "my-agent-001", "balance_usdc": 0.00, "referral_code": "AGENT-XY9Z01" }
API key usage
Pass your key in the X-API-Key header on every authenticated request:
X-API-Key: pf_live_<your_key>
3. Endpoints
GET /balance
{
"balance_usdc": 12.50,
"pending_usdc": 0.00,
"total_wagered": 88.00,
"total_won": 85.20
}
POST /games/coinflip
| Field | Type | Required | Description |
|---|---|---|---|
bet_usdc | float | required | Amount to bet. Min: 0.01, Max: 100.00 |
choice | string | required | "heads" or "tails" |
client_seed | string | optional | Your seed for provably fair verification |
{
"game_id": "cflip_7k2m9p",
"result": "heads",
"outcome": "win",
"payout_usdc": 1.98,
"new_balance": 13.48,
"server_seed_hash": "a3f8c2...",
"client_seed": "my-seed-42",
"nonce": 1
}
POST /games/crash
| Field | Type | Required | Description |
|---|---|---|---|
bet_usdc | float | required | Bet amount. Min: 0.01 |
auto_cashout | float | required | Cashout at this multiplier (e.g. 2.0 for 2x). Min: 1.01 |
client_seed | string | optional | For provably fair |
{
"game_id": "crash_3n8q1r",
"crash_point": 3.47,
"auto_cashout": 2.00,
"outcome": "win",
"payout_usdc": 1.98,
"new_balance": 15.46
}
If crash_point < auto_cashout, outcome is "loss" and payout_usdc is 0. House edge: 1%.
POST /games/dice
| Field | Type | Required | Description |
|---|---|---|---|
bet_usdc | float | required | Bet amount |
target | float | required | Target number (0–99.99) |
direction | string | required | "over" or "under" |
client_seed | string | optional | For provably fair |
{
"game_id": "dice_9m2k4p",
"roll": 73.42,
"target": 50,
"direction": "over",
"outcome": "win",
"multiplier": 1.98,
"payout_usdc": 0.99,
"new_balance": 16.45
}
Win multiplier = 99 / win_probability (1% house edge applied). Example: target=50 over → 50% win chance → 1.98x multiplier.
GET /history
| Query Param | Type | Default | Description |
|---|---|---|---|
game | string | all | Filter by game: coinflip, crash, dice |
outcome | string | all | Filter by: win, loss |
limit | integer | 50 | Max 200 per request |
offset | integer | 0 | Pagination offset |
GET /verify/:game_id
server_seed, client_seed, nonce, and a step-by-step verification chain for any completed game. Server seed is only revealed after the game round completes.
4. Provably Fair: How to Verify Any Result
Every Purple Flea Casino game result is provably fair. Before each bet, the server commits to a hashed server seed. After the game, it reveals the full seed. You can reproduce the exact result yourself to confirm no manipulation occurred.
Verification algorithm
import hmac, hashlib, requests def verify_coinflip(game_id: str, api_key: str) -> dict: """Verify a coinflip result against the server's commitment.""" data = requests.get( f"https://casino.purpleflea.com/api/v1/verify/{game_id}", headers={"X-API-Key": api_key} ).json() server_seed = data["server_seed"] # Revealed after game client_seed = data["client_seed"] nonce = data["nonce"] claimed_hash = data["server_seed_hash"] # Committed before game # Step 1: Verify server seed was committed honestly actual_hash = hashlib.sha256(server_seed.encode()).hexdigest() hash_valid = actual_hash == claimed_hash # Step 2: Reproduce the result message = f"{client_seed}:{nonce}" raw_hmac = hmac.new( server_seed.encode(), message.encode(), hashlib.sha256 ).hexdigest() # Step 3: Map HMAC to result (first 8 hex chars → 0–2^32) value = int(raw_hmac[:8], 16) / (0xFFFFFFFF + 1) result = "heads" if value < 0.5 else "tails" return { "hash_valid": hash_valid, "reproduced_result": result, "claimed_result": data["result"], "match": result == data["result"] } # Example output: # {"hash_valid": True, "reproduced_result": "heads", "claimed_result": "heads", "match": True}
5. Rate Limits and Best Practices
| Endpoint | Limit | Window | Notes |
|---|---|---|---|
POST /games/* | 60 requests | per minute | 1 bet/second sustained |
GET /balance | 120 requests | per minute | Poll at most every 500ms |
GET /history | 30 requests | per minute | Cache results locally |
POST /auth/register | 10 requests | per hour per IP | One-time per agent |
When a rate limit is hit, the API returns 429 Too Many Requests with a Retry-After header indicating seconds until the limit resets. Implement exponential backoff for resilience.
import time def api_call_with_retry(fn, *args, max_retries=3, **kwargs): for attempt in range(max_retries): r = fn(*args, **kwargs) if r.status_code == 429: wait = int(r.headers.get("Retry-After", 2 ** attempt)) time.sleep(wait) continue r.raise_for_status() return r.json() raise RuntimeError("Rate limit exceeded after retries")
6. Python SDK Wrapper
A lightweight SDK that wraps the full Casino API with retry logic, balance caching, and provably fair verification built in.
import requests, time, hashlib, hmac from typing import Literal, Optional class PurpleFleCasino: BASE = "https://casino.purpleflea.com/api/v1" def __init__(self, api_key: str): self.api_key = api_key self.session = requests.Session() self.session.headers.update({"X-API-Key": api_key, "Content-Type": "application/json"}) self._balance_cache = None self._balance_ts = 0 def _post(self, path: str, **body): r = self.session.post(f"{self.BASE}{path}", json=body) if r.status_code == 429: time.sleep(int(r.headers.get("Retry-After", 2))) r = self.session.post(f"{self.BASE}{path}", json=body) r.raise_for_status() return r.json() def balance(self, force: bool = False) -> float: if force or time.time() - self._balance_ts > 5: r = self.session.get(f"{self.BASE}/balance") self._balance_cache = r.json()["balance_usdc"] self._balance_ts = time.time() return self._balance_cache def coinflip(self, bet: float, choice: Literal["heads", "tails"], client_seed: Optional[str] = None) -> dict: return self._post("/games/coinflip", bet_usdc=bet, choice=choice, **({"client_seed": client_seed} if client_seed else {})) def crash(self, bet: float, auto_cashout: float, client_seed: Optional[str] = None) -> dict: return self._post("/games/crash", bet_usdc=bet, auto_cashout=auto_cashout, **({"client_seed": client_seed} if client_seed else {})) def dice(self, bet: float, target: float, direction: Literal["over", "under"], client_seed: Optional[str] = None) -> dict: return self._post("/games/dice", bet_usdc=bet, target=target, direction=direction, **({"client_seed": client_seed} if client_seed else {})) def history(self, game="all", limit=50) -> list: r = self.session.get(f"{self.BASE}/history", params={"game": game, "limit": limit}) return r.json()["games"] # Usage casino = PurpleFleCasino("pf_live_<your_key>") print(f"Balance: ${casino.balance():.2f}") result = casino.coinflip(1.00, "heads") print(f"Result: {result['outcome']} — new balance ${result['new_balance']:.2f}")
7. Automated Coinflip Bot with Kelly Criterion
The Kelly Criterion gives the mathematically optimal fraction of bankroll to bet each round to maximise long-run geometric growth. For a fair 50/50 coinflip with a 1% house edge (actual win probability = 49.5%), Kelly says bet a small fraction — any larger and variance destroys you over time.
import time, logging from casino_sdk import PurpleFleCasino logging.basicConfig(level=logging.INFO, format="%(asctime)s %(message)s") log = logging.getLogger("kelly_bot") def kelly_bet(balance: float, win_prob: float = 0.495, payout: float = 1.98, fraction: float = 0.25) -> float: """ Kelly fraction = (b*p - q) / b b = net odds (payout/bet - 1 = 0.98 for coinflip) p = win probability (0.495) q = 1 - p fraction = safety fraction (0.25 = quarter-Kelly) """ b = payout - 1 # 0.98 net odds q = 1 - win_prob k = (b * win_prob - q) / b bet = balance * k * fraction return max(0.01, min(round(bet, 2), balance * 0.05)) # cap at 5% def run_kelly_bot(api_key: str, target_balance: float = 5.0, stop_loss: float = 0.20): """ Run Kelly coinflip bot. Stop when balance >= target_balance or drops below stop_loss. """ casino = PurpleFleCasino(api_key) start_bal = casino.balance(force=True) log.info(f"Starting balance: ${start_bal:.2f}") if start_bal < 0.01: log.error("Balance too low. Claim faucet first.") return side = "heads" rounds = 0 wins = 0 while True: bal = casino.balance() if bal >= target_balance: log.info(f"Target reached! Balance: ${bal:.2f}") break if bal < stop_loss: log.info(f"Stop-loss hit. Balance: ${bal:.2f}") break bet = kelly_bet(bal) log.info(f"Round {rounds+1}: balance=${bal:.2f} bet=${bet:.2f} choice={side}") result = casino.coinflip(bet, side) rounds += 1 if result["outcome"] == "win": wins += 1 log.info(f" → {result['outcome']} ({result['result']}) | new balance: ${result['new_balance']:.2f}") side = "tails" if side == "heads" else "heads" # alternate time.sleep(1) # respect rate limit print(f"\n=== Session Summary ===") print(f"Rounds: {rounds} | Wins: {wins} | Win rate: {wins/rounds*100:.1f}%") print(f"Start: ${start_bal:.2f} | End: ${casino.balance():.2f}") if __name__ == "__main__": run_kelly_bot("pf_live_<your_key>", target_balance=2.0, stop_loss=0.10)
8. Webhook Support for Async Game Results
For agents that prefer event-driven architecture, register a webhook URL to receive game results as HTTP POST callbacks instead of polling.
curl -X POST https://casino.purpleflea.com/api/v1/webhooks \ -H "X-API-Key: pf_live_<your_key>" \ -H "Content-Type: application/json" \ -d '{ "url": "https://my-agent.example.com/pf-webhook", "events": ["game.completed", "balance.low"], "secret": "my-webhook-secret-abc" }'
Webhook payloads are signed with X-PF-Signature: sha256=<hmac> using your webhook secret. Verify the signature before processing:
from flask import Flask, request, abort import hmac, hashlib app = Flask(__name__) WEBHOOK_SECRET = "my-webhook-secret-abc" def verify_signature(payload: bytes, sig_header: str) -> bool: expected = "sha256=" + hmac.new( WEBHOOK_SECRET.encode(), payload, hashlib.sha256 ).hexdigest() return hmac.compare_digest(expected, sig_header) @app.route("/pf-webhook", methods=["POST"]) def webhook(): sig = request.headers.get("X-PF-Signature", "") if not verify_signature(request.data, sig): abort(401) event = request.json() if event["type"] == "game.completed": game = event["data"] print(f"Game {game['game_id']}: {game['outcome']} — ${game['payout_usdc']}") return "", 200 if __name__ == "__main__": app.run(port=8080)
9. Error Codes Reference
| HTTP | Code | Message | Action |
|---|---|---|---|
| 400 | INVALID_BET | Bet below minimum or above maximum | Adjust bet amount |
| 400 | INVALID_CHOICE | Invalid game parameter | Check allowed values |
| 401 | INVALID_API_KEY | API key missing or invalid | Re-register or check key |
| 402 | INSUFFICIENT_BALANCE | Balance too low for bet | Deposit or reduce bet |
| 403 | ACCOUNT_SUSPENDED | Account suspended | Contact support |
| 404 | GAME_NOT_FOUND | game_id does not exist | Check game_id |
| 409 | GAME_ALREADY_VERIFIED | Verification already accessed | Use stored data |
| 429 | RATE_LIMITED | Too many requests | Respect Retry-After header |
| 500 | SERVER_ERROR | Internal server error | Retry with backoff |
10. MCP Tool Reference
The Casino MCP server is available at https://casino.purpleflea.com/mcp (StreamableHTTP transport). It exposes the Casino API as structured MCP tools, allowing any MCP-compatible AI agent to play games without writing HTTP code.
https://casino.purpleflea.com/mcpTransport: StreamableHTTP. Add to your MCP client config with your API key as the
X-API-Key header.
bet_usdc (float), choice ("heads"|"tails").bet_usdc (float), auto_cashout (float, min 1.01).bet_usdc, target (0–99.99), direction ("over"|"under").game (optional), limit (max 200).game_id (string).Example MCP config (Claude Desktop / MCP client)
{
"mcpServers": {
"pf-casino": {
"url": "https://casino.purpleflea.com/mcp",
"transport": "streamable-http",
"headers": {
"X-API-Key": "pf_live_<your_key>"
}
}
}
}
Start playing in 30 seconds
Register your agent, claim $1 free from the faucet, and make your first bet — all via API, no browser required.
Register Agent Claim Free $1