use alloy::signers::local::LocalSigner;
use rust_decimal_macros::dec;
use xo_orderbook_client::orderbook::{Client, Config};
use xo_orderbook_client::orderbook::types::{OrderType, Side};
use xo_orderbook_client::types::{Decimal, U256};
// 1. Authenticate (mints/derives the L2 HMAC creds).
let signer = LocalSigner::from_bytes(&std::env::var("XO_PRIVATE_KEY")?.parse()?)?;
let client = Client::new("https://orderbooks.xo.market", Config::default())?
.authentication_builder(signer.clone())
.authenticate()
.await?;
let token_id = U256::from_str_radix(
"26516164265702901957933644848127860370782874751279270726689263951695181556943",
10,
)?;
// 2. Build a GTC limit BUY at 0.55 for 100 shares.
let order = client
.limit_order()
.token_id(token_id)
.order_type(OrderType::GTC)
.price(dec!(0.55))
.size(Decimal::ONE_HUNDRED)
.side(Side::Buy)
.build()
.await?;
// 3. Sign + submit.
let signed = client.sign(&signer, order).await?;
let resp = client.post_order(signed).await?;
println!("order id: {}, status: {}", resp.order_id, resp.status);curl --request POST \
--url https://orderbooks.xo.market/order \
--header 'Content-Type: application/json' \
--data '
{
"orderType": "GTC",
"order": {
"salt": "12345678901234567890",
"maker": "0xCAFE000000000000000000000000000000000A11",
"signer": "0xCAFE000000000000000000000000000000000A11",
"beneficiary": "0x0000000000000000000000000000000000000000",
"tokenId": "26516164265702901957933644848127860370782874751279270726689263951695181556943",
"makerAmount": "55000000",
"takerAmount": "100000000",
"expiration": "0",
"nonce": "0",
"identifier": "0x00000000000000000000000000000000",
"metadata": "0x0000000000000000000000000000000000000000000000000000000000000000",
"side": 0,
"signatureType": 3,
"signature": "0xa1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f901b"
}
}
'import requests
url = "https://orderbooks.xo.market/order"
payload = {
"orderType": "GTC",
"order": {
"salt": "12345678901234567890",
"maker": "0xCAFE000000000000000000000000000000000A11",
"signer": "0xCAFE000000000000000000000000000000000A11",
"beneficiary": "0x0000000000000000000000000000000000000000",
"tokenId": "26516164265702901957933644848127860370782874751279270726689263951695181556943",
"makerAmount": "55000000",
"takerAmount": "100000000",
"expiration": "0",
"nonce": "0",
"identifier": "0x00000000000000000000000000000000",
"metadata": "0x0000000000000000000000000000000000000000000000000000000000000000",
"side": 0,
"signatureType": 3,
"signature": "0xa1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f901b"
}
}
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({
orderType: 'GTC',
order: {
salt: '12345678901234567890',
maker: '0xCAFE000000000000000000000000000000000A11',
signer: '0xCAFE000000000000000000000000000000000A11',
beneficiary: '0x0000000000000000000000000000000000000000',
tokenId: '26516164265702901957933644848127860370782874751279270726689263951695181556943',
makerAmount: '55000000',
takerAmount: '100000000',
expiration: '0',
nonce: '0',
identifier: '0x00000000000000000000000000000000',
metadata: '0x0000000000000000000000000000000000000000000000000000000000000000',
side: 0,
signatureType: 3,
signature: '0xa1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f901b'
}
})
};
fetch('https://orderbooks.xo.market/order', 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/order",
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([
'orderType' => 'GTC',
'order' => [
'salt' => '12345678901234567890',
'maker' => '0xCAFE000000000000000000000000000000000A11',
'signer' => '0xCAFE000000000000000000000000000000000A11',
'beneficiary' => '0x0000000000000000000000000000000000000000',
'tokenId' => '26516164265702901957933644848127860370782874751279270726689263951695181556943',
'makerAmount' => '55000000',
'takerAmount' => '100000000',
'expiration' => '0',
'nonce' => '0',
'identifier' => '0x00000000000000000000000000000000',
'metadata' => '0x0000000000000000000000000000000000000000000000000000000000000000',
'side' => 0,
'signatureType' => 3,
'signature' => '0xa1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f901b'
]
]),
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/order"
payload := strings.NewReader("{\n \"orderType\": \"GTC\",\n \"order\": {\n \"salt\": \"12345678901234567890\",\n \"maker\": \"0xCAFE000000000000000000000000000000000A11\",\n \"signer\": \"0xCAFE000000000000000000000000000000000A11\",\n \"beneficiary\": \"0x0000000000000000000000000000000000000000\",\n \"tokenId\": \"26516164265702901957933644848127860370782874751279270726689263951695181556943\",\n \"makerAmount\": \"55000000\",\n \"takerAmount\": \"100000000\",\n \"expiration\": \"0\",\n \"nonce\": \"0\",\n \"identifier\": \"0x00000000000000000000000000000000\",\n \"metadata\": \"0x0000000000000000000000000000000000000000000000000000000000000000\",\n \"side\": 0,\n \"signatureType\": 3,\n \"signature\": \"0xa1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f901b\"\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/order")
.header("Content-Type", "application/json")
.body("{\n \"orderType\": \"GTC\",\n \"order\": {\n \"salt\": \"12345678901234567890\",\n \"maker\": \"0xCAFE000000000000000000000000000000000A11\",\n \"signer\": \"0xCAFE000000000000000000000000000000000A11\",\n \"beneficiary\": \"0x0000000000000000000000000000000000000000\",\n \"tokenId\": \"26516164265702901957933644848127860370782874751279270726689263951695181556943\",\n \"makerAmount\": \"55000000\",\n \"takerAmount\": \"100000000\",\n \"expiration\": \"0\",\n \"nonce\": \"0\",\n \"identifier\": \"0x00000000000000000000000000000000\",\n \"metadata\": \"0x0000000000000000000000000000000000000000000000000000000000000000\",\n \"side\": 0,\n \"signatureType\": 3,\n \"signature\": \"0xa1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f901b\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://orderbooks.xo.market/order")
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 \"orderType\": \"GTC\",\n \"order\": {\n \"salt\": \"12345678901234567890\",\n \"maker\": \"0xCAFE000000000000000000000000000000000A11\",\n \"signer\": \"0xCAFE000000000000000000000000000000000A11\",\n \"beneficiary\": \"0x0000000000000000000000000000000000000000\",\n \"tokenId\": \"26516164265702901957933644848127860370782874751279270726689263951695181556943\",\n \"makerAmount\": \"55000000\",\n \"takerAmount\": \"100000000\",\n \"expiration\": \"0\",\n \"nonce\": \"0\",\n \"identifier\": \"0x00000000000000000000000000000000\",\n \"metadata\": \"0x0000000000000000000000000000000000000000000000000000000000000000\",\n \"side\": 0,\n \"signatureType\": 3,\n \"signature\": \"0xa1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f901b\"\n }\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"errorMsg": null,
"makingAmount": "0",
"takingAmount": "0",
"orderID": "0x0011223344556677889900aabbccddeeff00112233445566778899aabbccddee",
"status": "live",
"transactionsHashes": [],
"tradeIds": []
}Post a new order
Place a single signed CTF order. Optional postOnly on the
envelope (not inside the signed order) rejects the request if
the order would take liquidity. See PlaceOrderRequest.postOnly.
use alloy::signers::local::LocalSigner;
use rust_decimal_macros::dec;
use xo_orderbook_client::orderbook::{Client, Config};
use xo_orderbook_client::orderbook::types::{OrderType, Side};
use xo_orderbook_client::types::{Decimal, U256};
// 1. Authenticate (mints/derives the L2 HMAC creds).
let signer = LocalSigner::from_bytes(&std::env::var("XO_PRIVATE_KEY")?.parse()?)?;
let client = Client::new("https://orderbooks.xo.market", Config::default())?
.authentication_builder(signer.clone())
.authenticate()
.await?;
let token_id = U256::from_str_radix(
"26516164265702901957933644848127860370782874751279270726689263951695181556943",
10,
)?;
// 2. Build a GTC limit BUY at 0.55 for 100 shares.
let order = client
.limit_order()
.token_id(token_id)
.order_type(OrderType::GTC)
.price(dec!(0.55))
.size(Decimal::ONE_HUNDRED)
.side(Side::Buy)
.build()
.await?;
// 3. Sign + submit.
let signed = client.sign(&signer, order).await?;
let resp = client.post_order(signed).await?;
println!("order id: {}, status: {}", resp.order_id, resp.status);curl --request POST \
--url https://orderbooks.xo.market/order \
--header 'Content-Type: application/json' \
--data '
{
"orderType": "GTC",
"order": {
"salt": "12345678901234567890",
"maker": "0xCAFE000000000000000000000000000000000A11",
"signer": "0xCAFE000000000000000000000000000000000A11",
"beneficiary": "0x0000000000000000000000000000000000000000",
"tokenId": "26516164265702901957933644848127860370782874751279270726689263951695181556943",
"makerAmount": "55000000",
"takerAmount": "100000000",
"expiration": "0",
"nonce": "0",
"identifier": "0x00000000000000000000000000000000",
"metadata": "0x0000000000000000000000000000000000000000000000000000000000000000",
"side": 0,
"signatureType": 3,
"signature": "0xa1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f901b"
}
}
'import requests
url = "https://orderbooks.xo.market/order"
payload = {
"orderType": "GTC",
"order": {
"salt": "12345678901234567890",
"maker": "0xCAFE000000000000000000000000000000000A11",
"signer": "0xCAFE000000000000000000000000000000000A11",
"beneficiary": "0x0000000000000000000000000000000000000000",
"tokenId": "26516164265702901957933644848127860370782874751279270726689263951695181556943",
"makerAmount": "55000000",
"takerAmount": "100000000",
"expiration": "0",
"nonce": "0",
"identifier": "0x00000000000000000000000000000000",
"metadata": "0x0000000000000000000000000000000000000000000000000000000000000000",
"side": 0,
"signatureType": 3,
"signature": "0xa1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f901b"
}
}
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({
orderType: 'GTC',
order: {
salt: '12345678901234567890',
maker: '0xCAFE000000000000000000000000000000000A11',
signer: '0xCAFE000000000000000000000000000000000A11',
beneficiary: '0x0000000000000000000000000000000000000000',
tokenId: '26516164265702901957933644848127860370782874751279270726689263951695181556943',
makerAmount: '55000000',
takerAmount: '100000000',
expiration: '0',
nonce: '0',
identifier: '0x00000000000000000000000000000000',
metadata: '0x0000000000000000000000000000000000000000000000000000000000000000',
side: 0,
signatureType: 3,
signature: '0xa1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f901b'
}
})
};
fetch('https://orderbooks.xo.market/order', 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/order",
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([
'orderType' => 'GTC',
'order' => [
'salt' => '12345678901234567890',
'maker' => '0xCAFE000000000000000000000000000000000A11',
'signer' => '0xCAFE000000000000000000000000000000000A11',
'beneficiary' => '0x0000000000000000000000000000000000000000',
'tokenId' => '26516164265702901957933644848127860370782874751279270726689263951695181556943',
'makerAmount' => '55000000',
'takerAmount' => '100000000',
'expiration' => '0',
'nonce' => '0',
'identifier' => '0x00000000000000000000000000000000',
'metadata' => '0x0000000000000000000000000000000000000000000000000000000000000000',
'side' => 0,
'signatureType' => 3,
'signature' => '0xa1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f901b'
]
]),
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/order"
payload := strings.NewReader("{\n \"orderType\": \"GTC\",\n \"order\": {\n \"salt\": \"12345678901234567890\",\n \"maker\": \"0xCAFE000000000000000000000000000000000A11\",\n \"signer\": \"0xCAFE000000000000000000000000000000000A11\",\n \"beneficiary\": \"0x0000000000000000000000000000000000000000\",\n \"tokenId\": \"26516164265702901957933644848127860370782874751279270726689263951695181556943\",\n \"makerAmount\": \"55000000\",\n \"takerAmount\": \"100000000\",\n \"expiration\": \"0\",\n \"nonce\": \"0\",\n \"identifier\": \"0x00000000000000000000000000000000\",\n \"metadata\": \"0x0000000000000000000000000000000000000000000000000000000000000000\",\n \"side\": 0,\n \"signatureType\": 3,\n \"signature\": \"0xa1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f901b\"\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/order")
.header("Content-Type", "application/json")
.body("{\n \"orderType\": \"GTC\",\n \"order\": {\n \"salt\": \"12345678901234567890\",\n \"maker\": \"0xCAFE000000000000000000000000000000000A11\",\n \"signer\": \"0xCAFE000000000000000000000000000000000A11\",\n \"beneficiary\": \"0x0000000000000000000000000000000000000000\",\n \"tokenId\": \"26516164265702901957933644848127860370782874751279270726689263951695181556943\",\n \"makerAmount\": \"55000000\",\n \"takerAmount\": \"100000000\",\n \"expiration\": \"0\",\n \"nonce\": \"0\",\n \"identifier\": \"0x00000000000000000000000000000000\",\n \"metadata\": \"0x0000000000000000000000000000000000000000000000000000000000000000\",\n \"side\": 0,\n \"signatureType\": 3,\n \"signature\": \"0xa1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f901b\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://orderbooks.xo.market/order")
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 \"orderType\": \"GTC\",\n \"order\": {\n \"salt\": \"12345678901234567890\",\n \"maker\": \"0xCAFE000000000000000000000000000000000A11\",\n \"signer\": \"0xCAFE000000000000000000000000000000000A11\",\n \"beneficiary\": \"0x0000000000000000000000000000000000000000\",\n \"tokenId\": \"26516164265702901957933644848127860370782874751279270726689263951695181556943\",\n \"makerAmount\": \"55000000\",\n \"takerAmount\": \"100000000\",\n \"expiration\": \"0\",\n \"nonce\": \"0\",\n \"identifier\": \"0x00000000000000000000000000000000\",\n \"metadata\": \"0x0000000000000000000000000000000000000000000000000000000000000000\",\n \"side\": 0,\n \"signatureType\": 3,\n \"signature\": \"0xa1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f901b\"\n }\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"errorMsg": null,
"makingAmount": "0",
"takingAmount": "0",
"orderID": "0x0011223344556677889900aabbccddeeff00112233445566778899aabbccddee",
"status": "live",
"transactionsHashes": [],
"tradeIds": []
}Body
EIP-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
Wire shape uses camelCase (orderID, errorMsg,
makingAmount, takingAmount, transactionsHashes, tradeIds)
to satisfy polymarket-client-sdk deserialisation. The struct's
Rust source is #[serde(rename_all = "camelCase")] with explicit
rename = "orderID" and rename = "transactionsHashes".
null when success: true. Populated with a stable failure
message when success: false (e.g. "FOK could not fill at signed price").
Total maker-side amount across all fills, decimal string.
USDC micro-units for a BUY, human-share tokens for a SELL.
"0" when the order rested with no fills.
Total taker-side amount across all fills, decimal string.
Opposite-side unit of makingAmount. "0" when no fills.
0x-prefixed EIP-712 order hash digest. Same hash the SDK signed.
live— resting on the book (GTC/GTD with remainder).matched— fully filled.delayed— queued, FOK could not fill at signed price, or otherwise not yet matched. Matches the canonicalpy-clob-clientstatus strings (NOT"cancelled").
live, matched, delayed 0x-prefixed on-chain settlement tx hashes (one per matched batch).
0x-prefixed 32-byte trade ids for fills produced by this order.