// Requires an authenticated client. Sign each order, then submit the batch.
let signed_a = client.sign(&signer, order_a).await?;
let signed_b = client.sign(&signer, order_b).await?;
let results = client.post_orders(vec![signed_a, signed_b]).await?;
// Vec<PostOrderResponse> — same length and order as the input.
curl --request POST \
--url https://orderbooks.xo.market/orders \
--header 'Content-Type: application/json' \
--data '
[
{
"order": {
"salt": "<string>",
"maker": "<string>",
"signer": "<string>",
"beneficiary": "0x0000000000000000000000000000000000000000",
"tokenId": "<string>",
"makerAmount": "<string>",
"takerAmount": "<string>",
"expiration": "0",
"nonce": "<string>",
"identifier": "0x00000000000000000000000000000000",
"metadata": "0x0000000000000000000000000000000000000000000000000000000000000000",
"signature": "<string>"
},
"postOnly": false
}
]
'import requests
url = "https://orderbooks.xo.market/orders"
payload = [
{
"order": {
"salt": "<string>",
"maker": "<string>",
"signer": "<string>",
"beneficiary": "0x0000000000000000000000000000000000000000",
"tokenId": "<string>",
"makerAmount": "<string>",
"takerAmount": "<string>",
"expiration": "0",
"nonce": "<string>",
"identifier": "0x00000000000000000000000000000000",
"metadata": "0x0000000000000000000000000000000000000000000000000000000000000000",
"signature": "<string>"
},
"postOnly": False
}
]
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([
{
order: {
salt: '<string>',
maker: '<string>',
signer: '<string>',
beneficiary: '0x0000000000000000000000000000000000000000',
tokenId: '<string>',
makerAmount: '<string>',
takerAmount: '<string>',
expiration: '0',
nonce: '<string>',
identifier: '0x00000000000000000000000000000000',
metadata: '0x0000000000000000000000000000000000000000000000000000000000000000',
signature: '<string>'
},
postOnly: false
}
])
};
fetch('https://orderbooks.xo.market/orders', 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://orderbooks.xo.market/orders",
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([
[
'order' => [
'salt' => '<string>',
'maker' => '<string>',
'signer' => '<string>',
'beneficiary' => '0x0000000000000000000000000000000000000000',
'tokenId' => '<string>',
'makerAmount' => '<string>',
'takerAmount' => '<string>',
'expiration' => '0',
'nonce' => '<string>',
'identifier' => '0x00000000000000000000000000000000',
'metadata' => '0x0000000000000000000000000000000000000000000000000000000000000000',
'signature' => '<string>'
],
'postOnly' => false
]
]),
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://orderbooks.xo.market/orders"
payload := strings.NewReader("[\n {\n \"order\": {\n \"salt\": \"<string>\",\n \"maker\": \"<string>\",\n \"signer\": \"<string>\",\n \"beneficiary\": \"0x0000000000000000000000000000000000000000\",\n \"tokenId\": \"<string>\",\n \"makerAmount\": \"<string>\",\n \"takerAmount\": \"<string>\",\n \"expiration\": \"0\",\n \"nonce\": \"<string>\",\n \"identifier\": \"0x00000000000000000000000000000000\",\n \"metadata\": \"0x0000000000000000000000000000000000000000000000000000000000000000\",\n \"signature\": \"<string>\"\n },\n \"postOnly\": false\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://orderbooks.xo.market/orders")
.header("Content-Type", "application/json")
.body("[\n {\n \"order\": {\n \"salt\": \"<string>\",\n \"maker\": \"<string>\",\n \"signer\": \"<string>\",\n \"beneficiary\": \"0x0000000000000000000000000000000000000000\",\n \"tokenId\": \"<string>\",\n \"makerAmount\": \"<string>\",\n \"takerAmount\": \"<string>\",\n \"expiration\": \"0\",\n \"nonce\": \"<string>\",\n \"identifier\": \"0x00000000000000000000000000000000\",\n \"metadata\": \"0x0000000000000000000000000000000000000000000000000000000000000000\",\n \"signature\": \"<string>\"\n },\n \"postOnly\": false\n }\n]")
.asString();require 'uri'
require 'net/http'
url = URI("https://orderbooks.xo.market/orders")
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 {\n \"order\": {\n \"salt\": \"<string>\",\n \"maker\": \"<string>\",\n \"signer\": \"<string>\",\n \"beneficiary\": \"0x0000000000000000000000000000000000000000\",\n \"tokenId\": \"<string>\",\n \"makerAmount\": \"<string>\",\n \"takerAmount\": \"<string>\",\n \"expiration\": \"0\",\n \"nonce\": \"<string>\",\n \"identifier\": \"0x00000000000000000000000000000000\",\n \"metadata\": \"0x0000000000000000000000000000000000000000000000000000000000000000\",\n \"signature\": \"<string>\"\n },\n \"postOnly\": false\n }\n]"
response = http.request(request)
puts response.read_body{
"results": [
{
"order_id": "101",
"fills": 0,
"resting": true,
"remaining_size": "100000000",
"order_hash": "0x0011223344556677889900aabbccddeeff00112233445566778899aabbccddee",
"error": null
},
{
"order_id": "102",
"fills": 1,
"resting": false,
"remaining_size": "0",
"order_hash": "0x1122334455667788990011223344556677889900aabbccddeeff112233445566",
"error": null
},
{
"order_id": null,
"fills": null,
"resting": null,
"remaining_size": null,
"order_hash": null,
"error": "insufficient balance: required 200000000, available 50000000"
}
]
}Post multiple orders
Batch place up to 100 orders. Each entry succeeds or fails independently — the response array is parallel to the request body. The top-level call returns 200 even when every entry rejects.
// Requires an authenticated client. Sign each order, then submit the batch.
let signed_a = client.sign(&signer, order_a).await?;
let signed_b = client.sign(&signer, order_b).await?;
let results = client.post_orders(vec![signed_a, signed_b]).await?;
// Vec<PostOrderResponse> — same length and order as the input.
curl --request POST \
--url https://orderbooks.xo.market/orders \
--header 'Content-Type: application/json' \
--data '
[
{
"order": {
"salt": "<string>",
"maker": "<string>",
"signer": "<string>",
"beneficiary": "0x0000000000000000000000000000000000000000",
"tokenId": "<string>",
"makerAmount": "<string>",
"takerAmount": "<string>",
"expiration": "0",
"nonce": "<string>",
"identifier": "0x00000000000000000000000000000000",
"metadata": "0x0000000000000000000000000000000000000000000000000000000000000000",
"signature": "<string>"
},
"postOnly": false
}
]
'import requests
url = "https://orderbooks.xo.market/orders"
payload = [
{
"order": {
"salt": "<string>",
"maker": "<string>",
"signer": "<string>",
"beneficiary": "0x0000000000000000000000000000000000000000",
"tokenId": "<string>",
"makerAmount": "<string>",
"takerAmount": "<string>",
"expiration": "0",
"nonce": "<string>",
"identifier": "0x00000000000000000000000000000000",
"metadata": "0x0000000000000000000000000000000000000000000000000000000000000000",
"signature": "<string>"
},
"postOnly": False
}
]
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([
{
order: {
salt: '<string>',
maker: '<string>',
signer: '<string>',
beneficiary: '0x0000000000000000000000000000000000000000',
tokenId: '<string>',
makerAmount: '<string>',
takerAmount: '<string>',
expiration: '0',
nonce: '<string>',
identifier: '0x00000000000000000000000000000000',
metadata: '0x0000000000000000000000000000000000000000000000000000000000000000',
signature: '<string>'
},
postOnly: false
}
])
};
fetch('https://orderbooks.xo.market/orders', 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://orderbooks.xo.market/orders",
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([
[
'order' => [
'salt' => '<string>',
'maker' => '<string>',
'signer' => '<string>',
'beneficiary' => '0x0000000000000000000000000000000000000000',
'tokenId' => '<string>',
'makerAmount' => '<string>',
'takerAmount' => '<string>',
'expiration' => '0',
'nonce' => '<string>',
'identifier' => '0x00000000000000000000000000000000',
'metadata' => '0x0000000000000000000000000000000000000000000000000000000000000000',
'signature' => '<string>'
],
'postOnly' => false
]
]),
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://orderbooks.xo.market/orders"
payload := strings.NewReader("[\n {\n \"order\": {\n \"salt\": \"<string>\",\n \"maker\": \"<string>\",\n \"signer\": \"<string>\",\n \"beneficiary\": \"0x0000000000000000000000000000000000000000\",\n \"tokenId\": \"<string>\",\n \"makerAmount\": \"<string>\",\n \"takerAmount\": \"<string>\",\n \"expiration\": \"0\",\n \"nonce\": \"<string>\",\n \"identifier\": \"0x00000000000000000000000000000000\",\n \"metadata\": \"0x0000000000000000000000000000000000000000000000000000000000000000\",\n \"signature\": \"<string>\"\n },\n \"postOnly\": false\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://orderbooks.xo.market/orders")
.header("Content-Type", "application/json")
.body("[\n {\n \"order\": {\n \"salt\": \"<string>\",\n \"maker\": \"<string>\",\n \"signer\": \"<string>\",\n \"beneficiary\": \"0x0000000000000000000000000000000000000000\",\n \"tokenId\": \"<string>\",\n \"makerAmount\": \"<string>\",\n \"takerAmount\": \"<string>\",\n \"expiration\": \"0\",\n \"nonce\": \"<string>\",\n \"identifier\": \"0x00000000000000000000000000000000\",\n \"metadata\": \"0x0000000000000000000000000000000000000000000000000000000000000000\",\n \"signature\": \"<string>\"\n },\n \"postOnly\": false\n }\n]")
.asString();require 'uri'
require 'net/http'
url = URI("https://orderbooks.xo.market/orders")
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 {\n \"order\": {\n \"salt\": \"<string>\",\n \"maker\": \"<string>\",\n \"signer\": \"<string>\",\n \"beneficiary\": \"0x0000000000000000000000000000000000000000\",\n \"tokenId\": \"<string>\",\n \"makerAmount\": \"<string>\",\n \"takerAmount\": \"<string>\",\n \"expiration\": \"0\",\n \"nonce\": \"<string>\",\n \"identifier\": \"0x00000000000000000000000000000000\",\n \"metadata\": \"0x0000000000000000000000000000000000000000000000000000000000000000\",\n \"signature\": \"<string>\"\n },\n \"postOnly\": false\n }\n]"
response = http.request(request)
puts response.read_body{
"results": [
{
"order_id": "101",
"fills": 0,
"resting": true,
"remaining_size": "100000000",
"order_hash": "0x0011223344556677889900aabbccddeeff00112233445566778899aabbccddee",
"error": null
},
{
"order_id": "102",
"fills": 1,
"resting": false,
"remaining_size": "0",
"order_hash": "0x1122334455667788990011223344556677889900aabbccddeeff112233445566",
"error": null
},
{
"order_id": null,
"fills": null,
"resting": null,
"remaining_size": null,
"order_hash": null,
"error": "insufficient balance: required 200000000, available 50000000"
}
]
}Body
100EIP-712 signed order. Wire fields are camelCase. Sign over domain
name="XO Market CLOB", version="1", chainId=<XO chain id>, verifyingContract=<CTF Exchange address>. XO Privy/ZeroDev smart
accounts use signatureType = 3; direct EOA integrations use
signatureType = 0.
Orders do not carry a fee rate. Fetch the market category rate
with GET /fee-rate and see the Fees guide for the conviction curve.
Legacy wire keys taker and feeRateBps are ignored on parse and
must not be used for signing (the typehash changed).
Show child attributes
Show child attributes
GTC- Good-Till-Cancel; rests on the book until filled or cancelled.GTD- Good-Till-Date; requires non-zeroexpirationin the signed order.FOK- Fill-Or-Kill; fills the entire signedtakerAmount(BUY) /makerAmount(SELL) at the signed price or rejects with no fills.FAK- Fill-And-Kill (a.k.a. IOC); fills as much as the book supports at the signed price; cancels any unfilled remainder.
Market-style execution. There is no dedicated MARKET value.
Submit a signed CTFOrder at an aggressive cap price (e.g. 0.99
for BUY, 0.001 for SELL), then choose FAK for immediate
partial fill or FOK for all-or-nothing execution. The matching
logic can also use economically compatible YES/NO liquidity.
GTC, FAK, FOK, GTD Envelope flag — not part of the signed EIP-712 order. When
true, the order must rest without taking any liquidity.
The engine rejects it (HTTP 400) if it would match at
placement via COMPLEMENTARY, MINT, or MERGE.
Requires orderType of GTC or GTD. FAK / FOK with
postOnly: true returns
{"error": "postOnly orders must use orderType GTC or GTD"}.
A crossing GTC/GTD returns
{"error": "post-only order would cross resting liquidity"}.
Omitted or false is a normal order.
Response
OK
Show child attributes
Show child attributes