luziadev

Official Python SDK for the Luzia cryptocurrency pricing API.

Requires Python 3.10+

Installation

 
pip install luziadev
# or
uv add luziadev

For WebSocket streaming support, install with the optional dependency:

 
pip install luziadev[websocket]
# or
uv add luziadev[websocket]

Quick Start

 
import asyncio
from luziadev import Luzia
async def main():
async with Luzia("lz_your_api_key") as client:
# List all supported exchanges
exchanges = await client.exchanges.list()
print(exchanges)
# [Exchange(id='binance', name='Binance', status='operational', ...)]
# Get a single ticker
ticker = await client.tickers.get("binance", "BTC/USDT")
print(f"BTC/USDT: ${ticker.last}")
# Get multiple tickers
result = await client.tickers.list_filtered(
exchange="binance",
symbols=["BTC/USDT", "ETH/USDT"],
)
for t in result.tickers:
print(f"{t.symbol}: ${t.last}")
# Get markets with filters
markets = await client.markets.list("binance", quote="USDT")
# Get historical OHLCV candles
ohlcv = await client.history.get(
"binance", "BTC/USDT",
interval="1h",
limit=24,
)
print(f"Last close: ${ohlcv.candles[-1].close}")
asyncio.run(main())

Client Lifecycle

The SDK uses httpx for async HTTP requests. Use the async context manager to ensure connections are properly closed.

 
# Option 1: Async context manager (recommended)
async with Luzia("lz_your_api_key") as client:
ticker = await client.tickers.get("binance", "BTC/USDT")
# Option 2: Manual lifecycle
client = Luzia("lz_your_api_key")
try:
ticker = await client.tickers.get("binance", "BTC/USDT")
finally:
await client.close()

Configuration

Customize the SDK behavior with these configuration options.

 
from luziadev import Luzia, RetryOptions
client = Luzia(
# Required: Your API key
api_key="lz_xxxxx",
# Optional: Custom base URL (default: https://api.luzia.dev)
base_url="http://localhost:3000",
# Optional: Request timeout in seconds (default: 30)
timeout=10,
# Optional: Retry configuration
retry=RetryOptions(
max_retries=3, # Number of retry attempts (default: 3)
initial_delay_ms=1000, # Initial delay before first retry (default: 1000)
max_delay_ms=30000, # Maximum delay between retries (default: 30000)
backoff_multiplier=2.0, # Multiplier for exponential backoff (default: 2)
jitter=True, # Add random jitter to delays (default: True)
),
)

API Reference

Exchanges

 
# List all supported exchanges
exchanges = await client.exchanges.list()

Tickers

 
# Get a single ticker
ticker = await client.tickers.get("binance", "BTC/USDT")
# List all tickers for an exchange
result = await client.tickers.list("binance", limit=50, offset=0)
print(f"Found {result.total} tickers")
# Get specific tickers across exchanges
result = await client.tickers.list_filtered(
exchange="binance", # Optional: filter by exchange
symbols=["BTC/USDT", "ETH/USDT"], # Optional: filter by symbols
limit=100,
offset=0,
)

Markets

 
# List markets for an exchange
result = await client.markets.list(
"binance",
base="BTC", # Optional: filter by base currency
quote="USDT", # Optional: filter by quote currency
active=True, # Optional: filter by active status
limit=100,
offset=0,
)

History (OHLCV Candles)

Fetch historical OHLCV candlestick data for any supported centralized-exchange pair. Useful for charting, backtesting, and performance analysis. DEX markets (Raydium, Orca, Uniswap, Curve) including tokenized stocks and RWAs are not yet covered by this endpoint.

 
# Get 24h of hourly candles (default)
result = await client.history.get("binance", "BTC/USDT")
# Specify interval and limit
result = await client.history.get(
"binance", "ETH/USDT",
interval="15m", # "1m" | "5m" | "15m" | "1h" | "1d"
limit=96, # Number of candles (max: 500)
)
# Specify a custom time range
import time
result = await client.history.get(
"binance", "BTC/USDT",
interval="1d",
start=int((time.time() - 30 * 24 * 3600) * 1000), # 30 days ago
end=int(time.time() * 1000),
)
# Each candle contains OHLCV data
for candle in result.candles:
print({
"timestamp": candle.timestamp, # Candle open time (RFC 3339)
"open": candle.open,
"high": candle.high,
"low": candle.low,
"close": candle.close,
"volume": candle.volume, # Base currency volume
"quote_volume": candle.quote_volume,
"trades": candle.trades, # Number of trades
})
IntervalDescription
1m1 minute candles
5m5 minute candles
15m15 minute candles
1h1 hour candles
1d1 day candles
TierMax Lookback
Free30 days
Pro90 days

WebSocket Streaming

Stream real-time ticker updates over WebSocket. Requires the websocket extra and a Pro or Enterprise tier API key.

 
import asyncio
from luziadev import Luzia
async def main():
client = Luzia("lz_your_api_key")
ws = client.create_websocket()
ws.on("connected", lambda data: print(f"Connected! Max subs: {data['limits']['maxSubscriptions']}"))
ws.on("ticker", lambda data: print(f"{data['data']['symbol']}: ${data['data']['last']}"))
ws.on("error", lambda data: print(f"Error: {data['message']}"))
ws.on("reconnecting", lambda data: print(f"Reconnecting (attempt {data['attempt']})..."))
await ws.connect()
ws.subscribe(["ticker:binance:BTC-USDT", "ticker:binance:ETH-USDT"])
# Keep running
try:
await asyncio.sleep(3600)
finally:
ws.disconnect()
await client.close()
asyncio.run(main())

WebSocket Configuration

 
ws = client.create_websocket(
auto_reconnect=True, # Auto-reconnect on disconnect (default: True)
max_reconnect_attempts=10, # Max reconnect attempts (default: 10)
reconnect_delay_ms=1000, # Initial reconnect delay (default: 1000)
max_reconnect_delay_ms=30000, # Max reconnect delay (default: 30000)
heartbeat_interval_ms=30000, # Heartbeat ping interval (default: 30000)
)
EventDescription
connectedConnected to the WebSocket server
tickerReceived a ticker price update
subscribedSuccessfully subscribed to a channel
unsubscribedSuccessfully unsubscribed from a channel
errorAn error occurred
reconnectingAttempting to reconnect
disconnectedDisconnected from the server

Error Handling

The SDK uses a single LuziaError class with a code property to distinguish error types. Use Python's match statement for clean error handling.

 
from luziadev import Luzia, LuziaError
async with Luzia("lz_your_api_key") as client:
try:
ticker = await client.tickers.get("invalid", "BTC/USDT")
except LuziaError as e:
match e.code:
case "auth":
print("Invalid API key")
case "rate_limit":
print(f"Rate limited. Retry after {e.retry_after}s")
case "not_found":
print("Resource not found")
case "validation":
print(f"Invalid request parameters: {e.details}")
case "server":
print("Server error (exchange may be temporarily unavailable)")
case "network":
print(f"Network error: {e}")
case "timeout":
print(f"Request timed out after {e.timeout_ms}ms")

Checking Error Types

 
from luziadev import is_luzia_error, is_retryable_error
if is_luzia_error(error):
print(f"Luzia error: {error}")
if is_retryable_error(error):
print("This error can be retried")
CodeDescription
authInvalid or missing API key
rate_limitRate limit exceeded
not_foundResource not found (exchange, market, or ticker)
validationInvalid request parameters
serverServer error (exchange may be temporarily unavailable)
networkNetwork connectivity issue
timeoutRequest timed out

Rate Limit Information

Access rate limit information from the most recent request.

 
ticker = await client.tickers.get("binance", "BTC/USDT")
info = client.rate_limit_info
if info:
print(f"Requests remaining: {info.remaining}/{info.limit}")
print(f"Resets at: {info.reset}")
# Free tier also has daily limits
if info.daily_limit:
print(f"Daily remaining: {info.daily_remaining}/{info.daily_limit}")

Automatic Retries

The SDK automatically retries requests on certain errors when retry options are configured.

Retryable Errors

  • Rate limit errors (429) - respects Retry-After header
  • Timeout errors (408)
  • Server errors (500, 502, 503, 504)
  • Network errors

Non-Retryable Errors

  • Bad request (400)
  • Unauthorized (401)
  • Forbidden (403)
  • Not found (404)

Types

All types are exported from the main package and are fully type-annotated for IDE support.

 
from luziadev import (
Exchange,
Ticker,
Market,
MarketListResponse,
OHLCVCandle,
OHLCVResponse,
TickerListResponse,
RateLimitInfo,
RetryOptions,
RetryContext,
LuziaError,
ErrorCode,
LuziaWebSocket,
)

Ready to get started?

Create an account to get your API key and start using the SDK.