
Trading with the GaiaEx API: Authentication, Orders, and Market Data
Connect to GaiaEx programmatically and place your first automated trade
GaiaEx API Overview: REST + WebSocket on Hyperliquid L1
GaiaEx is a decentralized exchange built on Hyperliquid L1, and its API gives you programmatic access to everything the platform offers — market data, order management, position tracking, and real-time streaming. Whether you're building a trading bot, a portfolio dashboard, or a custom alerting system, the API is your entry point.
The API is split into two complementary protocols:
- REST API — Request-response endpoints for placing orders, querying balances, fetching historical trades, and managing API keys. Use REST when you need to do something or ask for something specific.
- WebSocket API — Persistent streaming connections for real-time market data (trades, order book updates, tickers) and private account events (order fills, position changes). Use WebSocket when you need to react to something the moment it happens.
Under the hood, GaiaEx connects to the Hyperliquid L1 on-chain order book. Your orders are matched on-chain with deterministic execution, and your funds are secured by MPC (Multi-Party Computation) wallets — meaning no single party (not even GaiaEx) holds your complete private key. The API abstracts the blockchain complexity: you send a JSON request to place an order, and the platform handles signing, submission, and confirmation on L1.
The base URL for the REST API follows standard conventions: https://api.gaiaex.com/v1/. WebSocket connections are established at wss://api.gaiaex.com/ws/v1/. All endpoints return JSON, all timestamps are in milliseconds since epoch (UTC), and all monetary values are strings to avoid floating-point precision issues.
API Key Management and HMAC Authentication
To access private endpoints (placing orders, querying your balances), you need an API key pair. Generate one from the GaiaEx dashboard under Settings → API Keys. You'll receive two values:
- API Key — A public identifier sent with every request. Think of it as your username.
- API Secret — A private key used to sign requests. Never share it, never commit it to version control, never send it in a request header.
GaiaEx uses HMAC-SHA256 signing to authenticate private requests. The process: concatenate the timestamp, HTTP method, request path, and body into a single string, then compute an HMAC signature using your secret. The server performs the same computation and compares signatures.
import hmac, hashlib, time, requests, json
API_KEY = "your_api_key"
API_SECRET = "your_api_secret"
BASE_URL = "https://api.gaiaex.com/v1"
def signed_request(method, path, body=None):
timestamp = str(int(time.time() * 1000))
body_str = json.dumps(body) if body else ""
message = timestamp + method.upper() + path + body_str
signature = hmac.new(
API_SECRET.encode(), message.encode(), hashlib.sha256
).hexdigest()
headers = {
"X-API-Key": API_KEY,
"X-Timestamp": timestamp,
"X-Signature": signature,
"Content-Type": "application/json",
}
resp = requests.request(method, BASE_URL + path, headers=headers,
data=body_str if body else None)
return resp.json()
Store your API secret in environment variables or a secrets manager — never hardcode it. Set IP whitelisting on your API key in the dashboard to restrict usage to your server's IP address. If your key is compromised, revoke it immediately from the dashboard and generate a new one.
The timestamp component prevents replay attacks: the server rejects any request where the timestamp is more than 30 seconds from the server's clock. Make sure your machine's clock is synchronized via NTP.
Fetching Market Data: Orderbook, Trades, and Ticker
Market data endpoints are public — no authentication required. They provide the raw information you need to make trading decisions.
Order book — Returns the current bids and asks for a given symbol. The depth parameter controls how many price levels are returned (default 20, max 100).
# Fetch the BTC-USD order book (top 10 levels)
resp = requests.get(f"{BASE_URL}/orderbook/BTC-USD?depth=10")
book = resp.json()
best_bid = book["bids"][0] # [price, quantity]
best_ask = book["asks"][0]
spread = float(best_ask[0]) - float(best_bid[0])
print(f"Spread: ${spread:.2f}")
Recent trades — Returns the last N executed trades for a symbol. Each trade includes the price, quantity, side (whether the taker was buying or selling), and timestamp.
# Fetch the last 50 ETH-USD trades
resp = requests.get(f"{BASE_URL}/trades/ETH-USD?limit=50")
trades = resp.json()["trades"]
avg_price = sum(float(t["price"]) for t in trades) / len(trades)
print(f"Average of last 50 trades: ${avg_price:.2f}")
Ticker — A summary of the current market state: last price, 24h high/low, 24h volume, best bid/ask, and percentage change. Ideal for building watchlists or scanning for volatility.
# Fetch all tickers
resp = requests.get(f"{BASE_URL}/tickers")
for ticker in resp.json():
if float(ticker["change24h"]) > 5.0:
print(f"{ticker['symbol']}: +{ticker['change24h']}%")
For real-time data, use the WebSocket feeds instead of polling these endpoints. The REST endpoints are rate-limited and introduce latency; the WebSocket delivers updates the instant they occur on Hyperliquid L1.
Placing Orders: Market, Limit, and Stop
Order placement is the core action in any trading system. GaiaEx supports three order types through the POST /orders endpoint:
Market order — Execute immediately at the best available price. Use when speed of execution matters more than price precision.
# Buy 0.1 BTC at market price
order = signed_request("POST", "/orders", {
"symbol": "BTC-USD",
"side": "buy",
"type": "market",
"quantity": "0.1",
})
print(f"Filled at {order['avgPrice']}")
Limit order — Execute only at your specified price or better. Rests on the order book until filled, cancelled, or expired.
# Sell 2 ETH at $3,500 or higher
order = signed_request("POST", "/orders", {
"symbol": "ETH-USD",
"side": "sell",
"type": "limit",
"price": "3500.00",
"quantity": "2.0",
"timeInForce": "GTC", # Good Till Cancelled
})
Stop order — A conditional order that becomes active when the market reaches a trigger price. Used for stop-losses and breakout entries.
# Stop-loss: sell 0.5 BTC if price drops to $58,000
order = signed_request("POST", "/orders", {
"symbol": "BTC-USD",
"side": "sell",
"type": "stop_market",
"stopPrice": "58000.00",
"quantity": "0.5",
})
To manage existing orders: query open orders with GET /orders?status=open, cancel a specific order with DELETE /orders/{orderId}, or cancel all open orders for a symbol with DELETE /orders?symbol=BTC-USD. For position management, GET /positions returns all open positions with entry price, quantity, unrealized P&L, and liquidation price.
Streaming Real-Time Data via WebSocket
The GaiaEx WebSocket API uses a subscribe/unsubscribe model. After connecting, you send subscription messages specifying which channels you want to receive. Both public (market data) and private (account events) channels are available on the same connection.
import asyncio, json, hmac, hashlib, time
import websockets
async def connect_gaiaex():
uri = "wss://api.gaiaex.com/ws/v1"
async with websockets.connect(uri) as ws:
# Authenticate for private channels
ts = str(int(time.time() * 1000))
sig = hmac.new(API_SECRET.encode(),
(ts + "websocket_auth").encode(),
hashlib.sha256).hexdigest()
await ws.send(json.dumps({
"method": "auth",
"apiKey": API_KEY,
"timestamp": ts,
"signature": sig,
}))
# Subscribe to public + private channels
await ws.send(json.dumps({
"method": "subscribe",
"channels": [
"trades.BTC-USD",
"orderbook.BTC-USD",
"account.orders",
"account.positions",
]
}))
async for msg in ws:
data = json.loads(msg)
ch = data.get("channel", "")
if ch == "account.orders":
print(f"Order update: {data['status']} {data['orderId']}")
elif ch == "trades.BTC-USD":
print(f"Trade: {data['price']} x {data['quantity']}")
asyncio.run(connect_gaiaex())
The account.orders channel pushes updates whenever one of your orders is filled, partially filled, or cancelled — eliminating the need to poll the REST endpoint. The account.positions channel streams real-time P&L and margin updates. Combined with the public market data channels, a single WebSocket connection provides everything a trading bot needs to operate.
Always implement a heartbeat mechanism: GaiaEx sends periodic ping frames, and your client must respond with pong frames. If no pong is received within 30 seconds, the server closes the connection. On your side, if no data arrives for 30 seconds, assume the connection is dead and reconnect.
Building a Simple Trading Bot: Monitor, Execute, Manage
Let's tie everything together into a minimal but functional trading bot. The bot monitors the BTC-USD price via WebSocket, and when the price drops below a target, it places a limit buy order. When the position is open and the price rises above a take-profit level, it closes the position.
import asyncio, json
import websockets
TARGET_BUY = 60000.0
TAKE_PROFIT = 63000.0
QUANTITY = "0.05"
position_open = False
async def trading_bot():
global position_open
uri = "wss://api.gaiaex.com/ws/v1"
async with websockets.connect(uri) as ws:
# Auth + subscribe (omitted for brevity)
await ws.send(json.dumps({
"method": "subscribe",
"channels": ["trades.BTC-USD"]
}))
async for msg in ws:
data = json.loads(msg)
if data.get("channel") != "trades.BTC-USD":
continue
price = float(data["price"])
if not position_open and price <= TARGET_BUY:
order = signed_request("POST", "/orders", {
"symbol": "BTC-USD", "side": "buy",
"type": "limit", "price": str(TARGET_BUY),
"quantity": QUANTITY,
})
print(f"BUY order placed: {order['orderId']}")
position_open = True
elif position_open and price >= TAKE_PROFIT:
order = signed_request("POST", "/orders", {
"symbol": "BTC-USD", "side": "sell",
"type": "market", "quantity": QUANTITY,
})
print(f"SELL order placed: {order['orderId']}")
position_open = False
asyncio.run(trading_bot())
This is deliberately simple. A production bot would add: error handling with try/except around every API call and automatic reconnection; retry logic with exponential backoff for transient failures; position tracking via the account.positions WebSocket channel instead of a boolean flag; risk limits that halt trading after a maximum daily loss; and logging that records every decision and API response for post-trade analysis.
GaiaEx's MPC wallet architecture means your bot never handles raw private keys — the signing is handled by the platform's distributed key infrastructure. This reduces the security surface area compared to bots that manage their own wallet keys, where a single compromise can drain all funds. Combined with API key IP whitelisting and the HMAC authentication layer, you get defense in depth for automated trading.
Start small: deploy with the minimum position size, monitor for 48 hours, verify that fills match expectations, then scale gradually. The best trading bots are built incrementally, not in a single coding sprint.