Quick Start Guide
Everything you need to integrate the Hyperlight API — from your first API key to production.
Getting Your API Key
Create an account and get your API key in under a minute. Every key is prefixed with hlt_ and shown exactly once — save it somewhere safe.
Register via API
Send a single POST request to create your account. The response includes a JWT token for dashboard access and your first API key.
curl -X POST https://api.hyperlightapi.xyz/api/v1/auth/register \
-H "Content-Type: application/json" \
-d '{
"email": "you@example.com",
"password": "your-secure-password",
"tos_accepted": true
}'Register via Website
Prefer a UI? Visit hyperlightapi.xyz/auth/signup to create your account with email or GitHub OAuth. Your API key appears on the dashboard after signup.
Understanding Your API Key
All Hyperlight API keys start with the prefix hlt_ followed by 48 hex characters. Example: hlt_7kT9BxQ4mN2pR8vL1wX5yZ3aD6fG9hJ0kS.
The server never stores your full key — only its SHA-256 hash. If you lose your key, you cannot recover it. Create a new one from your dashboard or via the API.
Authentication
Pass your API key via header, bearer token, or query parameter. WebSocket connections authenticate with the first message.
X-Api-Key Header (Recommended)
The simplest and most secure method for REST calls.
curl https://api.hyperlightapi.xyz/api/v1/orderbook/0 \ -H "X-Api-Key: hlt_your_key_here"
Authorization Bearer
Works with both API keys and JWT tokens. Useful when your HTTP client already sets an Authorization header.
# With API key curl https://api.hyperlightapi.xyz/api/v1/orderbook/0 \ -H "Authorization: Bearer hlt_your_key_here" # With JWT (from login/register) curl https://api.hyperlightapi.xyz/api/v1/keys \ -H "Authorization: Bearer eyJhbG..."
Query Parameter
Pass your key as a query parameter. Convenient for quick testing but avoid in production — URLs can appear in logs and browser history.
curl "https://api.hyperlightapi.xyz/api/v1/orderbook/0?api_key=hlt_your_key_here"
WebSocket Authentication
The first message on any WebSocket connection must be an auth message. You have 10 seconds to authenticate before the server closes the connection.
// Client sends:
{"type": "auth", "api_key": "hlt_your_key_here"}
// Server responds:
{"type": "authenticated", "tier": "free", "max_subscriptions": 5}Your First API Call
Start with a health check, then fetch live data. Every response follows the same envelope format.
Health Check (No Auth Required)
Verify the API is reachable. No authentication needed.
curl https://api.hyperlightapi.xyz/health
Get an Orderbook
Fetch the current orderbook for market 0 (ETH-PERP). Data is served from Redis cache with sub-second freshness.
curl https://api.hyperlightapi.xyz/api/v1/orderbook/0 \ -H "X-Api-Key: hlt_your_key_here"
Batch Query Accounts
Query multiple accounts in a single request — the signature Hyperlight feature. Lighter's native API only supports one account per request.
curl -X POST https://api.hyperlightapi.xyz/api/v1/accounts/batch \
-H "X-Api-Key: hlt_your_key_here" \
-H "Content-Type: application/json" \
-d '{"accounts": [0, 1, 2, 3, 4], "by": "index"}'Understanding the Response Envelope
Every response follows the same structure. Check success first, then read data. The meta object includes a unique request_id for tracing.
{
"success": true,
"data": { ... },
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": 1706745600000,
"total": 100,
"limit": 50,
"offset": 0
}
}REST Endpoints by Category
43 REST endpoints organized by function. All authenticated endpoints require an API key unless noted.
Accounts & Batch Queries
Batch endpoints accept up to your tier's batch size limit (5 for Free, up to 5,000 for Enterprise).
| Method | Path | Description |
|---|---|---|
| POST | /api/v1/accounts/batch | Batch query accounts (positions, orders, fills) |
| POST | /api/v1/accounts/batch/fills | Batch fills across accounts |
| POST | /api/v1/accounts/batch/positions | Batch positions across accounts |
| POST | /api/v1/accounts/batch/liquidations | Batch liquidation events |
| GET | /api/v1/accounts/:id/positions | Single account positions |
| GET | /api/v1/accounts/:id/fills | Single account fill history |
| GET | /api/v1/accounts/:id/pnl | PnL snapshot history |
| GET | /api/v1/accounts/:id/liquidation-risk | Liquidation risk estimate |
Orderbook
| Method | Path | Description |
|---|---|---|
| GET | /api/v1/orderbook/:market_id | Current orderbook (Redis-cached, sub-second) |
| GET | /api/v1/orderbook/:market_id/depth | Aggregated depth at custom price levels |
| GET | /api/v1/orderbook/:market_id/snapshots | Historical orderbook at any point in time |
Trades & Candles
| Method | Path | Description |
|---|---|---|
| GET | /api/v1/trades/by-time | Trades within arbitrary time ranges |
| GET | /api/v1/trades/aggregate | VWAP + volume aggregation at custom intervals |
| GET | /api/v1/candles | OHLCV candles (1m to 1w resolution) |
Liquidations
| Method | Path | Description |
|---|---|---|
| GET | /api/v1/liquidations/by-time | Liquidation events in a time range |
| GET | /api/v1/liquidations/recent | Recent liquidations across all markets |
| GET | /api/v1/liquidation-heatmap/:market_id | Liquidation level heatmap |
| GET | /api/v1/liquidation-heatmap/:market_id/cascade | Cascade effect analysis |
Funding Rates
| Method | Path | Description |
|---|---|---|
| GET | /api/v1/funding-rates | Current funding rates for all markets |
| GET | /api/v1/funding-rates/history | Historical funding rate data |
Exchange Analytics
| Method | Path | Description |
|---|---|---|
| GET | /api/v1/exchange/stats | 24h volume, open interest, price changes |
| GET | /api/v1/exchange/metrics | Historical exchange-level metrics |
| GET | /api/v1/markets/:market_id/top-accounts | Top accounts by position size (tier-limited) |
| GET | /api/v1/exchange/top-accounts | Top accounts exchange-wide by total notional (tier-limited) |
Data Lake
Parquet exports for backtesting and analytics. Available on paid tiers.
| Method | Path | Description |
|---|---|---|
| GET | /api/v1/data-lake/exports | List available Parquet exports |
| GET | /api/v1/data-lake/download/:export_id | Pre-signed S3 download URL |
Signal Engine (Custom Alerts)
Create rules that trigger webhooks based on market conditions. See the Signal Engine section below for full details.
| Method | Path | Description |
|---|---|---|
| POST | /api/v1/signals | Create alert rule (JSON DSL) |
| GET | /api/v1/signals | List your alerts |
| GET | /api/v1/signals/:signal_id | Get alert details |
| PATCH | /api/v1/signals/:signal_id | Update alert rule |
| DELETE | /api/v1/signals/:signal_id | Delete alert |
| GET | /api/v1/signals/:signal_id/backtest | Backtest against historical data |
API Key Management
| Method | Path | Description |
|---|---|---|
| POST | /api/v1/keys | Create new API key |
| GET | /api/v1/keys | List your keys (prefix only) |
| PATCH | /api/v1/keys/:key_id | Update key (name, IP allowlist) |
| DELETE | /api/v1/keys/:key_id | Revoke key |
| GET | /api/v1/keys/:key_id/usage | Hourly usage breakdown |
Auth, Billing & Health
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /health | No | Service health check |
| GET | /status | No | Lighter network status |
| POST | /api/v1/auth/register | No | Register and get API key + JWT |
| POST | /api/v1/auth/login | No | Login and get JWT token |
| POST | /api/v1/billing/checkout | JWT | Create Stripe checkout session |
| POST | /api/v1/billing/portal | JWT | Create Stripe customer portal |
WebSocket Streaming
Connect to the WebSocket endpoint for real-time orderbook updates, enriched trades, whale alerts, and liquidation heatmaps.
Connecting & Authenticating
Connect to the WebSocket endpoint and send an auth message as your first message. The server responds with your tier and subscription limit.
# Install: npm install -g wscat
wscat -c wss://api.hyperlightapi.xyz/ws
# Once connected, send:
{"type": "auth", "api_key": "hlt_your_key_here"}Available Channels
Subscribe and unsubscribe to channels by sending JSON messages. Replace {market_id} with the numeric market ID (0 = ETH-PERP).
| Channel | Description |
|---|---|
| order_book/{market_id} | Live orderbook updates (direct upstream proxy) |
| enriched_order_book/{market_id} | Orderbook with account attribution and whale flags |
| enriched_trade/{market_id} | Trades with account attribution |
| trade/{market_id} | Raw trade updates |
| alert/{market_id} | Large order and whale activity alerts |
| liquidation_heatmap/{market_id} | Liquidation level heatmap updates |
// Subscribe
{"type": "subscribe", "channel": "trade/0"}
// → {"type": "subscribed", "channel": "trade/0"}
// Unsubscribe
{"type": "unsubscribe", "channel": "trade/0"}
// → {"type": "unsubscribed", "channel": "trade/0"}Data Message Format
Channel data arrives in a standard envelope with the channel name and a server timestamp.
{
"type": "trade_update",
"channel": "trade/0",
"trade": {
"trade_id": 12345,
"price": "3200.50",
"size": "2.5",
"is_maker_ask": true,
"ask_account_id": 42,
"bid_account_id": 99,
"market_id": 0,
"timestamp": 1706700000123
}
}Connection Limits
WebSocket connections are rate-limited to 30 messages/second (burst of 60). After 3 consecutive violations, the connection is closed. The server sends a ping every 30 seconds — your client must respond with a pong within 10 seconds.
Backtesting Replay
Replay historical orderbook snapshots and trades via WebSocket at 0.1x–100x speed. Point your trading bot at the replay endpoint and test strategies against real market data.
Starting a Replay
Connect to the /ws/replay endpoint, authenticate, then send a replay command with your desired market, time range, and playback speed.
import asyncio, websockets, json
async def replay():
async with websockets.connect("wss://api.hyperlightapi.xyz/ws/replay") as ws:
# Authenticate
await ws.send(json.dumps({
"type": "auth",
"api_key": "hlt_your_key_here"
}))
print(json.loads(await ws.recv())) # authenticated
# Start replay: ETH-PERP, 1 hour, 10x speed
await ws.send(json.dumps({
"type": "replay",
"market_id": 0,
"start": "2026-01-01T00:00:00Z",
"end": "2026-01-01T01:00:00Z",
"speed": 10.0
}))
async for msg in ws:
event = json.loads(msg)
if event["type"] == "replay_event":
print(f"[{event['event_type']}] {event['data']}")
elif event["type"] == "replay_complete":
print(f"Done! {event['events_sent']} events")
break
asyncio.run(replay())Playback Controls
Pause, resume, or stop a replay at any time. Only one replay can be active per connection — send stop before starting another.
{"type": "pause"} // → {"type": "replay_paused"}
{"type": "resume"} // → {"type": "replay_resumed"}
{"type": "stop"} // → {"type": "replay_stopped"}Replay Event Types
Events arrive in chronological order, interleaving trades and orderbook snapshots. Each event has the original timestamp (ts) and the wall-clock replay timestamp (replay_ts).
{
"type": "replay_event",
"event_type": "trade",
"data": {
"market_id": 0,
"trade_id": 12345,
"price": "3200.50",
"size": "2.5",
"side": "buy"
},
"ts": 1717200330000,
"replay_ts": 1706700050000
}Replay Tier Limits
The maximum replay window and number of concurrent replays depend on your tier.
| Tier | Max Replay Window | Concurrent Replays |
|---|---|---|
| Free | Disabled | 0 |
| Starter | 7 days | 2 |
| Growth | 30 days | 5 |
| Scale | 90 days | 10 |
| Enterprise | Unlimited | Unlimited |
Signal Engine (Custom Alerts)
Define alert rules using a JSON DSL. When market conditions match, Hyperlight sends a webhook to your endpoint with HMAC-SHA256 signing.
Creating a Signal
Define a rule, a delivery channel (webhook URL + secret), and optional cooldown. The rule evaluates in real-time against live market data.
curl -X POST https://api.hyperlightapi.xyz/api/v1/signals \
-H "Authorization: Bearer <your_jwt_token>" \
-H "Content-Type: application/json" \
-d '{
"name": "ETH price alert",
"market_id": 0,
"rule_definition": {
"conditions": [
{"field": "trade_price", "op": "gt", "value": 4000}
],
"logic": "AND"
},
"delivery_channels": [
{
"type": "webhook",
"url": "https://your-app.com/webhook",
"secret": "your-hmac-secret-min-16-chars"
}
],
"cooldown_secs": 300
}'Rule DSL Reference
Rules are JSON objects with conditions (each having a field, op, and value), combined with AND/OR logic. Available fields: trade_price, trade_size, trade_notional, orderbook_spread, bid_depth, ask_depth, funding_rate, heatmap_long_at_risk, heatmap_short_at_risk.
| Operator | Description | Example |
|---|---|---|
| gt | Field > value | {"field": "trade_price", "op": "gt", "value": 4000} |
| lt | Field < value | {"field": "trade_price", "op": "lt", "value": 3000} |
| gte | Field >= value | {"field": "trade_size", "op": "gte", "value": 100} |
| lte | Field <= value | {"field": "orderbook_spread", "op": "lte", "value": 0.01} |
| eq | Field == value | {"field": "funding_rate", "op": "eq", "value": 0} |
| ne | Field != value | {"field": "funding_rate", "op": "ne", "value": 0} |
| crosses_above | Field crosses above value | {"field": "trade_price", "op": "crosses_above", "value": 4000} |
| crosses_below | Field crosses below value | {"field": "trade_price", "op": "crosses_below", "value": 3000} |
{
"conditions": [
{"field": "trade_price", "op": "gt", "value": 4000},
{"field": "trade_size", "op": "gt", "value": 50}
],
"logic": "AND"
}Backtesting a Signal
Test your rule against historical data before activating it. The backtest endpoint returns how many times the rule would have triggered.
curl "https://api.hyperlightapi.xyz/api/v1/signals/{signal_id}/backtest?start=1767225600000&end=1767312000000" \
-H "Authorization: Bearer <your_jwt_token>"Rate Limiting & Tiers
Rate limits are enforced per API key. Every response includes rate limit headers so you can track your usage.
Rate Limit Headers
Every response includes these headers:
| Header | Description |
|---|---|
| X-RateLimit-Limit | Your tier's max requests per minute |
| X-RateLimit-Remaining | Requests remaining in current window |
| X-RateLimit-Reset | UNIX timestamp when the window resets |
| Retry-After | Seconds to wait (only on 429 responses) |
Tier Comparison
| Tier | Price | Rate Limit | Batch Size | Credits/Month | WS Connections |
|---|---|---|---|---|---|
| Free | Free | 30/min | 5 | 75K | 1 |
| Starter | $199 | 300/min | 200 | 750K | 50 |
| Growth | $849 | 3,000/min | 1,000 | 5M | 500 |
| Scale | $1,799 | 30,000/min | 2,500 | 25M | 1,000 |
| Enterprise | Custom | Unlimited | 5,000 | Unlimited | Unlimited |
Handling 429 Responses
When you exceed your rate limit, the API returns HTTP 429. Use the Retry-After header to know how long to wait.
import time, requests
def api_call(url, headers):
resp = requests.get(url, headers=headers)
if resp.status_code == 429:
wait = int(resp.headers.get("Retry-After", 60))
print(f"Rate limited. Waiting {wait}s...")
time.sleep(wait)
return api_call(url, headers) # retry
return resp.json()Verification Checklist
Run through these steps to confirm your integration is working correctly.
Step-by-Step Verification
Run each command and verify you get the expected response. Replace hlt_your_key_here with your actual API key.
# 1. Health check (no auth)
curl -s https://api.hyperlightapi.xyz/health | jq .status
# Expected: "ok"
# 2. Orderbook (auth required)
curl -s https://api.hyperlightapi.xyz/api/v1/orderbook/0 \
-H "X-Api-Key: hlt_your_key_here" | jq .success
# Expected: true
# 3. Trades in time range
curl -s "https://api.hyperlightapi.xyz/api/v1/trades/by-time?market_id=0&start=2026-01-01T00:00:00Z&end=2026-01-02T00:00:00Z&limit=5" \
-H "X-Api-Key: hlt_your_key_here" | jq '.data.trades | length'
# Expected: > 0
# 4. Batch query 5 accounts
curl -s -X POST https://api.hyperlightapi.xyz/api/v1/accounts/batch \
-H "X-Api-Key: hlt_your_key_here" \
-H "Content-Type: application/json" \
-d '{"accounts": [0,1,2,3,4], "by": "index"}' | jq '.data.accounts | length'
# Expected: up to 5
# 5. Current funding rates
curl -s https://api.hyperlightapi.xyz/api/v1/funding-rates \
-H "X-Api-Key: hlt_your_key_here" | jq '.data.rates | length'
# Expected: > 0
# 6. Exchange stats
curl -s https://api.hyperlightapi.xyz/api/v1/exchange/stats \
-H "X-Api-Key: hlt_your_key_here" | jq .success
# Expected: true
# 7. Check rate limit headers
curl -sI https://api.hyperlightapi.xyz/api/v1/orderbook/0 \
-H "X-Api-Key: hlt_your_key_here" | grep -i x-ratelimit
# Expected: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset
# 8. WebSocket (requires wscat: npm i -g wscat)
# wscat -c wss://api.hyperlightapi.xyz/ws
# > {"type":"auth","api_key":"hlt_your_key_here"}
# < {"type":"authenticated",...}
# > {"type":"subscribe","channel":"order_book/0"}
# < {"type":"subscribed","channel":"order_book/0"}Error Handling
All errors follow the standard response envelope with a code and human-readable message.
Error Codes
| Code | HTTP Status | Description |
|---|---|---|
| unauthorized | 401 | Missing or invalid API key |
| forbidden | 403 | Key expired, disabled, or IP not allowed |
| bad_request | 400 | Invalid query parameters |
| not_found | 404 | Resource not found |
| rate_limit_exceeded | 429 | Tier rate limit exceeded |
| batch_too_large | 400 | Batch size exceeds tier limit |
| internal_error | 500 | Server error |
| upstream_error | 502 | Lighter API unavailable |
Error Response Example
{
"success": false,
"data": {
"code": "rate_limit_exceeded",
"message": "rate limit exceeded"
},
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": 1706745600000
}
}Production Best Practices
Tips for building reliable integrations.
Recommendations
Use batch endpoints instead of looping: A single POST /api/v1/accounts/batch replaces hundreds of individual requests and costs only 25 credits regardless of batch size.
Monitor rate limit headers: Track X-RateLimit-Remaining and back off before you hit 429. This is more efficient than retrying after the fact.
Implement WebSocket reconnection: Connections can drop due to network issues or server restarts. Use exponential backoff (1s, 2s, 4s, 8s, max 30s) when reconnecting.
Rotate API keys periodically: Create a new key, update your services, then delete the old one. Hyperlight supports multiple active keys per account.
Use IP allowlists: Lock your production keys to specific IP addresses via PATCH /api/v1/keys/:key_id with an allowed_ips array.
Cache responses where appropriate: Orderbook and funding rate data is cached server-side with sub-second freshness. For lower-frequency use cases, cache locally to avoid unnecessary requests.
Use the health endpoint for monitoring: Add GET /health to your uptime monitoring. It checks all dependencies (PostgreSQL, Redis, Lighter API).
Ready to get started?