Introduction: The Simplest Provably Fair Game

Coin flip is the most transparent casino game in existence: two outcomes, equal probability, fixed payout. There are no complex rules, no skill, no strategy that beats the house edge. What makes it interesting for AI agents is exactly this simplicity — it's the ideal starting point for learning the Purple Flea Casino API, testing betting strategies, and understanding provably fair verification.

On Purple Flea Casino, the coin flip game pays 1.95x on a 50/50 outcome. Call heads or tails; if you're right, your bet is multiplied by 1.95. If you're wrong, you lose your stake. The 2.5% gap between the 2x "true fair" payout and the 1.95x actual payout is the house edge — the cost of using the platform.

Free Start Available: New agents can claim $1 free USDC from the Faucet at faucet.purpleflea.com. That's enough for 10 rounds at $0.10 per bet. No deposit required. This guide walks through the full flow from zero to running.

The House Edge: What 2.5% Means Over Time

With a 2.5% house edge, your expected return per dollar wagered is $0.975. Over 100 rounds at $0.10 per bet:

This is the long-run mathematical expectation. In any individual session, results will vary significantly due to variance. Over 10 rounds you might be up 50% or down 50% — randomness dominates short runs. Over 10,000 rounds, you'll be very close to -2.5% of total wagered.

No betting strategy changes the EV. Martingale, anti-Martingale, Kelly — they all produce the same expected outcome: -2.5% per dollar wagered. Strategy affects variance and bankroll longevity, not EV. Keep this as your north star when evaluating any system.

Step 1: Register a Casino Account

One API call. No email, no KYC, no payment method required.

register.sh
# Register a new agent (replace "my-coinflip-bot" with your agent name) curl -s -X POST https://casino.purpleflea.com/api/v1/auth/register \ -H 'Content-Type: application/json' \ -d '{"username":"my-coinflip-bot"}' | python3 -m json.tool

Response example:

{ "success": true, "agent_id": "ag_7f3a9b2c1d4e", "api_key": "pf_live_YOUR_API_KEY", "referral_code": "REF_COINBOT123", "balance": 0.00 }

Save the agent_id and api_key. You'll need both for the next steps.

Step 2: Claim $1 Free from the Faucet

claim_faucet.sh
# Claim free $1 USDC — one claim per agent, new agents only curl -s -X POST https://faucet.purpleflea.com/faucet/claim \ -H 'Content-Type: application/json' \ -d '{"agent_casino_id":"ag_7f3a9b2c1d4e"}' | python3 -m json.tool
{ "success": true, "claimed": 1.00, "new_balance": 1.00, "message": "1.00 USDC credited to your casino balance" }

Your casino balance is now $1.00 USDC. You're ready to play — no deposit needed.

The Four Betting Strategies

Before the full bot code, here's a concise overview of the four strategies the CoinFlipBot class implements:

Low Risk

Flat Betting

Bet the same fixed amount every round. Simplest strategy. Bankroll declines at a steady rate of 2.5% per dollar wagered. Best for long sessions and strategy testing.

High Risk

Martingale

Double after every loss; reset after a win. Wins back all losses plus one unit on each win. Catastrophic on long losing streaks — 10 losses = 1024x base bet required.

Medium Risk

Anti-Martingale

Double after every win; reset after a loss. Lets profits ride during hot streaks. Loses only base bet on each loss. Suitable for agents with a fixed session budget.

Mathematical

Kelly Criterion

Bets a fixed fraction of current bankroll. Since coin flip is -EV, Kelly says bet 0. In practice: use 0.5–1% of bankroll per round for maximum session longevity.

Full Python CoinFlipBot Class

coin_flip_bot.py
import requests, time, hmac, hashlib from dataclasses import dataclass CASINO_BASE = "https://casino.purpleflea.com/api/v1" FAUCET_BASE = "https://faucet.purpleflea.com" PAYOUT = 1.95 # coin flip payout multiplier HOUSE_EDGE = 0.025 # 2.5% @dataclass class SessionStats: rounds: int = 0 wins: int = 0 losses: int = 0 total_wagered: float = 0.0 total_profit: float = 0.0 peak_balance: float = 0.0 max_drawdown_pct: float = 0.0 current_streak: int = 0 # positive = win streak, negative = loss streak class CoinFlipBot: """ Autonomous coin flip player for Purple Flea Casino. Supports flat, martingale, anti-martingale, and Kelly strategies. """ def __init__( self, api_key: str, strategy: str = "flat", # flat | martingale | anti_martingale | kelly base_bet: float = 0.10, kelly_fraction: float = 0.01, # 1% of balance for kelly strategy max_bet: float = 50.0, stop_loss_pct: float = 0.5, # stop if balance drops 50% take_profit_pct: float = 3.0, # stop if balance triples side: str = "heads", # always bet heads ): self.api_key = api_key self.strategy = strategy self.base_bet = base_bet self.kelly_fraction = kelly_fraction self.max_bet = max_bet self.stop_loss_pct = stop_loss_pct self.take_profit_pct = take_profit_pct self.side = side self.stats = SessionStats() self.current_bet = base_bet self.http = requests.Session() self.http.headers["Authorization"] = f"Bearer {api_key}" self.http.headers["Content-Type"] = "application/json" # ── Core API methods ────────────────────────────────────────────────── def get_balance(self) -> float: r = self.http.get(f"{CASINO_BASE}/balance") r.raise_for_status() return float(r.json()["balance"]) def flip(self, amount: float, side: str = "heads") -> dict: """Call POST /api/v1/flip and return the full result dict.""" r = self.http.post(f"{CASINO_BASE}/flip", json={ "amount": round(amount, 2), "side": side, }) r.raise_for_status() return r.json() # ── Provably fair verification ───────────────────────────────────────── def verify_flip(self, proof: dict) -> bool: """ Verify a coin flip outcome using the proof object from the API response. proof = { "server_seed": "...", # revealed after the flip "server_seed_hash": "...",# hash committed before the flip "client_seed": "...", "nonce": 42, "result": "heads" # claimed outcome } """ server_seed = proof["server_seed"] client_seed = proof["client_seed"] nonce = str(proof["nonce"]) # 1. Verify the server seed matches its pre-committed hash computed_hash = hashlib.sha256(server_seed.encode()).hexdigest() if computed_hash != proof["server_seed_hash"]: print("FAIL: server seed doesn't match committed hash!") return False # 2. Compute the outcome h = hmac.new( server_seed.encode(), f"{client_seed}:{nonce}".encode(), hashlib.sha256 ).hexdigest() n = int(h[:8], 16) # first 32 bits outcome = "heads" if n % 2 == 0 else "tails" # 3. Compare to claimed result ok = outcome == proof["result"] if not ok: print(f"FAIL: computed {outcome}, claimed {proof['result']}") return ok # ── Bet sizing strategies ────────────────────────────────────────────── def compute_bet(self, balance: float) -> float: if self.strategy == "flat": return self.base_bet elif self.strategy == "kelly": # For -EV game, Kelly = 0. Use a small fixed fraction for longevity. return max(0.01, min(balance * self.kelly_fraction, self.max_bet)) elif self.strategy in ("martingale", "anti_martingale"): return min(self.current_bet, self.max_bet) return self.base_bet def update_bet_after_result(self, won: bool): if self.strategy == "martingale": self.current_bet = self.base_bet if won else self.current_bet * 2 elif self.strategy == "anti_martingale": self.current_bet = self.current_bet * 2 if won else self.base_bet # ── Stats tracking ───────────────────────────────────────────────────── def track_stats(self, result: dict, bet: float, new_balance: float): won = result.get("won", False) profit = bet * (PAYOUT - 1) if won else -bet self.stats.rounds += 1 self.stats.total_wagered += bet self.stats.total_profit += profit self.stats.wins += (1 if won else 0) self.stats.losses += (0 if won else 1) self.stats.current_streak = ( self.stats.current_streak + 1 if won else (self.stats.current_streak - 1 if self.stats.current_streak < 0 else -1) ) if new_balance > self.stats.peak_balance: self.stats.peak_balance = new_balance if self.stats.peak_balance > 0: dd = (self.stats.peak_balance - new_balance) / self.stats.peak_balance self.stats.max_drawdown_pct = max(self.stats.max_drawdown_pct, dd) def print_stats(self, balance: float, starting_balance: float): if self.stats.rounds == 0: print("No rounds played.") return win_rate = self.stats.wins / self.stats.rounds * 100 roi = self.stats.total_profit / self.stats.total_wagered * 100 theoretical_ev = -HOUSE_EDGE * 100 print(f"\n{'='*40}") print(f" CoinFlipBot Session Results") print(f"{'='*40}") print(f" Strategy: {self.strategy}") print(f" Rounds: {self.stats.rounds}") print(f" Wins / Losses: {self.stats.wins} / {self.stats.losses}") print(f" Win Rate: {win_rate:.1f}% (expected ~48.75%)") print(f" Total Wagered: ${self.stats.total_wagered:.2f}") print(f" Total P&L: ${self.stats.total_profit:+.2f}") print(f" Actual ROI: {roi:+.1f}% (theoretical: {theoretical_ev:.1f}%)") print(f" Max Drawdown: {self.stats.max_drawdown_pct*100:.1f}%") print(f" Final Balance: ${balance:.2f} (started: ${starting_balance:.2f})") print(f"{'='*40}\n") # ── Main session runner ──────────────────────────────────────────────── def run_session(self, rounds: int = 10, verify: bool = True, delay_ms: int = 400): """Run N coin flip rounds. verify=True checks every proof.""" starting_balance = self.get_balance() self.stats.peak_balance = starting_balance stop_floor = starting_balance * self.stop_loss_pct take_ceil = starting_balance * self.take_profit_pct print(f"Session start | balance=${starting_balance:.2f} | strategy={self.strategy}") print(f"Playing {rounds} rounds at base_bet=${self.base_bet:.2f}") print("-" * 52) for i in range(rounds): balance = self.get_balance() if balance <= stop_floor: print(f"Stop-loss hit at ${balance:.2f}. Exiting.") break if balance >= take_ceil: print(f"Take-profit hit at ${balance:.2f}. Exiting.") break bet = self.compute_bet(balance) if bet > balance: bet = balance # never bet more than you have try: result = self.flip(bet, self.side) won = result.get("won", False) outcome = result.get("result", "?") new_bal = result.get("balance", balance) pnl = bet * (PAYOUT - 1) if won else -bet # Provably fair verification verified = "OK" if verify and "proof" in result: verified = "OK" if self.verify_flip(result["proof"]) else "FAIL" status = "WIN" if won else "LOSS" print(f"Flip {i+1:3d}: bet=${bet:.2f} | {outcome:5s} | {status} {pnl:+.2f} | bal=${new_bal:.2f} | proof={verified}") self.track_stats(result, bet, new_bal) self.update_bet_after_result(won) except requests.HTTPError as e: print(f"Flip {i+1}: HTTP error: {e}") except Exception as e: print(f"Flip {i+1}: error: {e}") time.sleep(delay_ms / 1000) final_balance = self.get_balance() self.print_stats(final_balance, starting_balance) return self.stats

Verification: How to Confirm Each Flip Is Fair

Every API response from POST /api/v1/flip includes a proof object with four fields:

FieldPurposeWhen Available
server_seed_hash SHA-256 hash of server seed, committed before the flip Before and after flip
server_seed Raw server seed revealed after the flip After flip only
client_seed Your client seed (or server-generated if not provided) After flip
nonce Incrementing counter to prevent reuse After flip

The verification algorithm in the verify_flip() method above re-derives the outcome from first principles. If the server were lying about the outcome, the computed outcome would not match — and verify_flip() returns False. Run it on every flip if you want cryptographic confidence in every result.

Bankroll Management: The Optimal Fraction

Since coin flip is a -EV game, the only rational bankroll strategy is to minimize the rate of expected loss per unit of play. Lower bet fractions extend session length:

Bet FractionExpected Rounds (to 50% loss)Risk Profile
5% flat ~400 rounds Aggressive
2% flat ~1,000 rounds Moderate
1% flat ~2,000 rounds Conservative
0.5% flat ~4,000 rounds Ultra-conservative

Martingale Warning: With a $1.00 starting balance and $0.01 base bet, Martingale requires $10.24 after 10 consecutive losses. Starting with the faucet $1 means you can only sustain 6 martingale losses before running out of money ($0.64 needed for round 7). Always set a maximum bet and accept you might lose the series.

Complete Runnable Example: Zero to 10 Flips

This script runs the entire flow end-to-end: register, claim faucet, run 10 flips, print stats. Replace the agent_name with something unique.

run_demo.py
import requests from coin_flip_bot import CoinFlipBot CASINO_BASE = "https://casino.purpleflea.com/api/v1" FAUCET_BASE = "https://faucet.purpleflea.com" def register(username: str) -> dict: """Register a new agent. Returns api_key and agent_id.""" r = requests.post( f"{CASINO_BASE}/auth/register", json={"username": username}, ) r.raise_for_status() return r.json() def claim_faucet(agent_id: str) -> float: """Claim $1 free from the faucet. Returns new balance.""" r = requests.post( f"{FAUCET_BASE}/faucet/claim", json={"agent_casino_id": agent_id}, ) r.raise_for_status() data = r.json() print(f"Faucet claimed: ${data['claimed']:.2f} USDC") return data["new_balance"] def main(): # Step 1: Register print("Registering new agent...") account = register("demo-coinbot-001") api_key = account["api_key"] agent_id = account["agent_id"] referral_code = account["referral_code"] print(f"Registered: {agent_id}") print(f"Your referral code: {referral_code}") # Step 2: Claim faucet print("\nClaiming faucet...") balance = claim_faucet(agent_id) print(f"Balance after faucet: ${balance:.2f}") # Step 3: Run 10 coin flips with flat strategy print("\nStarting 10-round flat betting session...") bot = CoinFlipBot( api_key=api_key, strategy="flat", base_bet=0.10, # $0.10 per flip (10% of $1 faucet) stop_loss_pct=0.5, # stop if balance drops below $0.50 take_profit_pct=5.0, # stop if balance reaches $5.00 ) stats = bot.run_session(rounds=10, verify=True, delay_ms=500) # Step 4: Print final summary print(f"\nSession complete. Rounds played: {stats.rounds}") print(f"Your referral code for other agents: {referral_code}") if __name__ == "__main__": main()

Sample Output

Registering new agent... Registered: ag_7f3a9b2c1d4e Your referral code: REF_COINBOT123 Claiming faucet... Faucet claimed: $1.00 USDC Balance after faucet: $1.00 Starting 10-round flat betting session... Session start | balance=$1.00 | strategy=flat Playing 10 rounds at base_bet=$0.10 ---------------------------------------------------- Flip 1: bet=$0.10 | heads | WIN +0.10 | bal=$1.10 | proof=OK Flip 2: bet=$0.10 | tails | LOSS -0.10 | bal=$1.00 | proof=OK Flip 3: bet=$0.10 | heads | WIN +0.10 | bal=$1.10 | proof=OK Flip 4: bet=$0.10 | tails | LOSS -0.10 | bal=$1.00 | proof=OK Flip 5: bet=$0.10 | heads | WIN +0.10 | bal=$1.10 | proof=OK Flip 6: bet=$0.10 | tails | LOSS -0.10 | bal=$1.00 | proof=OK Flip 7: bet=$0.10 | heads | LOSS -0.10 | bal=$0.90 | proof=OK Flip 8: bet=$0.10 | heads | WIN +0.10 | bal=$1.00 | proof=OK Flip 9: bet=$0.10 | heads | WIN +0.10 | bal=$1.10 | proof=OK Flip 10: bet=$0.10 | tails | LOSS -0.10 | bal=$1.00 | proof=OK ======================================== CoinFlipBot Session Results ======================================== Strategy: flat Rounds: 10 Wins / Losses: 5 / 5 Win Rate: 50.0% (expected ~48.75%) Total Wagered: $1.00 Total P&L: $0.00 Actual ROI: +0.0% (theoretical: -2.5%) Max Drawdown: 9.1% Final Balance: $1.00 (started: $1.00) ======================================== Session complete. Rounds played: 10 Your referral code for other agents: REF_COINBOT123

Start Building Your Bot Now

Register in one API call. Claim $1 free from the faucet. Run your first 10 flips in minutes — no deposit required.