GaiaExGaiaEx
API

Migrating from Binance

Step-by-step guide for Binance traders switching to GaiaEx: header mapping, symbol format differences, endpoint equivalents, and working code examples.

Migrating from Binance

This guide helps Binance Futures API users migrate to GaiaEx. The core concepts are identical — HMAC-SHA256 authentication, REST + WebSocket architecture, and similar order types. The differences are mainly in header names, endpoint paths, and symbol formatting.

QUICK SUMMARY

If you have a working Binance Futures bot, the migration typically takes 30–60 minutes. The main changes are: (1) swap header names, (2) update base URL, (3) adjust symbol format, (4) update endpoint paths.

WHAT'S DIFFERENT FROM BINANCE — FUNDING

Binance lets API keys with a withdrawal scope and whitelisted addresses move funds off the exchange. GaiaEx does not. Because the account is self-custodied, deposits and withdrawals require the user's embedded-wallet signature and a passkey step-up, which are only available in the GaiaEx mobile app. Your trading bot operates entirely within the user's deposited balance — it cannot top up, withdraw, or transfer on-chain. Plan for this: migrate the trading logic, but keep funding as a manual in-app step.

Authentication Mapping

Both exchanges use HMAC-SHA256, but the header names and signature construction differ.

ConceptBinanceGaiaEx
API Key HeaderX-MBX-APIKEYX-GAIAEX-APIKEY
TimestampQuery param: timestamp=Header: X-GAIAEX-TIMESTAMP
SignatureQuery param: signature=Header: X-GAIAEX-SIGNATURE
Signature Inputquery_stringtimestamp + METHOD + path + body
Recv WindowrecvWindow=5000 (query)Fixed 5-second window (server-side)

Binance Signature (Before)

# Binance: signature is over the query string
query = f"symbol=BTCUSDT&side=BUY&type=LIMIT×tamp={timestamp}"
signature = hmac.new(secret.encode(), query.encode(), hashlib.sha256).hexdigest()
url = f"https://fapi.binance.com/fapi/v1/order?{query}&signature={signature}"
headers = {"X-MBX-APIKEY": api_key}

GaiaEx Signature (After)

# GaiaEx: signature is over timestamp + method + path + body
timestamp = str(int(time.time() * 1000))
body = json.dumps({"user_address": addr, "symbol": "BTC", "is_buy": True, "size": "0.1"})
message = timestamp + "POST" + "/order" + body
signature = hmac.new(secret.encode(), message.encode(), hashlib.sha256).hexdigest()
headers = {
    "X-GAIAEX-APIKEY": api_key,
    "X-GAIAEX-TIMESTAMP": timestamp,
    "X-GAIAEX-SIGNATURE": signature,
}

Base URL

Binance FuturesGaiaEx
RESThttps://fapi.binance.comhttps://openapi.gaiaex.com/v1/trade
WebSocketwss://fstream.binance.comwss://openapi.gaiaex.com

Symbol Format

GaiaEx uses a simpler symbol format without the quote asset suffix.

AssetBinanceGaiaEx
Bitcoin perpBTCUSDTBTC
Ethereum perpETHUSDTETH
Solana perpSOLUSDTSOL
Apple (RWA)N/Axyz:AAPL
Gold (RWA)N/Axyz:GOLD
OpenAI (venture)N/Avntl:OPENAI

Conversion rule: Strip the USDT suffix. All GaiaEx perps are USDC-margined.

# Binance symbol → GaiaEx symbol
def convert_symbol(binance_symbol: str) -> str:
    return binance_symbol.replace("USDT", "").replace("USD", "")

Endpoint Mapping

Market Data

ActionBinanceGaiaEx
List symbolsGET /fapi/v1/exchangeInfoGET /symbols/list
Server timeGET /fapi/v1/timeGET /time
Order bookGET /fapi/v1/depth?symbol=WebSocket: wss://.../ws/market/{symbol}

Trading

ActionBinanceGaiaEx
Place orderPOST /fapi/v1/orderPOST /order
Cancel orderDELETE /fapi/v1/orderPOST /order/cancel
Cancel allDELETE /fapi/v1/allOpenOrdersPOST /order/cancel-all
Modify orderPUT /fapi/v1/orderPOST /order/modify
Set leveragePOST /fapi/v1/leveragePOST /leverage

Account Data

ActionBinanceGaiaEx
BalanceGET /fapi/v2/balanceGET /user/{address}/balance
PositionsGET /fapi/v2/positionRiskGET /user/{address}/positions
Open ordersGET /fapi/v1/openOrdersGET /user/{address}/openOrders
Trade fillsGET /fapi/v1/userTradesGET /user/{address}/fills
Funding historyGET /fapi/v1/income?incomeType=FUNDING_FEEGET /user/{address}/fundingHistory

WebSocket Streams

StreamBinanceGaiaEx
Order bookwss://.../ws/btcusdt@depthwss://.../ws/market/BTC
User datawss://.../ws/{listenKey}wss://.../ws/user/{address}

KEY DIFFERENCE: WebSocket Auth

Binance uses a listenKey obtained from a REST call. GaiaEx authenticates directly via the Sec-WebSocket-Protocol: Bearer.{token} header — no extra REST call needed.

No Mapping: Funding Endpoints

Binance endpoints like POST /sapi/v1/capital/withdraw/apply, GET /sapi/v1/capital/deposit/address, and internal-transfer APIs have no GaiaEx equivalent in the public API. All deposits and withdrawals happen in the mobile app via the user's embedded wallet — there is no API-key-callable path.

Order Parameter Mapping

Binance ParamGaiaEx ParamNotes
symbol ("BTCUSDT")symbol ("BTC")No quote asset suffix
side ("BUY"/"SELL")is_buy (true/false)Boolean instead of string enum
type ("LIMIT"/"MARKET")order_type ("limit"/"market")Lowercase
quantitysizeString type
pricepriceString type, omit for market
timeInForce ("GTC")N/AAll limit orders are GTC
reduceOnlyreduce_onlySnake_case
newClientOrderIdclient_idOptional tracking ID
N/Auser_addressRequired — your wallet address

Before (Binance)

order = client.futures_create_order(
    symbol="ETHUSDT",
    side="BUY",
    type="LIMIT",
    timeInForce="GTC",
    quantity=0.1,
    price=3500,
)

After (GaiaEx)

import hmac, hashlib, time, json, requests

with open("config.json") as f:
    cfg = json.load(f)

API_KEY, API_SECRET = cfg["api_key"], cfg["api_secret"]
ADDRESS = cfg["user_address"]
BASE = "https://openapi.gaiaex.com/v1/trade"

def sign(method, path, body=""):
    ts = str(int(time.time() * 1000))
    sig = hmac.new(API_SECRET.encode(), (ts + method + path + body).encode(), hashlib.sha256).hexdigest()
    return {"X-GAIAEX-APIKEY": API_KEY, "X-GAIAEX-TIMESTAMP": ts, "X-GAIAEX-SIGNATURE": sig, "Content-Type": "application/json"}

body = json.dumps({"user_address": ADDRESS, "symbol": "ETH", "is_buy": True, "size": "0.1", "price": "3500.00", "order_type": "limit"})
order = requests.post(BASE + "/order", headers=sign("POST", "/order", body), data=body).json()

Complete Migration Example

A full trading bot migration — from Binance to GaiaEx.

Before (Binance)

from binance.client import Client

client = Client(api_key="...", api_secret="...")

# Get balance
balance = client.futures_account_balance()
usdt = next(b for b in balance if b["asset"] == "USDT")
print(f"USDT: {usdt['balance']}")

# Place order
order = client.futures_create_order(
    symbol="ETHUSDT", side="BUY", type="LIMIT",
    timeInForce="GTC", quantity=0.1, price=3500,
)

# Set leverage
client.futures_change_leverage(symbol="ETHUSDT", leverage=10)

# Cancel all
client.futures_cancel_all_open_orders(symbol="ETHUSDT")

After (GaiaEx)

import hmac, hashlib, time, json, requests

with open("config.json") as f:
    cfg = json.load(f)

API_KEY, API_SECRET = cfg["api_key"], cfg["api_secret"]
ADDRESS = cfg["user_address"]
BASE = "https://openapi.gaiaex.com/v1/trade"

def sign(method, path, body=""):
    ts = str(int(time.time() * 1000))
    sig = hmac.new(API_SECRET.encode(), (ts + method + path + body).encode(), hashlib.sha256).hexdigest()
    return {"X-GAIAEX-APIKEY": API_KEY, "X-GAIAEX-TIMESTAMP": ts, "X-GAIAEX-SIGNATURE": sig, "Content-Type": "application/json"}

# Get balance
balance = requests.get(BASE + f"/user/{ADDRESS}/balance", headers=sign("GET", f"/user/{ADDRESS}/balance")).json()
print(f"USDC: {balance.get('available_margin')}")

# Place order
body = json.dumps({"user_address": ADDRESS, "symbol": "ETH", "is_buy": True, "size": "0.1", "price": "3500.00", "order_type": "limit"})
order = requests.post(BASE + "/order", headers=sign("POST", "/order", body), data=body).json()

# Set leverage
body = json.dumps({"user_address": ADDRESS, "symbol": "ETH", "leverage": 10})
requests.post(BASE + "/leverage", headers=sign("POST", "/leverage", body), data=body)

# Cancel all
body = json.dumps({"user_address": ADDRESS, "symbol": "ETH"})
requests.post(BASE + "/order/cancel-all", headers=sign("POST", "/order/cancel-all", body), data=body)

GaiaEx ADVANTAGE

GaiaEx is fully non-custodial — your funds stay on-chain. Unlike Binance, there's no KYC requirement for API trading, and the order book settles on MegaETH with single-block finality.