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:
- Total wagered: $10.00
- Expected return: $9.75
- Expected loss: $0.25 (2.5% of $10)
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 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 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
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:
| Field | Purpose | When 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 Fraction | Expected 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.
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.