> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sx.bet/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart

> Go from zero to your first bet on SX Bet.

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)

<Info>
  Market data and orderbook reads are public — no authentication needed. You only need an account for posting or filling orders.
</Info>

## Base URL

All API requests go to:

```
https://api.sx.bet
```

## Install dependencies

<CodeGroup>
  ```bash Python theme={null}
  pip install requests eth-account python-dotenv
  ```

  ```bash JavaScript theme={null}
  npm install ethers dotenv
  ```
</CodeGroup>

<Steps>
  <Step title="Create an account">
    Sign up at [sx.bet](https://sx.bet) with email or Google. Complete registration by choosing a username.

    Fetch your private key from the [assets page](https://sx.bet/wallet/assets). You will need this to sign orders through the API.

    Store it securely in a `.env` file:

    ```bash theme={null}
    SX_PRIVATE_KEY="0xyour_private_key_here"
    ```
  </Step>

  <Step title="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.

    <CodeGroup>
      ```bash cURL theme={null}
      curl "https://api.sx.bet/markets/active"
      ```

      ```python Python theme={null}
      import requests

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

      markets = requests.get(
          f"{BASE_URL}/markets/active"
      ).json()["data"]["markets"]

      first = markets[0]
      print("Market hash:", first["marketHash"])
      print("Event:", first["teamOneName"], "vs", first["teamTwoName"])
      print(f"Outcomes: [1 = {first['outcomeOneName']}, 2 = {first['outcomeTwoName']}]")
      print("Start time:", first["gameTime"])
      ```

      ```javascript JavaScript theme={null}
      const BASE_URL = "https://api.sx.bet"; // Mainnet — use https://api.toronto.sx.bet for testnet

      const data = await fetch(`${BASE_URL}/markets/active`).then((r) => r.json());
      const markets = data.data.markets;

      const first = markets[0];
      console.log("Market hash:", first.marketHash);
      console.log("Event:", first.teamOneName, "vs", first.teamTwoName);
      console.log(`Outcomes: [1 = ${first.outcomeOneName}, 2 = ${first.outcomeTwoName}]`);
      console.log("Start time:", first.gameTime);
      ```
    </CodeGroup>
  </Step>

  <Step title="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.

    <CodeGroup>
      ```bash cURL theme={null}
      curl "https://api.sx.bet/orders/odds/best?marketHashes=YOUR_MARKET_HASH&baseToken=0x6629Ce1Cf35Cc1329ebB4F63202F3f197b3F050B"
      ```

      ```python Python theme={null}
      market_hash = "YOUR_MARKET_HASH"  # from step 2

      response = requests.get(
          f"{BASE_URL}/orders/odds/best",
          params={
              "marketHashes": market_hash,
              "baseToken": "0x6629Ce1Cf35Cc1329ebB4F63202F3f197b3F050B",  # Mainnet USDC — see References for testnet address
          }
      )
      odds = response.json()["data"]["bestOdds"][0]

      # Maker odds — the best prices available from makers on each outcome
      # percentageOdds is null if no orders exist on that side
      pct_one = odds["outcomeOne"]["percentageOdds"]
      pct_two = odds["outcomeTwo"]["percentageOdds"]
      outcome_one_maker = int(pct_one) / 10**20 if pct_one is not None else None
      outcome_two_maker = int(pct_two) / 10**20 if pct_two is not None else None
      print(f"Maker odds on outcome 1: {outcome_one_maker:.2%}" if outcome_one_maker is not None else "Maker odds on outcome 1: no orders")
      print(f"Maker odds on outcome 2: {outcome_two_maker:.2%}" if outcome_two_maker is not None else "Maker odds on outcome 2: no orders")
      ```

      ```javascript JavaScript theme={null}
      const BASE_URL = "https://api.sx.bet"; // Mainnet — use https://api.toronto.sx.bet for testnet
      const marketHash = "YOUR_MARKET_HASH"; // from step 2

      const response = await fetch(
        `${BASE_URL}/orders/odds/best?${new URLSearchParams({
          marketHashes: marketHash,
          baseToken: "0x6629Ce1Cf35Cc1329ebB4F63202F3f197b3F050B", // Mainnet USDC — see References for testnet address
        })}`
      ).then((r) => r.json());

      const odds = response.data.bestOdds[0];
      // Maker odds — the best prices available from makers on each outcome
      // percentageOdds is null if no orders exist on that side
      const pctOne = odds.outcomeOne.percentageOdds;
      const pctTwo = odds.outcomeTwo.percentageOdds;
      const outcomeOneMaker = pctOne !== null ? Number(pctOne) / 1e20 : null;
      const outcomeTwoMaker = pctTwo !== null ? Number(pctTwo) / 1e20 : null;
      console.log(outcomeOneMaker !== null ? `Maker odds on outcome 1: ${(outcomeOneMaker * 100).toFixed(2)}%` : "Maker odds on outcome 1: no orders");
      console.log(outcomeTwoMaker !== null ? `Maker odds on outcome 2: ${(outcomeTwoMaker * 100).toFixed(2)}%` : "Maker odds on outcome 2: no orders");
      ```
    </CodeGroup>
  </Step>

  <Step title="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.

    <Warning>
      The `verifyingContract` and `baseToken` values below are hardcoded to mainnet. Using the wrong values will cause signature failures. Fetch `verifyingContract` from [`GET /metadata`](/api-reference/get-metadata) → `EIP712FillHasher`, and get the correct `baseToken` for your network from [References](/api-reference/references). See [Testnet & Mainnet](/developers/testnet-and-mainnet) for the recommended config pattern.
    </Warning>

    <CodeGroup>
      ```python Python theme={null}
      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())
      ```

      ```javascript JavaScript theme={null}
      import "dotenv/config";
      import { Wallet, ZeroAddress, ZeroHash, randomBytes, hexlify } from "ethers";

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

      const wallet = new Wallet(process.env.SX_PRIVATE_KEY);

      const marketHash = "YOUR_MARKET_HASH"; // from step 2
      const baseToken = "0x6629Ce1Cf35Cc1329ebB4F63202F3f197b3F050B"; // Mainnet USDC — see References for testnet address
      const stakeWei = "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
      const desiredOdds = "YOUR_DESIRED_ODDS";

      const oddsSlippage = 0;
      const isTakerBettingOutcomeOne = true; // true = bet outcome 1, false = bet outcome 2
      const fillSalt = BigInt(hexlify(randomBytes(32))).toString();

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

      const 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" },
        ],
      };

      const message = {
        action: "N/A",
        market: marketHash,
        betting: "N/A",
        stake: "N/A",
        worstOdds: "N/A",
        worstReturning: "N/A",
        fills: {
          stakeWei,
          marketHash,
          baseToken,
          desiredOdds,
          oddsSlippage,
          isTakerBettingOutcomeOne,
          fillSalt,
          beneficiary: ZeroAddress,
          beneficiaryType: 0,
          cashOutTarget: ZeroHash,
        },
      };

      const takerSig = await wallet.signTypedData(domain, types, message);

      // --- Submit ---
      const response = await fetch(`${BASE_URL}/orders/fill/v2`, {
        method: "POST",
        body: JSON.stringify({
          market: marketHash,
          baseToken,
          isTakerBettingOutcomeOne,
          stakeWei,
          desiredOdds,
          oddsSlippage,
          taker: wallet.address,
          takerSig,
          fillSalt,
        }),
        headers: { "Content-Type": "application/json" },
      });
      console.log("Fill result:", await response.json());
      ```
    </CodeGroup>
  </Step>
</Steps>

<Check>
  If your fill returns `"status": "success"`, you're live on mainnet. Check your open positions at [sx.bet/my-bets](https://sx.bet/my-bets).
</Check>

<CardGroup cols={2}>
  <Card title="Core Concepts" icon="book" href="/developers/exchange-model">
    Understand how the exchange and orderbook work in depth.
  </Card>

  <Card title="Filling Orders" icon="map" href="/developers/filling-orders">
    Step-by-step guide to signing and submitting fills.
  </Card>
</CardGroup>
