> ## 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.

# Posting Orders

> How to construct, sign, and submit maker orders to the SX Bet orderbook.

## Overview

Posting an order places it on the SX Bet orderbook for takers to fill. This guide covers every field in the order payload, how to sign it, and how to handle the response.

## Order fields

Each order submitted to [`POST /orders/new`](/api-reference/post-new-order) requires these fields:

| Field                      | Type    | Description                                                                                                                                                      |
| -------------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `marketHash`               | string  | The market you're posting to. Get this from [`GET /markets/active`](/api-reference/get-markets-active) or [`GET /markets/find`](/api-reference/get-markets-find) |
| `maker`                    | string  | Your wallet address                                                                                                                                              |
| `baseToken`                | string  | The token this order is denominated in (e.g., USDC). See [References](/api-reference/references) for token addresses                                             |
| `totalBetSize`             | string  | Your maximum risk in base token units (Ethereum format). See [Unit Conversion](/api-reference/unit-conversion)                                                   |
| `percentageOdds`           | string  | The odds **you the maker** receive, in SX protocol format (`implied * 10^20`). Must be on the [odds ladder](/developers/odds-rounding)                           |
| `expiry`                   | number  | Deprecated. Must always be `2209006800`                                                                                                                          |
| `apiExpiry`                | number  | Unix timestamp (seconds) after which this order expires                                                                                                          |
| `executor`                 | string  | The SX Bet exchange address. Get this from [`GET /metadata`](/api-reference/get-metadata)                                                                        |
| `salt`                     | string  | A random number to differentiate otherwise identical orders                                                                                                      |
| `isMakerBettingOutcomeOne` | boolean | `true` if you're betting on outcome one, `false` for outcome two                                                                                                 |
| `signature`                | string  | Your wallet signature over the order hash                                                                                                                        |

### Understanding `percentageOdds`

This is the implied probability **from your perspective as the maker**. The taker gets the complementary odds on the opposite outcome:

```
taker_implied = 1 - (percentageOdds / 10^20)
```

For example, if you post at `percentageOdds = "52500000000000000000"` (52.5% maker implied), the taker sees 47.5% implied odds on the opposite outcome.

See [Odds Formats](/developers/odds-formats) for conversions between implied, American, and decimal odds.

### Understanding `totalBetSize`

This is the maximum amount of tokens **you** would put into the pot if the order is fully filled. It's in Ethereum units — for USDC (6 decimals), `"100000000"` = 100 USDC.

A taker can partially fill your order. The remaining unfilled portion stays on the book.

<Info>The minimum maker order size is **10 USDC**.</Info>

## Example

<CodeGroup>
  ```javascript JavaScript theme={null}
  import "dotenv/config";
  import { Wallet, solidityPackedKeccak256, getBytes, 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);

  // 1. Build the order
  const order = {
    marketHash: "0x8eeace4a9bbf6235bc59695258a419ed3a85a2c8e3b6a58fb71a0d9e6b031c2b",
    maker: wallet.address,
    baseToken: "0x6629Ce1Cf35Cc1329ebB4F63202F3f197b3F050B", // Mainnet USDC — see References for testnet address
    totalBetSize: "100000000", // 100 USDC
    percentageOdds: "52500000000000000000", // 52.5% maker implied
    expiry: 2209006800,
    apiExpiry: Math.floor(Date.now() / 1000) + 3600, // expires in 1 hour
    executor: "0x52adf738AAD93c31f798a30b2C74D658e1E9a562", // Mainnet — use GET /metadata → executorAddress for testnet
    salt: BigInt(hexlify(randomBytes(32))).toString(),
    isMakerBettingOutcomeOne: true,
  };

  // 2. Sign
  const orderHash = getBytes(
    solidityPackedKeccak256(
      [
        "bytes32",  // marketHash
        "address",  // baseToken
        "uint256",  // totalBetSize
        "uint256",  // percentageOdds
        "uint256",  // expiry
        "uint256",  // salt
        "address",  // maker
        "address",  // executor
        "bool",     // isMakerBettingOutcomeOne
      ],
      [
        order.marketHash,
        order.baseToken,
        order.totalBetSize,
        order.percentageOdds,
        order.expiry,
        order.salt,
        order.maker,
        order.executor,
        order.isMakerBettingOutcomeOne,
      ]
    )
  );
  const signature = await wallet.signMessage(orderHash);

  // For browser wallets (e.g. MetaMask), use an injected provider instead:
  // const provider = new BrowserProvider(window.ethereum);
  // const signer = await provider.getSigner();
  // const signature = await signer.signMessage(orderHash);

  // 3. Submit
  const response = await fetch(`${BASE_URL}/orders/new`, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ orders: [{ ...order, signature }] }),
  }).then((r) => r.json());

  console.log(response);
  ```

  ```python Python theme={null}
  import os
  import time
  import secrets
  import requests
  from dotenv import load_dotenv
  from eth_account import Account
  from eth_account.messages import encode_defunct
  from web3 import Web3

  load_dotenv()
  BASE_URL = "https://api.sx.bet"  # Mainnet — use https://api.toronto.sx.bet for testnet
  account = Account.from_key(os.environ["SX_PRIVATE_KEY"])

  # 1. Build the order
  order = {
      "marketHash": "0x8eeace4a9bbf6235bc59695258a419ed3a85a2c8e3b6a58fb71a0d9e6b031c2b",
      "maker": account.address,
      "baseToken": "0x6629Ce1Cf35Cc1329ebB4F63202F3f197b3F050B",  # Mainnet USDC — see References for testnet address
      "totalBetSize": "100000000",  # 100 USDC
      "percentageOdds": "52500000000000000000",  # 52.5% maker implied
      "expiry": 2209006800,
      "apiExpiry": int(time.time()) + 3600,  # expires in 1 hour
      "executor": "0x52adf738AAD93c31f798a30b2C74D658e1E9a562",  # Mainnet — use GET /metadata → executorAddress for testnet
      "salt": str(int.from_bytes(secrets.token_bytes(32), "big")),
      "isMakerBettingOutcomeOne": True,
  }

  # 2. Sign
  order_hash = Web3.solidity_keccak(
      [
          "bytes32",  # marketHash
          "address",  # baseToken
          "uint256",  # totalBetSize
          "uint256",  # percentageOdds
          "uint256",  # expiry
          "uint256",  # salt
          "address",  # maker
          "address",  # executor
          "bool",     # isMakerBettingOutcomeOne
      ],
      [
          order["marketHash"],
          order["baseToken"],
          int(order["totalBetSize"]),
          int(order["percentageOdds"]),
          order["expiry"],
          int(order["salt"]),
          order["maker"],
          order["executor"],
          order["isMakerBettingOutcomeOne"],
      ]
  )
  message = encode_defunct(primitive=order_hash)
  signed = account.sign_message(message)
  signature = "0x" + signed.signature.hex()

  # 3. Submit
  response = requests.post(
      f"{BASE_URL}/orders/new",
      json={"orders": [{**order, "signature": signature}]},
  )

  print(response.json())
  ```
</CodeGroup>

## Response

A successful response looks like this:

```json theme={null}
{
  "status": "success",
  "data": {
    "orders": [
      "0x7a9d420551c4a635849013dd908f7894766e97aee25fe656d0c5ac857e166fac"
    ],
    "statuses": {
      "0x7a9d420551c4a635849013dd908f7894766e97aee25fe656d0c5ac857e166fac": "OK"
    },
    "inserted": 1
  }
}
```

Each order gets a status:

| Status                 | Description                       |
| ---------------------- | --------------------------------- |
| `OK`                   | Order created successfully        |
| `INSUFFICIENT_BALANCE` | Insufficient maker token balance  |
| `INVALID_MARKET`       | Non-unique marketHashes specified |
| `ORDERS_ALREADY_EXIST` | The order already exists          |

## Common issues

### Order rejected — odds not on ladder

Your `percentageOdds` must land on the odds ladder (currently 0.125% intervals). See [Odds Rounding](/developers/odds-rounding) for how to validate and round your odds.

### Order rejected — exposure too high

Your total exposure per market hash (`sum of totalBetSize - fillAmount` across all open orders on that market hash) must stay under your wallet balance for that token. Cancel some orders or add funds.

### Order rejected — betting not enabled

You need to approve the `TokenTransferProxy` contract for each token you trade. The simplest way is to place a test bet through [sx.bet](https://sx.bet) (or [toronto.sx.bet](https://toronto.sx.bet) for testnet). To do it programmatically, use [POST /orders/approve](/api-reference/post-approve).

### `apiExpiry` tips

* Set a reasonable expiry — orders left open indefinitely consume exposure
* For volatile markets, use shorter expiries (minutes) and repost
* For stable pre-game markets, longer expiries (hours) are fine
* The `expiry` field is deprecated and must always be `2209006800`

## Related

<CardGroup cols={2}>
  <Card title="Odds Rounding →" icon="calculator" href="/developers/odds-rounding">
    Validate and round odds to the ladder.
  </Card>

  <Card title="POST /orders/new →" icon="paper-plane" href="/api-reference/post-new-order">
    Full API reference for the endpoint.
  </Card>

  <Card title="Unit Conversion →" icon="arrows-rotate" href="/api-reference/unit-conversion">
    Converting between raw values and human-readable amounts.
  </Card>

  <Card title="Latency & Server Locations →" icon="gauge" href="/developers/latency">
    Expected response times and co-location recommendations.
  </Card>
</CardGroup>
