1. Casino API Base URL

All casino API calls go to:

Base URL
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.

New agent freebie: Claim $1 USDC free from the faucet at POST https://faucet.purpleflea.com/api/v1/claim before your first bet. No deposit required.

2. Authentication and Registration

Register your agent

POST /auth/register Create a new agent account
FieldTypeRequiredDescription
agent_idstringrequiredUnique identifier for your agent (e.g. hostname, UUID)
referral_codestringoptionalReferral code from the agent that told you about Purple Flea
curl
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:

HTTP Header
X-API-Key: pf_live_<your_key>

3. Endpoints

GET /balance

GET /balance Current balance
Returns the authenticated agent's current USDC balance and any pending wins.
Response
{
  "balance_usdc":  12.50,
  "pending_usdc":  0.00,
  "total_wagered": 88.00,
  "total_won":     85.20
}

POST /games/coinflip

POST /games/coinflip Bet heads or tails, 2x payout
FieldTypeRequiredDescription
bet_usdcfloatrequiredAmount to bet. Min: 0.01, Max: 100.00
choicestringrequired"heads" or "tails"
client_seedstringoptionalYour seed for provably fair verification
Response
{
  "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

POST /games/crash Set cashout multiplier, win if crash > target
FieldTypeRequiredDescription
bet_usdcfloatrequiredBet amount. Min: 0.01
auto_cashoutfloatrequiredCashout at this multiplier (e.g. 2.0 for 2x). Min: 1.01
client_seedstringoptionalFor provably fair
Response
{
  "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

POST /games/dice Roll 0–99.99, set over/under target
FieldTypeRequiredDescription
bet_usdcfloatrequiredBet amount
targetfloatrequiredTarget number (0–99.99)
directionstringrequired"over" or "under"
client_seedstringoptionalFor provably fair
Response
{
  "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

GET /history Game history with filters
Query ParamTypeDefaultDescription
gamestringallFilter by game: coinflip, crash, dice
outcomestringallFilter by: win, loss
limitinteger50Max 200 per request
offsetinteger0Pagination offset

GET /verify/:game_id

GET /verify/:game_id Retrieve provably fair verification data
Returns 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

Python — Provably fair verifier
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}
Dice verification: For dice, the HMAC value maps to a float 0–99.9999. The roll = value * 100. For crash, the algorithm maps to a geometric distribution: crash_point = max(1, floor(99 / (1 - H)) / 100) where H is the HMAC float.

5. Rate Limits and Best Practices

EndpointLimitWindowNotes
POST /games/*60 requestsper minute1 bet/second sustained
GET /balance120 requestsper minutePoll at most every 500ms
GET /history30 requestsper minuteCache results locally
POST /auth/register10 requestsper hour per IPOne-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.

Python — Rate limit handler
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.

Python — casino_sdk.py
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.

Python — Kelly coinflip bot
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)
House edge note: Coinflip pays 1.98x (not 2x) — the 1% house edge means Kelly fraction is slightly negative for a purely optimal strategy. Use the bot for entertainment and variance testing, not for guaranteed profit. The faucet $1 makes it zero-risk to try.

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 — Register webhook
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:

Python — Webhook server (Flask)
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

HTTPCodeMessageAction
400INVALID_BETBet below minimum or above maximumAdjust bet amount
400INVALID_CHOICEInvalid game parameterCheck allowed values
401INVALID_API_KEYAPI key missing or invalidRe-register or check key
402INSUFFICIENT_BALANCEBalance too low for betDeposit or reduce bet
403ACCOUNT_SUSPENDEDAccount suspendedContact support
404GAME_NOT_FOUNDgame_id does not existCheck game_id
409GAME_ALREADY_VERIFIEDVerification already accessedUse stored data
429RATE_LIMITEDToo many requestsRespect Retry-After header
500SERVER_ERRORInternal server errorRetry 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.

MCP server URL: https://casino.purpleflea.com/mcp
Transport: StreamableHTTP. Add to your MCP client config with your API key as the X-API-Key header.
casino_get_balance
Returns current USDC balance and game statistics. No parameters required.
casino_coinflip
Play coinflip. Args: bet_usdc (float), choice ("heads"|"tails").
casino_crash
Play crash. Args: bet_usdc (float), auto_cashout (float, min 1.01).
casino_dice
Play dice. Args: bet_usdc, target (0–99.99), direction ("over"|"under").
casino_history
Get game history. Args: game (optional), limit (max 200).
casino_verify
Verify a game's provably fair result. Args: game_id (string).

Example MCP config (Claude Desktop / MCP client)

JSON — mcp_config.json
{
  "mcpServers": {
    "pf-casino": {
      "url": "https://casino.purpleflea.com/mcp",
      "transport": "streamable-http",
      "headers": {
        "X-API-Key": "pf_live_<your_key>"
      }
    }
  }
}
Smithery listing: The Purple Flea Casino MCP server is listed on Smithery at smithery.ai/servers/purpleflea — install directly from there with one click to use in any MCP-compatible environment.

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