Arbitrage involves risk - odds change rapidly, no guaranteed profits.

Docs
Error Handling

Error Handling

Handle API errors and edge cases in Python.

Basic Error Handling

import requests
 
def get_arbitrages_safe(api_key, investment=100, min_profit=1.9):
    """Fetch arbitrages with proper error handling."""
    try:
        response = requests.get(
            "https://getarbitragebets.com/api/internal/arbs-full_2",
            headers={"Authorization": f"Bearer {api_key}"},
            params={"investment": investment, "min_profit": min_profit},
            timeout=30
        )
 
        # Check HTTP status
        if response.status_code == 401:
            raise Exception("Invalid API key")
        elif response.status_code == 429:
            raise Exception("Rate limit exceeded - wait and retry")
        elif response.status_code == 402:
            raise Exception("Insufficient credits")
        elif response.status_code != 200:
            raise Exception(f"API error: {response.status_code}")
 
        data = response.json()
 
        # Verify success
        if not data.get('success', False):
            raise Exception(f"API returned error: {data.get('error', 'Unknown')}")
 
        return data
 
    except requests.exceptions.Timeout:
        raise Exception("Request timed out")
    except requests.exceptions.ConnectionError:
        raise Exception("Connection failed")
    except requests.exceptions.JSONDecodeError:
        raise Exception("Invalid JSON response")
 
# Usage
try:
    data = get_arbitrages_safe("your_api_key")
    print(f"Found {data['profitable_count']} opportunities")
except Exception as e:
    print(f"Error: {e}")

HTTP Status Codes

CodeMeaningAction
200SuccessProcess the response
401UnauthorizedCheck your API key
402Payment RequiredAdd more credits
429Rate LimitedWait and retry
500Server ErrorRetry after a moment

Retry Logic

import time
import requests
 
def get_with_retry(api_key, max_retries=3, backoff=2):
    """Fetch with automatic retry on failure."""
    for attempt in range(max_retries):
        try:
            response = requests.get(
                "https://getarbitragebets.com/api/internal/arbs-full_2",
                headers={"Authorization": f"Bearer {api_key}"},
                params={"investment": 100, "min_profit": 1.9},
                timeout=30
            )
 
            if response.status_code == 429:
                wait_time = backoff ** attempt
                print(f"Rate limited, waiting {wait_time}s...")
                time.sleep(wait_time)
                continue
 
            if response.status_code == 200:
                return response.json()
 
            # Other errors - retry
            print(f"Attempt {attempt + 1} failed: {response.status_code}")
            time.sleep(backoff ** attempt)
 
        except requests.exceptions.RequestException as e:
            print(f"Attempt {attempt + 1} error: {e}")
            time.sleep(backoff ** attempt)
 
    raise Exception(f"Failed after {max_retries} attempts")
 
# Usage
data = get_with_retry("your_api_key")

Validate Response Data

def validate_arbitrage(arb):
    """Validate an arbitrage opportunity before acting."""
    ba = arb.get('best_arbitrage', {})
 
    # Check required fields exist
    required = ['net_profit', 'roi_percent', 'bet_amount_1', 'bet_amount_2']
    for field in required:
        if field not in ba:
            return False, f"Missing field: {field}"
 
    # Validate profit is positive
    if ba['net_profit'] <= 0:
        return False, "Non-positive profit"
 
    # Validate bet amounts
    if ba['bet_amount_1'] <= 0 or ba['bet_amount_2'] <= 0:
        return False, "Invalid bet amounts"
 
    # Validate URLs exist
    if not arb.get('url_a') or not arb.get('url_b'):
        return False, "Missing market URLs"
 
    return True, "Valid"
 
# Validate before processing
for arb in data['profitable_arbitrages']:
    is_valid, reason = validate_arbitrage(arb)
    if is_valid:
        print(f"Processing: {arb['kalshi_id']}")
    else:
        print(f"Skipping {arb['kalshi_id']}: {reason}")

Handle Empty Results

def process_results(data):
    """Handle cases with no opportunities."""
    if data['profitable_count'] == 0:
        print("No profitable opportunities found")
        print(f"Markets analyzed: {data['total_markets_analyzed']}")
        print(f"Markets skipped: {data['markets_skipped']}")
 
        if data.get('skip_reasons'):
            print("Skip reasons:")
            for reason, count in data['skip_reasons'].items():
                print(f"  - {reason}: {count}")
 
        return []
 
    return data['profitable_arbitrages']
 
opportunities = process_results(data)

Logging

import logging
from datetime import datetime
 
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler('arb_api.log'),
        logging.StreamHandler()
    ]
)
logger = logging.getLogger(__name__)
 
def fetch_with_logging(api_key):
    """Fetch with comprehensive logging."""
    logger.info("Fetching arbitrage opportunities...")
 
    try:
        response = requests.get(
            "https://getarbitragebets.com/api/internal/arbs-full_2",
            headers={"Authorization": f"Bearer {api_key}"},
            params={"investment": 100, "min_profit": 1.9},
            timeout=30
        )
 
        logger.info(f"Response status: {response.status_code}")
 
        if response.status_code != 200:
            logger.error(f"API error: {response.status_code} - {response.text}")
            return None
 
        data = response.json()
        logger.info(f"Found {data['profitable_count']} opportunities")
        logger.info(f"Analyzed {data['total_markets_analyzed']} markets")
 
        return data
 
    except Exception as e:
        logger.exception(f"Request failed: {e}")
        return None
 
data = fetch_with_logging("your_api_key")