curl --request POST \
--url https://perps-api.vooi.io/exchange/batch-orders \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
[
{
"asset": "ETH",
"size": "0.001",
"clientOrderId": "<string>",
"normalizeParams": true,
"price": "1850.50",
"reduceOnly": true,
"timeInForce": "gtc"
}
]
'import requests
url = "https://perps-api.vooi.io/exchange/batch-orders"
payload = [
{
"asset": "ETH",
"size": "0.001",
"clientOrderId": "<string>",
"normalizeParams": True,
"price": "1850.50",
"reduceOnly": True,
"timeInForce": "gtc"
}
]
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify([
{
asset: 'ETH',
size: '0.001',
clientOrderId: '<string>',
normalizeParams: true,
price: '1850.50',
reduceOnly: true,
timeInForce: 'gtc'
}
])
};
fetch('https://perps-api.vooi.io/exchange/batch-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://perps-api.vooi.io/exchange/batch-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([
[
'asset' => 'ETH',
'size' => '0.001',
'clientOrderId' => '<string>',
'normalizeParams' => true,
'price' => '1850.50',
'reduceOnly' => true,
'timeInForce' => 'gtc'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"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://perps-api.vooi.io/exchange/batch-orders"
payload := strings.NewReader("[\n {\n \"asset\": \"ETH\",\n \"size\": \"0.001\",\n \"clientOrderId\": \"<string>\",\n \"normalizeParams\": true,\n \"price\": \"1850.50\",\n \"reduceOnly\": true,\n \"timeInForce\": \"gtc\"\n }\n]")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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://perps-api.vooi.io/exchange/batch-orders")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("[\n {\n \"asset\": \"ETH\",\n \"size\": \"0.001\",\n \"clientOrderId\": \"<string>\",\n \"normalizeParams\": true,\n \"price\": \"1850.50\",\n \"reduceOnly\": true,\n \"timeInForce\": \"gtc\"\n }\n]")
.asString();require 'uri'
require 'net/http'
url = URI("https://perps-api.vooi.io/exchange/batch-orders")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "[\n {\n \"asset\": \"ETH\",\n \"size\": \"0.001\",\n \"clientOrderId\": \"<string>\",\n \"normalizeParams\": true,\n \"price\": \"1850.50\",\n \"reduceOnly\": true,\n \"timeInForce\": \"gtc\"\n }\n]"
response = http.request(request)
puts response.read_body{
"results": [
{
"status": "created"
}
]
}{
"message": "Invalid order id: 123",
"statusCode": 503
}Create multiple orders in a single batch
curl --request POST \
--url https://perps-api.vooi.io/exchange/batch-orders \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
[
{
"asset": "ETH",
"size": "0.001",
"clientOrderId": "<string>",
"normalizeParams": true,
"price": "1850.50",
"reduceOnly": true,
"timeInForce": "gtc"
}
]
'import requests
url = "https://perps-api.vooi.io/exchange/batch-orders"
payload = [
{
"asset": "ETH",
"size": "0.001",
"clientOrderId": "<string>",
"normalizeParams": True,
"price": "1850.50",
"reduceOnly": True,
"timeInForce": "gtc"
}
]
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify([
{
asset: 'ETH',
size: '0.001',
clientOrderId: '<string>',
normalizeParams: true,
price: '1850.50',
reduceOnly: true,
timeInForce: 'gtc'
}
])
};
fetch('https://perps-api.vooi.io/exchange/batch-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://perps-api.vooi.io/exchange/batch-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([
[
'asset' => 'ETH',
'size' => '0.001',
'clientOrderId' => '<string>',
'normalizeParams' => true,
'price' => '1850.50',
'reduceOnly' => true,
'timeInForce' => 'gtc'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"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://perps-api.vooi.io/exchange/batch-orders"
payload := strings.NewReader("[\n {\n \"asset\": \"ETH\",\n \"size\": \"0.001\",\n \"clientOrderId\": \"<string>\",\n \"normalizeParams\": true,\n \"price\": \"1850.50\",\n \"reduceOnly\": true,\n \"timeInForce\": \"gtc\"\n }\n]")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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://perps-api.vooi.io/exchange/batch-orders")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("[\n {\n \"asset\": \"ETH\",\n \"size\": \"0.001\",\n \"clientOrderId\": \"<string>\",\n \"normalizeParams\": true,\n \"price\": \"1850.50\",\n \"reduceOnly\": true,\n \"timeInForce\": \"gtc\"\n }\n]")
.asString();require 'uri'
require 'net/http'
url = URI("https://perps-api.vooi.io/exchange/batch-orders")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "[\n {\n \"asset\": \"ETH\",\n \"size\": \"0.001\",\n \"clientOrderId\": \"<string>\",\n \"normalizeParams\": true,\n \"price\": \"1850.50\",\n \"reduceOnly\": true,\n \"timeInForce\": \"gtc\"\n }\n]"
response = http.request(request)
puts response.read_body{
"results": [
{
"status": "created"
}
]
}{
"message": "Invalid order id: 123",
"statusCode": 503
}Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Body
1Asset identifier: base symbol (e.g. "ETH") or full pair (e.g. "ETHUSDC").
1"ETH"
Supported perpetual exchange
aster, binance, bybit, extended, gate, hyperliquid, lighter, mexc, ondo, robinhood buy, sell Order size in base currency
\d+(\.\d+)?"0.001"
Broker configuration. Hyperliquid: id is builder address, feeBps is builder fee. Lighter/Robinhood: id is integrator account index, feeBps is integrator fee (applies to both taker and maker). Aster: id is builder address, feeBps is builder fee in BPS. MEXC: id is the Broker_ID sent as the source header to attribute the order; feeBps is still required but has no effect, since MEXC charges no builder fee. On Hyperliquid, Lighter, and Robinhood the user must have pre-approved this builder/integrator on-chain (and feeBps must be ≤ the approved cap); on Aster the approval is bundled into registration. Overridden by the broker settings (if any) of the broker the user is registered through: orders the venue executes as limit take the limitFeeBps of those settings, orders it executes as market take the marketFeeBps (trigger orders count as market on Hyperliquid, Aster and Ondo), and Lighter/Robinhood receive both as maker/taker fees.
Show child attributes
Show child attributes
Your custom order identifier, forwarded to the exchange as-is (max 32 characters on Binance). On Binance, when omitted, an id carrying the broker rebate tag is generated instead. Ignored on Lighter/Robinhood when placing orders with takeProfit or stopLoss.
When true, forces normalization of parameters to match exchange requirements if possible.
Limit price (optional for market orders)
\d+(\.\d+)?"1850.50"
If true, order will only reduce existing position. Used for TP/SL orders
true
Stop loss order configuration (combine with takeProfit for bracket orders, not supported on Aster)
Show child attributes
Show child attributes
Take profit order configuration (combine with stopLoss for bracket orders, not supported on Aster)
Show child attributes
Show child attributes
Order time in force policy. gtc (Good-Till-Cancel) — order stays active until filled or manually canceled. ioc (Immediate-Or-Cancel) — fills immediately (fully or partially), unfilled remainder is canceled. fok (Fill-Or-Kill) — fills entirely and immediately or is canceled completely; supported only on Aster. alo (Add Liquidity Only) — order only adds liquidity as a maker; canceled if it would execute as taker. Defaults to gtc when omitted.
gtc, ioc, fok, alo "gtc"
Optional trigger configuration for stop-loss or take-profit orders
Show child attributes
Show child attributes
Response
Per-order results, index-correlated with input
Order was placed successfully
- BatchCreateOrderItemResult
- BatchCreateOrderItemResult
Show child attributes
Show child attributes