Skip to main content
POST
/
v1
/
pm
/
orders
/
batch
Batch place orders
curl --request POST \
  --url https://relay.bayse.markets/v1/pm/orders/batch \
  --header 'Content-Type: application/json' \
  --data '
{
  "orders": [
    {
      "outcomeId": "<string>",
      "side": "<string>",
      "type": "<string>",
      "amount": 123,
      "currency": "<string>",
      "price": 123,
      "timeInForce": "<string>",
      "postOnly": true,
      "maxSlippage": 123,
      "expiresAt": "<string>",
      "stpMode": "<string>",
      "clientOrderId": "<string>"
    }
  ]
}
'
import requests

url = "https://relay.bayse.markets/v1/pm/orders/batch"

payload = { "orders": [
{
"outcomeId": "<string>",
"side": "<string>",
"type": "<string>",
"amount": 123,
"currency": "<string>",
"price": 123,
"timeInForce": "<string>",
"postOnly": True,
"maxSlippage": 123,
"expiresAt": "<string>",
"stpMode": "<string>",
"clientOrderId": "<string>"
}
] }
headers = {"Content-Type": "application/json"}

response = requests.post(url, json=payload, headers=headers)

print(response.text)
const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
orders: [
{
outcomeId: '<string>',
side: '<string>',
type: '<string>',
amount: 123,
currency: '<string>',
price: 123,
timeInForce: '<string>',
postOnly: true,
maxSlippage: 123,
expiresAt: '<string>',
stpMode: '<string>',
clientOrderId: '<string>'
}
]
})
};

fetch('https://relay.bayse.markets/v1/pm/orders/batch', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));
<?php

$curl = curl_init();

curl_setopt_array($curl, [
CURLOPT_URL => "https://relay.bayse.markets/v1/pm/orders/batch",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'orders' => [
[
'outcomeId' => '<string>',
'side' => '<string>',
'type' => '<string>',
'amount' => 123,
'currency' => '<string>',
'price' => 123,
'timeInForce' => '<string>',
'postOnly' => true,
'maxSlippage' => 123,
'expiresAt' => '<string>',
'stpMode' => '<string>',
'clientOrderId' => '<string>'
]
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
package main

import (
"fmt"
"strings"
"net/http"
"io"
)

func main() {

url := "https://relay.bayse.markets/v1/pm/orders/batch"

payload := strings.NewReader("{\n \"orders\": [\n {\n \"outcomeId\": \"<string>\",\n \"side\": \"<string>\",\n \"type\": \"<string>\",\n \"amount\": 123,\n \"currency\": \"<string>\",\n \"price\": 123,\n \"timeInForce\": \"<string>\",\n \"postOnly\": true,\n \"maxSlippage\": 123,\n \"expiresAt\": \"<string>\",\n \"stpMode\": \"<string>\",\n \"clientOrderId\": \"<string>\"\n }\n ]\n}")

req, _ := http.NewRequest("POST", url, payload)

req.Header.Add("Content-Type", "application/json")

res, _ := http.DefaultClient.Do(req)

defer res.Body.Close()
body, _ := io.ReadAll(res.Body)

fmt.Println(string(body))

}
HttpResponse<String> response = Unirest.post("https://relay.bayse.markets/v1/pm/orders/batch")
.header("Content-Type", "application/json")
.body("{\n \"orders\": [\n {\n \"outcomeId\": \"<string>\",\n \"side\": \"<string>\",\n \"type\": \"<string>\",\n \"amount\": 123,\n \"currency\": \"<string>\",\n \"price\": 123,\n \"timeInForce\": \"<string>\",\n \"postOnly\": true,\n \"maxSlippage\": 123,\n \"expiresAt\": \"<string>\",\n \"stpMode\": \"<string>\",\n \"clientOrderId\": \"<string>\"\n }\n ]\n}")
.asString();
require 'uri'
require 'net/http'

url = URI("https://relay.bayse.markets/v1/pm/orders/batch")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"orders\": [\n {\n \"outcomeId\": \"<string>\",\n \"side\": \"<string>\",\n \"type\": \"<string>\",\n \"amount\": 123,\n \"currency\": \"<string>\",\n \"price\": 123,\n \"timeInForce\": \"<string>\",\n \"postOnly\": true,\n \"maxSlippage\": 123,\n \"expiresAt\": \"<string>\",\n \"stpMode\": \"<string>\",\n \"clientOrderId\": \"<string>\"\n }\n ]\n}"

response = http.request(request)
puts response.read_body
{
  "engine": "CLOB",
  "results": [
    {
      "index": 0,
      "clientOrderId": "mm-001",
      "success": true,
      "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",
        "type": "GTC",
        "status": "open",
        "amount": 100,
        "price": 0.70,
        "size": 100,
        "filledSize": 0,
        "remainingSize": 100,
        "avgFillPrice": 0,
        "fee": 0,
        "postOnly": false,
        "stpMode": "SKIP",
        "quantity": 0,
        "createdAt": "2026-05-04T12:00:00Z",
        "updatedAt": "2026-05-04T12:00:00Z"
      }
    },
    {
      "index": 1,
      "clientOrderId": "mm-002",
      "success": false,
      "error": {
        "code": "INSUFFICIENT_BALANCE",
        "message": "Insufficient USD balance for this order"
      }
    }
  ],
  "summary": { "total": 2, "succeeded": 1, "failed": 1 }
}
{
  "error": "bad_request",
  "message": "invalid request body: orders[] required (1..20 entries with outcomeId, side, type, amount)",
  "statusCode": 400
}
{
  "error": "conflict",
  "message": "A request with this Idempotency-Key is already in flight; retry shortly.",
  "statusCode": 409
}
{
  "error": "unprocessable_entity",
  "message": "Idempotency-Key reused with a different request body",
  "statusCode": 422
}
{
  "message": "Rate limit exceeded for batch payload size. Please reduce the batch or try again later.",
  "retryAfter": 2
}
Submit up to 20 CLOB orders in a single request. Orders may span multiple markets and events — each item carries only outcomeId, and the server resolves the parent market and event. CLOB-only: AMM markets are rejected per-order with UNSUPPORTED_ENGINE. See the Batch orders concept page for limits, semantics, and rate-limit behavior.

Authentication

Write authentication required — X-Public-Key, X-Timestamp, and X-Signature headers. See the Authentication guide.

Headers

Idempotency-Key
string
Optional. 1–255 characters of [A-Za-z0-9_-]. Retries within 24 hours that share the same key, body, and route replay the original response with Idempotent-Replayed: true. A retry with the same key but a different body is rejected with 422. A concurrent retry (sent while the first is still in flight) is rejected with 409 — back off briefly and retry once the first call has finished. Transient responses (5xx, 429, 408) are not cached, so you can recover by retrying.

Request body

orders
array
required
1–20 order items. Each item is processed independently — one bad item does not abort the others.

Example request

PUBLIC_KEY="pk_live_abcdef123456"
SECRET_KEY="sk_live_secret789xyz"
TIMESTAMP=$(date +%s)
METHOD="POST"
URL_PATH="/v1/pm/orders/batch"
BODY='{"orders":[{"outcomeId":"c3d4e5f6-a7b8-9012-cdef-345678901234","side":"BUY","type":"LIMIT","amount":100,"price":0.70,"timeInForce":"GTC","clientOrderId":"mm-001"},{"outcomeId":"d4e5f6a7-b8c9-0123-defa-456789012345","side":"SELL","type":"LIMIT","amount":50,"price":0.32,"timeInForce":"GTC","clientOrderId":"mm-002"}]}'

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 "Idempotency-Key: 9d3f2c0e-7b1a-4e5d-9f80-3a8b1c2d4e5f" \
  -H "Content-Type: application/json" \
  -d "$BODY"
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/orders/batch';
const body = JSON.stringify({
  orders: [
    {
      outcomeId: 'c3d4e5f6-a7b8-9012-cdef-345678901234',
      side: 'BUY',
      type: 'LIMIT',
      amount: 100,
      price: 0.70,
      timeInForce: 'GTC',
      clientOrderId: 'mm-001',
    },
    {
      outcomeId: 'd4e5f6a7-b8c9-0123-defa-456789012345',
      side: 'SELL',
      type: 'LIMIT',
      amount: 50,
      price: 0.32,
      timeInForce: 'GTC',
      clientOrderId: 'mm-002',
    },
  ],
});

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,
    'Idempotency-Key': crypto.randomUUID(),
    'Content-Type': 'application/json',
  },
  body,
});
const result = await response.json();
import hmac, hashlib, base64, json, time, uuid, requests

public_key = 'pk_live_abcdef123456'
secret_key = 'sk_live_secret789xyz'
timestamp = int(time.time())
method = 'POST'
path = '/v1/pm/orders/batch'
body = json.dumps({
    'orders': [
        {
            'outcomeId': 'c3d4e5f6-a7b8-9012-cdef-345678901234',
            'side': 'BUY',
            'type': 'LIMIT',
            'amount': 100,
            'price': 0.70,
            'timeInForce': 'GTC',
            'clientOrderId': 'mm-001',
        },
        {
            'outcomeId': 'd4e5f6a7-b8c9-0123-defa-456789012345',
            'side': 'SELL',
            'type': 'LIMIT',
            'amount': 50,
            'price': 0.32,
            'timeInForce': 'GTC',
            'clientOrderId': 'mm-002',
        },
    ],
})

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,
        'Idempotency-Key': str(uuid.uuid4()),
        'Content-Type': 'application/json',
    },
    data=body,
)
result = resp.json()
import (
    "crypto/hmac"
    "crypto/sha256"
    "encoding/base64"
    "encoding/hex"
    "fmt"
    "strconv"
    "strings"
    "time"
)

timestamp := time.Now().Unix()
method := "POST"
urlPath := "/v1/pm/orders/batch"
body := []byte(`{"orders":[{"outcomeId":"c3d4e5f6-a7b8-9012-cdef-345678901234","side":"BUY","type":"LIMIT","amount":100,"price":0.70,"timeInForce":"GTC","clientOrderId":"mm-001"},{"outcomeId":"d4e5f6a7-b8c9-0123-defa-456789012345","side":"SELL","type":"LIMIT","amount":50,"price":0.32,"timeInForce":"GTC","clientOrderId":"mm-002"}]}`)

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("Idempotency-Key", "9d3f2c0e-7b1a-4e5d-9f80-3a8b1c2d4e5f")
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)

Response

engine
string
Always CLOB for batch endpoints today.
results
array
Per-order outcomes, in the same order as the request.
summary
object
{
  "engine": "CLOB",
  "results": [
    {
      "index": 0,
      "clientOrderId": "mm-001",
      "success": true,
      "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",
        "type": "GTC",
        "status": "open",
        "amount": 100,
        "price": 0.70,
        "size": 100,
        "filledSize": 0,
        "remainingSize": 100,
        "avgFillPrice": 0,
        "fee": 0,
        "postOnly": false,
        "stpMode": "SKIP",
        "quantity": 0,
        "createdAt": "2026-05-04T12:00:00Z",
        "updatedAt": "2026-05-04T12:00:00Z"
      }
    },
    {
      "index": 1,
      "clientOrderId": "mm-002",
      "success": false,
      "error": {
        "code": "INSUFFICIENT_BALANCE",
        "message": "Insufficient USD balance for this order"
      }
    }
  ],
  "summary": { "total": 2, "succeeded": 1, "failed": 1 }
}
{
  "error": "bad_request",
  "message": "invalid request body: orders[] required (1..20 entries with outcomeId, side, type, amount)",
  "statusCode": 400
}
{
  "error": "conflict",
  "message": "A request with this Idempotency-Key is already in flight; retry shortly.",
  "statusCode": 409
}
{
  "error": "unprocessable_entity",
  "message": "Idempotency-Key reused with a different request body",
  "statusCode": 422
}
{
  "message": "Rate limit exceeded for batch payload size. Please reduce the batch or try again later.",
  "retryAfter": 2
}
Batch calls are charged per item against your write rate-limit bucket — a 20-order batch costs 20 tokens. Over-budget batches are rejected with 429 before any orders reach the matching engine. See Rate limits.