Skip to main content
This quickstart walks you through the essentials of programmatic betting on SX Bet. By the end, you’ll have fetched live markets, read current odds, and filled a real order.

What you’ll need

  • An account on SX Bet (for signing orders)
  • USDC (to fill an order)
Market data and orderbook reads are public — no authentication needed. You only need an account for posting or filling orders.

Base URL

All API requests go to:
https://api.sx.bet

Install dependencies

pip install requests eth-account python-dotenv
1

Create an account

Sign up at sx.bet with email or Google. Complete registration by choosing a username.Fetch your private key from the assets page. You will need this to sign orders through the API.Store it securely in a .env file:
SX_PRIVATE_KEY="0xyour_private_key_here"
2

Fetch a market

Fetch active markets to find one you want to bet on. Copy the marketHash — you’ll need it in the next steps.
curl "https://api.sx.bet/markets/active"
3

Fetch current odds

Get the best available odds for your market (from the maker’s perspective) using the marketHash from the previous step. You’ll use these to derive your taker odds in the next step.
curl "https://api.sx.bet/orders/odds/best?marketHashes=YOUR_MARKET_HASH&baseToken=0x6629Ce1Cf35Cc1329ebB4F63202F3f197b3F050B"
4

Place a bet

Submit a fill against the market from step 2. desiredOdds is from the taker’s perspective — the inverse of the maker’s best odds on the opposite outcome from step 3.
The verifyingContract and baseToken values below are hardcoded to mainnet. Using the wrong values will cause signature failures. Fetch verifyingContract from GET /metadataEIP712FillHasher, and get the correct baseToken for your network from References. See Testnet & Mainnet for the recommended config pattern.
import os
import secrets
import requests
from eth_account import Account

BASE_URL = "https://api.sx.bet"  # Mainnet — use https://api.toronto.sx.bet for testnet

account = Account.from_key(os.environ["SX_PRIVATE_KEY"])

market_hash = "YOUR_MARKET_HASH"  # from step 2
base_token = "0x6629Ce1Cf35Cc1329ebB4F63202F3f197b3F050B"  # Mainnet USDC — see References for testnet address
stake_wei = "50000000"  # 50 USDC (6 decimals)

# Desired odds (taker's perspective)
# To get best available taker odds: 10^20 - opposite outcome's maker odds from step 3
desired_odds = "YOUR_DESIRED_ODDS"

is_taker_betting_outcome_one = True  # True = bet outcome 1, False = bet outcome 2
fill_salt = int.from_bytes(secrets.token_bytes(32), "big")

# --- Sign the fill ---
DOMAIN = {
    "name": "SX Bet",
    "version": "6.0",
    "chainId": 4162,  # Mainnet — use 79479957 for testnet
    "verifyingContract": "0x845a2Da2D70fEDe8474b1C8518200798c60aC364",  # Mainnet — use GET /metadata → EIP712FillHasher for testnet
}

FILL_TYPES = {
    "Details": [
        {"name": "action", "type": "string"},
        {"name": "market", "type": "string"},
        {"name": "betting", "type": "string"},
        {"name": "stake", "type": "string"},
        {"name": "worstOdds", "type": "string"},
        {"name": "worstReturning", "type": "string"},
        {"name": "fills", "type": "FillObject"},
    ],
    "FillObject": [
        {"name": "stakeWei", "type": "string"},
        {"name": "marketHash", "type": "string"},
        {"name": "baseToken", "type": "string"},
        {"name": "desiredOdds", "type": "string"},
        {"name": "oddsSlippage", "type": "uint256"},
        {"name": "isTakerBettingOutcomeOne", "type": "bool"},
        {"name": "fillSalt", "type": "uint256"},
        {"name": "beneficiary", "type": "address"},
        {"name": "beneficiaryType", "type": "uint8"},
        {"name": "cashOutTarget", "type": "bytes32"},
    ],
}

signed = Account.sign_typed_data(
    account.key,
    domain_data=DOMAIN,
    message_types=FILL_TYPES,
    message_data={
        "action": "N/A",
        "market": market_hash,
        "betting": "N/A",
        "stake": "N/A",
        "worstOdds": "N/A",
        "worstReturning": "N/A",
        "fills": {
            "stakeWei": stake_wei,
            "marketHash": market_hash,
            "baseToken": base_token,
            "desiredOdds": desired_odds,
            "oddsSlippage": 0,
            "isTakerBettingOutcomeOne": is_taker_betting_outcome_one,
            "fillSalt": fill_salt,
            "beneficiary": "0x0000000000000000000000000000000000000000",
            "beneficiaryType": 0,
            "cashOutTarget": b"\x00" * 32,
        },
    },
)
taker_sig = "0x" + signed.signature.hex()

# --- Submit ---
response = requests.post(f"{BASE_URL}/orders/fill/v2", json={
    "market": market_hash,
    "baseToken": base_token,
    "isTakerBettingOutcomeOne": is_taker_betting_outcome_one,
    "stakeWei": stake_wei,
    "desiredOdds": desired_odds,
    "oddsSlippage": 0,
    "taker": account.address,
    "takerSig": taker_sig,
    "fillSalt": str(fill_salt),
})
print("Fill result:", response.json())
If your fill returns "status": "success", you’re live on mainnet. Check your open positions at sx.bet/my-bets.

Core Concepts

Understand how the exchange and orderbook work in depth.

Filling Orders

Step-by-step guide to signing and submitting fills.