BettingLab

Build a Claude betting assistant with MoneyLine API

Marcus Hale
Marcus Hale

Building a Claude betting assistant that actually adds value requires more than throwing prompts at Anthropic's API. You need structured tool calls, clean data ingestion, and prompt design that keeps Claude focused on what matters: identifying +EV opportunities and explaining line movement with precision.

I've built dozens of betting tools. Most AI assistants are garbage—generic responses about "responsible gambling" with zero actionable insight. But Claude 3.5 Sonnet, properly constrained with the right tools and data feeds, can synthesize complex betting information faster than any human analyst.

Here's how to build a Claude betting assistant with MoneyLine API that actually improves your betting decisions.

Architecture: Claude + Function Calling + MoneyLine API

The winning combination is Claude 3.5 Sonnet with Anthropic's function calling, connected to MoneyLine's /v1/edge and /v1/odds endpoints. Claude handles the reasoning and synthesis. MoneyLine provides the sharp data and EV calculations.

Core Components

1. MoneyLine API Integration

2. Claude Function Definitions

3. Prompt Engineering

Implementing the Tool Functions

Here's the Python implementation using the Anthropic SDK and requests for MoneyLine API calls:

import anthropic
import requests
import json
from datetime import datetime

class ClaudeBettingAssistant:
    def __init__(self, anthropic_api_key, moneyline_api_key):
        self.anthropic = anthropic.Anthropic(api_key=anthropic_api_key)
        self.ml_headers = {
            'Authorization': f'Bearer {moneyline_api_key}',
            'Content-Type': 'application/json'
        }
        self.base_url = 'https://mlapi.bet'
    
    def get_edge_plays(self, sport='nfl', min_ev=3.0):
        """Fetch current +EV opportunities from MoneyLine API"""
        url = f'{self.base_url}/v1/edge'
        params = {
            'sport': sport,
            'min_ev': min_ev,
            'limit': 10
        }
        
        response = requests.get(url, headers=self.ml_headers, params=params)
        if response.status_code == 200:
            return response.json()['data']
        return []
    
    def analyze_line_movement(self, event_id):
        """Track odds movement for specific game"""
        url = f'{self.base_url}/v1/odds/{event_id}/history'
        
        response = requests.get(url, headers=self.ml_headers)
        if response.status_code == 200:
            return response.json()['data']
        return {}
    
    def get_game_context(self, event_id):
        """Get game context including injuries, weather"""
        url = f'{self.base_url}/v1/events/{event_id}'
        
        response = requests.get(url, headers=self.ml_headers)
        if response.status_code == 200:
            return response.json()['data']
        return {}

    def chat_with_claude(self, user_message, betting_context=None):
        """Main chat interface with Claude"""
        
        system_prompt = """You are a sharp sports betting analyst. Your job is to:

1. Identify +EV betting opportunities using MoneyLine API data
2. Explain line movement and market inefficiencies 
3. Provide clear, actionable betting advice
4. Never recommend bets below 3% expected value
5. Always explain your reasoning with specific numbers

You have access to real-time odds data and EV calculations. Use the tools to fetch current data before making recommendations.

Context about the user:
- Bankroll: $10,000
- Risk tolerance: Moderate (1-2% per play)
- Strategy: Value betting focused on NFL and NBA
- Books: FanDuel, DraftKings, Caesars access"""

        tools = [
            {
                "name": "get_edge_plays",
                "description": "Fetch current +EV betting opportunities",
                "input_schema": {
                    "type": "object",
                    "properties": {
                        "sport": {"type": "string", "enum": ["nfl", "nba", "mlb", "nhl"]},
                        "min_ev": {"type": "number", "minimum": 1.0}
                    },
                    "required": ["sport"]
                }
            },
            {
                "name": "analyze_line_movement", 
                "description": "Analyze odds movement for a specific game",
                "input_schema": {
                    "type": "object",
                    "properties": {
                        "event_id": {"type": "string"}
                    },
                    "required": ["event_id"]
                }
            },
            {
                "name": "get_game_context",
                "description": "Get injury reports and game context",
                "input_schema": {
                    "type": "object", 
                    "properties": {
                        "event_id": {"type": "string"}
                    },
                    "required": ["event_id"]
                }
            }
        ]

        messages = [
            {"role": "user", "content": user_message}
        ]

        response = self.anthropic.messages.create(
            model="claude-3-5-sonnet-20241022",
            max_tokens=1500,
            system=system_prompt,
            messages=messages,
            tools=tools
        )

        # Handle tool calls
        if response.stop_reason == "tool_use":
            return self.handle_tool_calls(response, messages)
        
        return response.content[0].text

    def handle_tool_calls(self, response, messages):
        """Process Claude's tool calls and return final response"""
        
        messages.append({"role": "assistant", "content": response.content})
        
        for content_block in response.content:
            if content_block.type == "tool_use":
                tool_name = content_block.name
                tool_input = content_block.input
                
                # Execute the tool call
                if tool_name == "get_edge_plays":
                    result = self.get_edge_plays(**tool_input)
                elif tool_name == "analyze_line_movement":
                    result = self.analyze_line_movement(**tool_input)  
                elif tool_name == "get_game_context":
                    result = self.get_game_context(**tool_input)
                
                # Add tool result to messages
                messages.append({
                    "role": "user",
                    "content": [
                        {
                            "type": "tool_result",
                            "tool_use_id": content_block.id,
                            "content": json.dumps(result)
                        }
                    ]
                })
        
        # Get Claude's final response with tool results
        final_response = self.anthropic.messages.create(
            model="claude-3-5-sonnet-20241022",
            max_tokens=1500,
            messages=messages,
            tools=[...]  # Same tools as before
        )
        
        return final_response.content[0].text

Prompt Design That Works

Generic AI assistant prompts produce generic responses. Sharp betting assistants require specific constraints and clear success criteria.

The Core System Prompt

You are a sharp sports betting analyst. Your job is to:

1. Identify +EV betting opportunities using MoneyLine API data
2. Explain line movement and market inefficiencies 
3. Provide clear, actionable betting advice
4. Never recommend bets below 3% expected value
5. Always explain your reasoning with specific numbers

You have access to real-time odds data and EV calculations. Use the tools to fetch current data before making recommendations.

User Context Variables

The system prompt includes specific user context:

Response Format Constraints

I constrain Claude's output format to ensure consistent, actionable responses:

Format your recommendations as:
PLAY: [Specific bet]
BOOK: [Where to place it]  
EV: [Expected value %]
REASONING: [Why this line is off]
SIZE: [Recommended bet amount]

Real User Experience

Here's what users actually see when interacting with the Claude betting assistant:

User Input: "What are the best NBA plays tonight? I'm looking for solid value."

Claude Response: "Let me check current +EV opportunities in the NBA..."

[Claude calls get_edge_plays(sport='nba', min_ev=3.0)]

PLAY: Lakers +4.5 vs Warriors
BOOK: FanDuel (-110)
EV: 4.2%
REASONING: FanDuel is 1.5 points off the sharp consensus. LeBron probable return creates value gap as books haven't fully adjusted. Pinnacle has this at +3, suggesting 4.5 is inflated.
SIZE: $150 (1.5% of bankroll)

PLAY: Under 234.5 in Celtics/Heat
BOOK: DraftKings (-105)
EV: 3.8%
REASONING: Weather delay shortened both teams' practice time. Historical data shows 6-point drop in scoring efficiency after schedule disruptions. Market hasn't priced this edge.
SIZE: $120 (1.2% of bankroll)

The key difference: Claude provides specific reasoning with numbers, not generic "both teams are playing well" analysis.

Advanced Features and Extensions

Historical Edge Analysis

Connect Claude to MoneyLine's historical data to identify patterns:

def analyze_betting_patterns(self, team, days_back=30):
    """Analyze team's recent betting patterns"""
    url = f'{self.base_url}/v1/edge/history'
    params = {
        'team': team,
        'days': days_back
    }
    
    response = requests.get(url, headers=self.ml_headers, params=params)
    return response.json()['data']

Claude can then identify: "Warriors are 8-2 ATS as road favorites this season when the spread is 6+ points. Tonight's line at -7.5 fits the pattern for value on GSW."

Multi-Market Arbitrage Detection

Extend the tool set to identify arbitrage opportunities:

def find_arbitrage(self, sport='nfl'):
    """Find arbitrage opportunities across books"""
    url = f'{self.base_url}/v1/arbitrage'
    params = {'sport': sport}
    
    response = requests.get(url, headers=self.ml_headers, params=params)
    return response.json()['data']

Claude can synthesize complex arbitrage setups: "Risk-free profit available on Knicks game. Bet Over 220.5 on FanDuel (-105) and Under 221.5 on Caesars (-110) for guaranteed 1.2% return."

Integration with Bankroll Management

Track bet history and adjust recommendations based on recent performance:

def log_bet_result(self, bet_data, result):
    """Track betting results for bankroll management"""
    # Log to database or file
    self.update_bankroll_strategy(result)

def update_bankroll_strategy(self, recent_results):
    """Adjust bet sizing based on recent performance"""
    # Implement Kelly Criterion adjustments
    pass

Technical Considerations

Rate Limiting and Caching

MoneyLine API has generous rate limits, but implement caching for frequently requested data:

import time
from functools import lru_cache

@lru_cache(maxsize=100)
def cached_odds_call(self, endpoint, cache_seconds=60):
    """Cache API calls for 60 seconds"""
    cache_key = f"{endpoint}_{int(time.time() / cache_seconds)}"
    # Implementation details...

Error Handling

Handle API failures gracefully:

def safe_api_call(self, url, params=None, retries=3):
    """API calls with exponential backoff"""
    for attempt in range(retries):
        try:
            response = requests.get(url, headers=self.ml_headers, params=params)
            if response.status_code == 200:
                return response.json()
        except requests.RequestException:
            if attempt < retries - 1:
                time.sleep(2 ** attempt)  # Exponential backoff
            continue
    
    return {"error": "API unavailable"}

Production Deployment

Deploy using FastAPI for web access or as a Discord bot for team collaboration:

from fastapi import FastAPI
app = FastAPI()

@app.post("/chat")
async def chat_endpoint(message: str):
    assistant = ClaudeBettingAssistant(anthropic_key, moneyline_key)
    response = assistant.chat_with_claude(message)
    return {"response": response}

Frequently Asked Questions

How accurate are Claude's betting predictions compared to traditional models?

Claude doesn't predict outcomes—it synthesizes market inefficiencies using MoneyLine's EV calculations. The MoneyLine API provides the mathematical edge detection; Claude explains why those edges exist and which ones to prioritize. This approach typically outperforms pure prediction models because it focuses on market mistakes rather than forecasting inherently uncertain events.

What's the minimum bankroll needed to make this system profitable?

The betting assistant works with any bankroll size, but profitability depends on bet volume and available edges. With a $1,000 bankroll using 1% bet sizing, you need consistent 3%+ EV opportunities to overcome variance. Smaller bankrolls face higher relative transaction costs (signup bonuses, minimum bets), while larger bankrolls can capitalize on more opportunities across multiple books.

How does Claude handle conflicting information between different sportsbooks?

Claude processes line discrepancies as data points rather than conflicts. When DraftKings shows Lakers -3 and FanDuel shows -5, Claude analyzes which book is historically sharper for NBA games and whether recent news explains the gap. The EV scanner approach treats disagreement between books as the source of profitable opportunities.

Can this system identify arbitrage opportunities automatically?

Yes, by extending the tool functions to include MoneyLine's arbitrage endpoints. Claude can identify risk-free profit opportunities and calculate optimal bet sizing across multiple books. However, arbitrage windows close quickly, so the system works best for users who can place bets immediately when opportunities arise.

What sports and bet types work best with Claude betting analysis?

Claude excels with major sports (NFL, NBA, MLB) where MoneyLine has deep data coverage. Simple bet types (spreads, totals, moneylines) work better than complex props because Claude can access relevant injury reports, weather data, and historical patterns. Niche sports and exotic props have less supporting data for Claude to analyze effectively.

Building a Claude betting assistant isn't about replacing human judgment—it's about augmenting your analysis with faster data synthesis and pattern recognition. When properly connected to sharp data sources like MoneyLine API, Claude becomes a powerful tool for identifying and explaining profitable betting opportunities that manual analysis might miss.

Build with the same data we use.

MoneyLine API powers BettingLab's edge calculations. Free tier, 1k credits/month.