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

# Place order

> Place a buy or sell order on a prediction market

## Authentication

Write authentication required — `X-Public-Key`, `X-Timestamp`, and `X-Signature` headers. See the [Authentication guide](/authentication).

## Path parameters

<ParamField path="eventId" type="string" required>
  UUID of the event.
</ParamField>

<ParamField path="marketId" type="string" required>
  UUID of the market.
</ParamField>

## Request body

<ParamField body="side" type="string" required>
  `BUY` or `SELL`.
</ParamField>

<ParamField body="outcomeId" type="string" required>
  UUID of the outcome. Use the [Get Event](/api-reference/pm/get-event) endpoint to find outcome IDs.
</ParamField>

<ParamField body="amount" type="number" required>
  Amount to spend (buy) or receive (sell), in the specified currency. Minimum: \$1.00 USD / ₦100.00 NGN.
</ParamField>

<ParamField body="type" type="string" required>
  `LIMIT` or `MARKET`.
</ParamField>

<ParamField body="currency" type="string">
  `USD` (default) or `NGN`.
</ParamField>

<ParamField body="price" type="number">
  Limit price per share (0.01–0.99). Required for `LIMIT` orders.
</ParamField>

<ParamField body="timeInForce" type="string">
  `GTC` (good-til-cancelled, default for limit), `GTD` (good-til-date), `FAK` (fill-and-kill, default for market), or `FOK` (fill-or-kill).
</ParamField>

<ParamField body="postOnly" type="boolean">
  If `true`, the order is rejected instead of crossing the spread. Limit orders only. Default: `false`.
</ParamField>

<ParamField body="stpMode" type="string">
  Self-trade prevention mode. Controls how the engine resolves a match against another resting order from the same user. CLOB only. Default: `SKIP`. Unknown values fall back to `SKIP`.

  * `SKIP` — the match is silently skipped and both orders remain on the book.
  * `CANCEL_OLDEST` — the resting same-user maker is cancelled and refunded; the taker continues matching against other counterparties.
  * `CANCEL_NEWEST` — the incoming taker stops at the same-user match. If it had already filled against other users, those fills stand and the taker comes back as `cancelled`; otherwise it is `rejected`.
  * `CANCEL_BOTH` — the resting maker is cancelled and the taker is cancelled or rejected under the same rule as `CANCEL_NEWEST`.
</ParamField>

<ParamField body="maxSlippage" type="number">
  Maximum acceptable slippage for market orders (0.00–1.00).
</ParamField>

<ParamField body="expiresAt" type="string">
  ISO 8601 expiration timestamp. Required for `GTD` orders.
</ParamField>

## Example request

<CodeGroup>
  ```bash cURL (market order) theme={null}
  PUBLIC_KEY="pk_live_abcdef123456"
  SECRET_KEY="sk_live_secret789xyz"
  TIMESTAMP=$(date +%s)
  METHOD="POST"
  URL_PATH="/v1/pm/events/a1b2c3d4-e5f6-7890-abcd-ef1234567890/markets/b2c3d4e5-f6a7-8901-bcde-f12345678901/orders"
  BODY='{"side":"BUY","outcomeId":"c3d4e5f6-a7b8-9012-cdef-345678901234","amount":100,"type":"MARKET","currency":"USD"}'

  BODY_HASH=$(printf '%s' "$BODY" | openssl dgst -sha256 -hex 2>/dev/null | sed 's/.*= //')
  PAYLOAD="${TIMESTAMP}.${METHOD}.${URL_PATH}.${BODY_HASH}"
  SIGNATURE=$(printf '%s' "$PAYLOAD" | openssl dgst -sha256 -hmac "$SECRET_KEY" -binary | base64)

  curl -X POST "https://relay.bayse.markets${URL_PATH}" \
    -H "X-Public-Key: ${PUBLIC_KEY}" \
    -H "X-Timestamp: ${TIMESTAMP}" \
    -H "X-Signature: ${SIGNATURE}" \
    -H "Content-Type: application/json" \
    -d "$BODY"
  ```

  ```bash cURL (limit order) theme={null}
  PUBLIC_KEY="pk_live_abcdef123456"
  SECRET_KEY="sk_live_secret789xyz"
  TIMESTAMP=$(date +%s)
  METHOD="POST"
  URL_PATH="/v1/pm/events/a1b2c3d4-e5f6-7890-abcd-ef1234567890/markets/b2c3d4e5-f6a7-8901-bcde-f12345678901/orders"
  BODY='{"side":"BUY","outcomeId":"c3d4e5f6-a7b8-9012-cdef-345678901234","amount":100,"type":"LIMIT","price":0.70,"currency":"USD"}'

  BODY_HASH=$(printf '%s' "$BODY" | openssl dgst -sha256 -hex 2>/dev/null | sed 's/.*= //')
  PAYLOAD="${TIMESTAMP}.${METHOD}.${URL_PATH}.${BODY_HASH}"
  SIGNATURE=$(printf '%s' "$PAYLOAD" | openssl dgst -sha256 -hmac "$SECRET_KEY" -binary | base64)

  curl -X POST "https://relay.bayse.markets${URL_PATH}" \
    -H "X-Public-Key: ${PUBLIC_KEY}" \
    -H "X-Timestamp: ${TIMESTAMP}" \
    -H "X-Signature: ${SIGNATURE}" \
    -H "Content-Type: application/json" \
    -d "$BODY"
  ```

  ```javascript Node.js theme={null}
  import crypto from 'crypto';

  const publicKey = 'pk_live_abcdef123456';
  const secretKey = 'sk_live_secret789xyz';
  const timestamp = Math.floor(Date.now() / 1000);
  const method = 'POST';
  const path = '/v1/pm/events/a1b2c3d4-e5f6-7890-abcd-ef1234567890/markets/b2c3d4e5-f6a7-8901-bcde-f12345678901/orders';
  const body = JSON.stringify({
    side: 'BUY',
    outcomeId: 'c3d4e5f6-a7b8-9012-cdef-345678901234',
    amount: 100,
    type: 'LIMIT',
    price: 0.70,
    currency: 'USD',
  });

  const bodyHash = crypto.createHash('sha256').update(body).digest('hex');
  const payload = `${timestamp}.${method}.${path}.${bodyHash}`;
  const signature = crypto
    .createHmac('sha256', secretKey)
    .update(payload)
    .digest('base64');

  const response = await fetch(`https://relay.bayse.markets${path}`, {
    method,
    headers: {
      'X-Public-Key': publicKey,
      'X-Timestamp': timestamp.toString(),
      'X-Signature': signature,
      'Content-Type': 'application/json',
    },
    body,
  });
  const order = await response.json();
  ```

  ```python Python theme={null}
  import hmac, hashlib, base64, json, time, requests

  public_key = 'pk_live_abcdef123456'
  secret_key = 'sk_live_secret789xyz'
  timestamp = int(time.time())
  method = 'POST'
  path = '/v1/pm/events/a1b2c3d4-e5f6-7890-abcd-ef1234567890/markets/b2c3d4e5-f6a7-8901-bcde-f12345678901/orders'
  body = json.dumps({
      'side': 'BUY',
      'outcomeId': 'c3d4e5f6-a7b8-9012-cdef-345678901234',
      'amount': 100,
      'type': 'LIMIT',
      'price': 0.70,
      'currency': 'USD',
  })

  body_hash = hashlib.sha256(body.encode()).hexdigest()
  payload = f'{timestamp}.{method}.{path}.{body_hash}'
  signature = base64.b64encode(
      hmac.new(secret_key.encode(), payload.encode(), hashlib.sha256).digest()
  ).decode()

  resp = requests.post(
      f'https://relay.bayse.markets{path}',
      headers={
          'X-Public-Key': public_key,
          'X-Timestamp': str(timestamp),
          'X-Signature': signature,
          'Content-Type': 'application/json',
      },
      data=body,
  )
  order = resp.json()
  ```

  ```go Go theme={null}
  import (
      "crypto/hmac"
      "crypto/sha256"
      "encoding/base64"
      "encoding/hex"
      "fmt"
      "strconv"
      "strings"
      "time"
  )

  timestamp := time.Now().Unix()
  method := "POST"
  urlPath := "/v1/pm/events/a1b2c3d4-e5f6-7890-abcd-ef1234567890/markets/b2c3d4e5-f6a7-8901-bcde-f12345678901/orders"
  body := []byte(`{"side":"BUY","outcomeId":"c3d4e5f6-a7b8-9012-cdef-345678901234","amount":100,"type":"LIMIT","price":0.70,"currency":"USD"}`)

  bodySum := sha256.Sum256(body)
  bodyHash := hex.EncodeToString(bodySum[:])
  payload := fmt.Sprintf("%d.%s.%s.%s", timestamp, method, urlPath, bodyHash)
  mac := hmac.New(sha256.New, []byte("sk_live_secret789xyz"))
  mac.Write([]byte(payload))
  signature := base64.StdEncoding.EncodeToString(mac.Sum(nil))

  req, _ := http.NewRequest("POST", "https://relay.bayse.markets"+urlPath, strings.NewReader(string(body)))
  req.Header.Set("X-Public-Key", "pk_live_abcdef123456")
  req.Header.Set("X-Timestamp", strconv.FormatInt(timestamp, 10))
  req.Header.Set("X-Signature", signature)
  req.Header.Set("Content-Type", "application/json")
  resp, _ := http.DefaultClient.Do(req)
  ```
</CodeGroup>

## Response

The response contains an `engine` field indicating the market type, and an `order` object with the order details.

<ResponseField name="engine" type="string">
  `AMM` or `CLOB`.
</ResponseField>

<ResponseField name="order" type="object">
  The placed order. Fields vary by engine type.

  <Expandable title="AMM order fields">
    <ResponseField name="id" type="string">Order UUID.</ResponseField>
    <ResponseField name="outcome" type="string">`YES` or `NO`.</ResponseField>
    <ResponseField name="side" type="string">`BUY` or `SELL`.</ResponseField>
    <ResponseField name="type" type="string">Order type.</ResponseField>
    <ResponseField name="status" type="string">Order status.</ResponseField>
    <ResponseField name="amount" type="number">Amount spent.</ResponseField>
    <ResponseField name="price" type="number">Average fill price.</ResponseField>
    <ResponseField name="quantity" type="number">Shares received.</ResponseField>
    <ResponseField name="currency" type="string">Currency used.</ResponseField>
    <ResponseField name="createdAt" type="string">ISO 8601 timestamp.</ResponseField>
    <ResponseField name="updatedAt" type="string">ISO 8601 timestamp.</ResponseField>
  </Expandable>

  <Expandable title="CLOB order fields">
    <ResponseField name="id" type="string">Order UUID.</ResponseField>
    <ResponseField name="marketId" type="string">Market UUID.</ResponseField>
    <ResponseField name="userId" type="string">User UUID.</ResponseField>
    <ResponseField name="outcome" type="string">`YES` or `NO`.</ResponseField>
    <ResponseField name="side" type="string">`BUY` or `SELL`.</ResponseField>
    <ResponseField name="orderType" type="string">`LIMIT` or `MARKET`.</ResponseField>
    <ResponseField name="type" type="string">Order type.</ResponseField>
    <ResponseField name="status" type="string">Order status: `pending`, `open`, `partial_filled`, `filled`, `cancelled`, `rejected`, or `expired`.</ResponseField>
    <ResponseField name="amount" type="number">Requested amount.</ResponseField>
    <ResponseField name="price" type="number">Limit price.</ResponseField>
    <ResponseField name="size" type="number">Total size.</ResponseField>
    <ResponseField name="filledSize" type="number">Amount filled so far.</ResponseField>
    <ResponseField name="remainingSize" type="number">Amount remaining on the book.</ResponseField>
    <ResponseField name="avgFillPrice" type="number">Average price of fills so far.</ResponseField>
    <ResponseField name="fee" type="number">Fee charged.</ResponseField>
    <ResponseField name="postOnly" type="boolean">Whether the order is post-only.</ResponseField>
    <ResponseField name="stpMode" type="string">Self-trade prevention mode applied: `SKIP`, `CANCEL_OLDEST`, `CANCEL_NEWEST`, or `CANCEL_BOTH`.</ResponseField>
    <ResponseField name="quantity" type="number">Shares received.</ResponseField>
    <ResponseField name="createdAt" type="string">ISO 8601 timestamp.</ResponseField>
    <ResponseField name="updatedAt" type="string">ISO 8601 timestamp.</ResponseField>
  </Expandable>
</ResponseField>

<ResponseExample>
  ```json 200 OK — AMM theme={null}
  {
    "engine": "AMM",
    "order": {
      "id": "e5f6a7b8-c9d0-1234-efab-567890123456",
      "outcome": "YES",
      "side": "BUY",
      "type": "MARKET",
      "status": "filled",
      "amount": 100,
      "price": 0.7235,
      "quantity": 138.21,
      "currency": "USD",
      "createdAt": "2026-02-17T12:00:00Z",
      "updatedAt": "2026-02-17T12:00:00Z"
    }
  }
  ```

  ```json 200 OK — CLOB theme={null}
  {
    "engine": "CLOB",
    "order": {
      "id": "f6a7b8c9-d0e1-2345-fabc-678901234567",
      "marketId": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
      "userId": "9a8b7c6d-5e4f-3210-abcd-ef1234567890",
      "outcome": "YES",
      "side": "BUY",
      "orderType": "LIMIT",
      "stpMode": "SKIP",
      "type": "GTC",
      "status": "open",
      "amount": 100,
      "price": 0.70,
      "size": 100,
      "filledSize": 0,
      "remainingSize": 100,
      "avgFillPrice": 0,
      "fee": 0,
      "postOnly": false,
      "quantity": 0,
      "createdAt": "2026-02-17T12:00:00Z",
      "updatedAt": "2026-02-17T12:00:00Z"
    }
  }
  ```
</ResponseExample>

## Replacing market-maker quotes with `stpMode`

A market maker re-quoting on both sides of a CLOB book risks crossing its own resting orders mid-update. Setting `stpMode` to `CANCEL_OLDEST` cancels the stale same-user maker server-side as the new quote arrives, so the new order can continue matching against external counterparties without sitting next to a duplicate of itself.

```bash cURL theme={null}
BODY='{"side":"BUY","outcomeId":"c3d4e5f6-a7b8-9012-cdef-345678901234","amount":100,"type":"LIMIT","price":0.71,"timeInForce":"GTC","stpMode":"CANCEL_OLDEST","currency":"USD"}'

curl -X POST "https://relay.bayse.markets/v1/pm/events/${EVENT_ID}/markets/${MARKET_ID}/orders" \
  -H "X-Public-Key: ${PUBLIC_KEY}" \
  -H "X-Timestamp: ${TIMESTAMP}" \
  -H "X-Signature: ${SIGNATURE}" \
  -H "Content-Type: application/json" \
  -d "$BODY"
```
