openOrders
Get all open limit orders for a user on Hyperliquid perpetual markets.
Why Hyperliquid? Build on the dominant perpetuals DEX with 70% market share, $2.7T+ lifetime volume, and $2B TVL with 200K orders/second throughput, zero gas fees, sub-second finality, and fully onchain Central Limit Order Book (CLOB).
When to Use This Endpoint#
The openOrders endpoint is essential for traders, trading platforms, and market makers who need to:
- Order Management — Monitor and manage active limit orders
- Trading Bots — Track order status and execution
- Market Making — Monitor spread and order book participation
- Portfolio Management — Track pending orders across multiple markets
Request#
Endpoint#
POST https://api-hyperliquid-mainnet-info.n.dwellir.com/info
Headers#
| Header | Value | Required |
|---|---|---|
Content-Type | application/json | Yes |
X-Api-Key | Your API key | Yes |
Parameters#
| Parameter | Type | Required | Description |
|---|---|---|---|
type | string | Yes | Must be "openOrders" |
user | string | Yes | User's Ethereum wallet address |
Example Request#
{
"type": "openOrders",
"user": "0x63E8c7C149556D5f34F833419A287bb9Ef81487f"
}
Response#
Success Response#
[
{
"coin": "BTC",
"side": "B",
"limitPx": "69043.0",
"sz": "0.29596",
"oid": 316509475419,
"timestamp": 1770639841704,
"origSz": "0.29596",
"cloid": "0x00000000000000000000019c4151ce32"
},
{
"coin": "ETH",
"side": "A",
"limitPx": "2034.3",
"sz": "12.1703",
"oid": 316509474405,
"timestamp": 1770639841704,
"origSz": "12.1703",
"cloid": "0x00000000000000000000019c4151ce2f"
}
]
Response Fields#
The response is an array of order objects. Each order contains:
| Field | Type | Description |
|---|---|---|
coin | string | Trading pair symbol (e.g., "BTC", "ETH") |
side | string | Order side: "B" for buy, "A" for ask/sell |
limitPx | string | Limit price for the order |
sz | string | Current remaining order size |
oid | integer | Unique order ID |
timestamp | integer | Order creation timestamp in milliseconds |
origSz | string | Original order size when placed |
cloid | string | Client order ID (hexadecimal string) |
Code Examples#
- cURL
- JavaScript
- Python
- Go
curl -X POST 'https://api-hyperliquid-mainnet-info.n.dwellir.com/info' \
-H 'X-Api-Key: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"type": "openOrders",
"user": "0x63E8c7C149556D5f34F833419A287bb9Ef81487f"
}'
const ENDPOINT = 'https://api-hyperliquid-mainnet-info.n.dwellir.com/info';
const API_KEY = 'your-api-key-here';
async function getOpenOrders(userAddress) {
const response = await fetch(ENDPOINT, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Api-Key': API_KEY
},
body: JSON.stringify({
type: 'openOrders',
user: userAddress
})
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
return await response.json();
}
// Usage
const orders = await getOpenOrders('0x63E8c7C149556D5f34F833419A287bb9Ef81487f');
console.log(`Total open orders: ${orders.length}`);
// Display orders
orders.forEach(order => {
const side = order.side === 'B' ? 'BUY' : 'SELL';
const filled = ((parseFloat(order.origSz) - parseFloat(order.sz)) / parseFloat(order.origSz)) * 100;
console.log(
`${side} ${order.sz}/${order.origSz} ${order.coin} @ $${order.limitPx} (${filled.toFixed(1)}% filled)`
);
});
import requests
from typing import List, Dict
from datetime import datetime
ENDPOINT = 'https://api-hyperliquid-mainnet-info.n.dwellir.com/info'
API_KEY = 'your-api-key-here'
def get_open_orders(user_address: str) -> List[Dict]:
"""Get all open orders for a user"""
response = requests.post(
ENDPOINT,
json={
'type': 'openOrders',
'user': user_address
},
headers={
'Content-Type': 'application/json',
'X-Api-Key': API_KEY
},
timeout=10
)
response.raise_for_status()
return response.json()
# Usage
orders = get_open_orders('0x63E8c7C149556D5f34F833419A287bb9Ef81487f')
print(f"Total open orders: {len(orders)}")
# Display orders
for order in orders:
side = "BUY" if order['side'] == 'B' else "SELL"
filled_pct = ((float(order['origSz']) - float(order['sz'])) / float(order['origSz'])) * 100
timestamp = datetime.fromtimestamp(order['timestamp'] / 1000)
print(f"{side} {order['sz']}/{order['origSz']} {order['coin']} @ ${order['limitPx']}")
print(f" Order ID: {order['oid']}")
print(f" Filled: {filled_pct:.1f}%")
print(f" Created: {timestamp}")
print()
# Group by market
from collections import defaultdict
by_market = defaultdict(list)
for order in orders:
by_market[order['coin']].append(order)
for market, market_orders in by_market.items():
print(f"{market}: {len(market_orders)} orders")
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"time"
)
const (
Endpoint = "https://api-hyperliquid-mainnet-info.n.dwellir.com/info"
APIKey = "your-api-key-here"
)
type OpenOrdersRequest struct {
Type string `json:"type"`
User string `json:"user"`
}
type Order struct {
Coin string `json:"coin"`
Side string `json:"side"`
LimitPx string `json:"limitPx"`
Sz string `json:"sz"`
Oid int64 `json:"oid"`
Timestamp int64 `json:"timestamp"`
OrigSz string `json:"origSz"`
}
func getOpenOrders(userAddress string) ([]Order, error) {
reqBody, _ := json.Marshal(OpenOrdersRequest{
Type: "openOrders",
User: userAddress,
})
req, _ := http.NewRequest("POST", Endpoint, bytes.NewBuffer(reqBody))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Api-Key", APIKey)
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
var orders []Order
if err := json.Unmarshal(body, &orders); err != nil {
return nil, err
}
return orders, nil
}
func main() {
orders, err := getOpenOrders("0x63E8c7C149556D5f34F833419A287bb9Ef81487f")
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
fmt.Printf("Total open orders: %d\n\n", len(orders))
for _, order := range orders {
side := "BUY"
if order.Side == "A" {
side = "SELL"
}
timestamp := time.Unix(order.Timestamp/1000, 0)
fmt.Printf("%s %s %s @ $%s\n", side, order.Sz, order.Coin, order.LimitPx)
fmt.Printf(" Order ID: %d\n", order.Oid)
fmt.Printf(" Original Size: %s\n", order.OrigSz)
fmt.Printf(" Created: %s\n\n", timestamp.Format(time.RFC3339))
}
}
Common Use Cases#
1. Monitor Order Fill Progress#
Track how much of each order has been filled:
async function getOrderFillProgress(userAddress) {
const orders = await getOpenOrders(userAddress);
return orders.map(order => {
const orig = parseFloat(order.origSz);
const remaining = parseFloat(order.sz);
const filled = orig - remaining;
const fillPercent = (filled / orig) * 100;
return {
orderId: order.oid,
coin: order.coin,
side: order.side === 'B' ? 'BUY' : 'SELL',
price: parseFloat(order.limitPx),
originalSize: orig,
remainingSize: remaining,
filledSize: filled,
fillPercent: fillPercent.toFixed(2),
isPartiallyFilled: fillPercent > 0 && fillPercent < 100
};
});
}
// Usage
const progress = await getOrderFillProgress('0x63E8c7C149556D5f34F833419A287bb9Ef81487f');
const partialFills = progress.filter(o => o.isPartiallyFilled);
console.log(`${partialFills.length} partially filled orders`);
2. Calculate Total Order Book Exposure#
Calculate total capital committed in open orders:
async function calculateOrderExposure(userAddress) {
const orders = await getOpenOrders(userAddress);
const totalExposure = orders.reduce((sum, order) => {
const size = parseFloat(order.sz);
const price = parseFloat(order.limitPx);
return sum + (size * price);
}, 0);
const byMarket = orders.reduce((acc, order) => {
const size = parseFloat(order.sz);
const price = parseFloat(order.limitPx);
const exposure = size * price;
if (!acc[order.coin]) {
acc[order.coin] = { buy: 0, sell: 0, total: 0 };
}
if (order.side === 'B') {
acc[order.coin].buy += exposure;
} else {
acc[order.coin].sell += exposure;
}
acc[order.coin].total += exposure;
return acc;
}, {});
return {
totalExposure: totalExposure,
byMarket: byMarket,
orderCount: orders.length
};
}
3. Find Stale Orders#
Identify orders that have been open for a long time:
async function findStaleOrders(userAddress, hoursThreshold = 24) {
const orders = await getOpenOrders(userAddress);
const now = Date.now();
const thresholdMs = hoursThreshold * 60 * 60 * 1000;
const staleOrders = orders.filter(order => {
return (now - order.timestamp) > thresholdMs;
});
return staleOrders.map(order => ({
orderId: order.oid,
coin: order.coin,
side: order.side === 'B' ? 'BUY' : 'SELL',
price: order.limitPx,
size: order.sz,
ageHours: ((now - order.timestamp) / (1000 * 60 * 60)).toFixed(1)
}));
}
// Usage
const stale = await findStaleOrders('0x63E8c7C149556D5f34F833419A287bb9Ef81487f', 48);
console.log(`${stale.length} orders older than 48 hours`);
stale.forEach(o => {
console.log(`${o.coin} ${o.side} @ $${o.price} (${o.ageHours}h old)`);
});
4. Group Orders by Market#
Organize orders by trading pair:
async function groupOrdersByMarket(userAddress) {
const orders = await getOpenOrders(userAddress);
const grouped = orders.reduce((acc, order) => {
if (!acc[order.coin]) {
acc[order.coin] = {
buy: [],
sell: [],
totalBuySize: 0,
totalSellSize: 0
};
}
const side = order.side === 'B' ? 'buy' : 'sell';
acc[order.coin][side].push(order);
if (side === 'buy') {
acc[order.coin].totalBuySize += parseFloat(order.sz);
} else {
acc[order.coin].totalSellSize += parseFloat(order.sz);
}
return acc;
}, {});
return grouped;
}
// Usage
const byMarket = await groupOrdersByMarket('0x63E8c7C149556D5f34F833419A287bb9Ef81487f');
Object.entries(byMarket).forEach(([coin, data]) => {
console.log(`\n${coin}:`);
console.log(` ${data.buy.length} buy orders (${data.totalBuySize} total)`);
console.log(` ${data.sell.length} sell orders (${data.totalSellSize} total)`);
});
5. Order Management Dashboard#
Create a comprehensive order dashboard:
async function getOrderDashboard(userAddress) {
const orders = await getOpenOrders(userAddress);
const now = Date.now();
const stats = {
totalOrders: orders.length,
buyOrders: orders.filter(o => o.side === 'B').length,
sellOrders: orders.filter(o => o.side === 'A').length,
markets: [...new Set(orders.map(o => o.coin))],
partiallyFilled: orders.filter(o => o.sz !== o.origSz).length,
averageAge: orders.reduce((sum, o) => sum + (now - o.timestamp), 0) / orders.length / (1000 * 60 * 60)
};
console.log('=== Order Dashboard ===');
console.log(`Total Orders: ${stats.totalOrders}`);
console.log(` Buy: ${stats.buyOrders}`);
console.log(` Sell: ${stats.sellOrders}`);
console.log(`Markets: ${stats.markets.join(', ')}`);
console.log(`Partially Filled: ${stats.partiallyFilled}`);
console.log(`Average Age: ${stats.averageAge.toFixed(1)} hours`);
return stats;
}
Error Handling#
Common Errors#
| Error | Cause | Solution |
|---|---|---|
401 Unauthorized | Invalid API key | Verify your API key is correct |
400 Bad Request | Missing or invalid user address | Ensure valid Ethereum address format |
429 Too Many Requests | Rate limit exceeded | Implement request throttling |
500 Internal Server Error | Server issue | Retry with exponential backoff |
Error Response Example#
{
"error": "Missing required parameter: user",
"code": "MISSING_PARAMETER"
}
Robust Error Handling#
async function safeGetOpenOrders(userAddress, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await getOpenOrders(userAddress);
} catch (error) {
if (error.response?.status === 429) {
// Rate limit - exponential backoff
await new Promise(r => setTimeout(r, Math.pow(2, i) * 1000));
} else if (error.response?.status === 400) {
throw new Error('Invalid user address');
} else if (i === maxRetries - 1) {
throw error;
}
}
}
}
Best Practices#
- Poll at appropriate intervals — Poll every 5-10 seconds for active trading, less frequently for monitoring
- Handle empty arrays — User may have no open orders
- Validate addresses — Ensure user addresses are valid Ethereum addresses
- Track order IDs — Use order IDs to track specific orders across polls
- Monitor fill rates — Alert when orders are partially filled
Related Endpoints#
- clearinghouseState — Get account state with positions
- userFees — Get user fee rates
- frontendOpenOrders — Get formatted orders for frontend display
- meta — Get trading pair metadata
Access real-time Hyperliquid order data with Dwellir's HyperCore Info Endpoint. Get your API key →