Quickstart
From an empty environment to trades, a rebuilt order book, a live stream and a Parquet file. Every step shows the Python SDK and the same request over plain HTTP.
You need Python 3.9 or later and an API key. A test key is enough for this page: it returns a fixed 24-hour sample, Hyperliquid BTC-PERP, ETH-PERP and SOL-PERP on September 15, 2026 (UTC), across every dataset including L4 and extended fields.
1. Install the SDK
pip install fdc
python -c "import fdc; print(fdc.__version__)"The package depends on httpx, websockets and pyarrow. pandas and Polars are optional; install either to use .to_pandas() or .to_polars().
2. Get a test key
Test keys are issued from the account console, which opens with Phase 1. If you have not registered yet, pre-register and we will send console access with your early-access invitation. A key looks like fdc_test_7Hq2Lx9WbN4vR1cK8sTe3YpD6fMz0aJg.
Put the key in the environment rather than in code. The SDK reads FDC_API_KEY when no api_key argument is given.
export FDC_API_KEY=fdc_test_7Hq2Lx9WbN4vR1cK8sTe3YpD6fMz0aJg403 test_key_out_of_range. Live keys (fdc_live_) work with the same code unchanged. Key types and scopes are on Authentication.3. Pull trades
One hour of Hyperliquid BTC perpetual trades. start is inclusive and end is exclusive; both accept ISO 8601 strings or int64 nanoseconds.
from fdc import Client
fdc = Client() # reads FDC_API_KEY
trades = fdc.trades(
venue="hyperliquid",
symbol="BTC-PERP",
start="2026-09-15T14:00:00Z",
end="2026-09-15T15:00:00Z",
).to_pandas()
print(trades[["ts_exchange", "price", "size", "side"]].head())
print(len(trades), "trades")curl -s https://api.financedatacloud.com/v1/trades \
-H "Authorization: Bearer $FDC_API_KEY" \
-G \
-d venue=hyperliquid \
-d symbol=BTC-PERP \
-d start=2026-09-15T14:00:00Z \
-d end=2026-09-15T15:00:00Z \
-d limit=1000The REST response wraps rows in a data array. When more rows exist, next_cursor is set; pass it back as cursor to get the next page. The SDK follows cursors for you.
{
"data": [
{"venue":"hyperliquid","symbol":"BTC-PERP","venue_symbol":"BTC",
"ts_exchange":1789480800043000000,"ts_capture":1789480800047915320,
"seq":1094089331232771,"source":"fdc_capture","region":"apne1",
"price":"104291","size":"0.0158","side":"sell","trade_id":"812773664018202", ...}
],
"next_cursor": "eyJzIjoxMDk0MDg5MzMxMjMyNzcxLCJpIjoxMDAwfQ"
}Prices and sizes are strings in JSON and decimal.Decimal in the SDK, so nothing is rounded on the way. Column meanings are on Schema reference.
4. Rebuild an L2 order book
Ask for depth="L2" with a start time and the first rows you receive are a snapshot of the book as of start, followed by deltas. Each delta carries the absolute size at a price level; size 0 removes the level. Apply every row of a message (up to is_last) before reading the book.
from decimal import Decimal
from fdc import Client
fdc = Client()
book = {"bid": {}, "ask": {}}
new_message = True
for r in fdc.book(venue="hyperliquid", symbol="BTC-PERP", depth="L2",
start="2026-09-15T14:30:00Z", end="2026-09-15T14:31:00Z"):
if new_message and r["is_snapshot"]:
book = {"bid": {}, "ask": {}} # a snapshot replaces the book
levels = book[r["side"]]
price, size = Decimal(r["price"]), Decimal(r["size"])
if size == 0:
levels.pop(price, None)
else:
levels[price] = size
new_message = r["is_last"]
bids = sorted(book["bid"].items(), reverse=True)[:5]
asks = sorted(book["ask"].items())[:5]
print("spread", asks[0][0] - bids[0][0])curl -s https://api.financedatacloud.com/v1/book/l2 \
-H "Authorization: Bearer $FDC_API_KEY" \
-G \
-d venue=hyperliquid \
-d symbol=BTC-PERP \
-d start=2026-09-15T14:30:00Z \
-d end=2026-09-15T14:31:00Z \
-d limit=5000
# first page begins with is_snapshot=true rows; follow next_cursor for deltasThe full set of rules, including truncated venues, checksums and L3 replay, is on Order book depth.
5. Subscribe to a live stream
Add live=True and the SDK backfills from start, then switches to the WebSocket stream without a gap or a duplicate. The handover is done on seq, so you can restart a consumer from its last processed timestamp. With a test key the stream replays the sample day at recorded speed.
from fdc import Client
fdc = Client()
for t in fdc.trades(venue="hyperliquid", symbol="BTC-PERP",
start="2026-09-15T14:55:00Z", live=True):
lag_ms = (t["ts_capture"] - t["ts_exchange"]) / 1e6
print(t["side"], t["price"], t["size"], f"{lag_ms:.1f} ms")# curl cannot hold a WebSocket open; websocat works the same way
websocat -H "Authorization: Bearer $FDC_API_KEY" \
wss://stream.financedatacloud.com/v1
# then send:
{"op":"subscribe","channel":"trades","venue":"hyperliquid","symbol":"BTC-PERP"}Live access needs the live scope, which comes with Desk and Enterprise keys and with every test key. Channel names match dataset names (trades, book_l2, book_l3, funding and so on); message envelopes and heartbeats are on WebSocket.
6. Export to Parquet
For anything larger than a few hours, download files instead of paging through JSON. fdc.download writes one Parquet file per symbol per UTC day, in the same layout as the S3 archive, and returns the paths.
import polars as pl
from fdc import Client
fdc = Client()
paths = fdc.download(
dataset="trades",
venue="hyperliquid",
symbol="BTC-PERP",
start="2026-09-15",
end="2026-09-16",
format="parquet",
path="./fdc-data",
)
# ['./fdc-data/trades/venue=hyperliquid/date=2026-09-15/BTC-PERP.parquet']
df = pl.read_parquet(paths[0])
print(df.schema["price"]) # Decimal(precision=38, scale=18)curl -s https://api.financedatacloud.com/v1/trades \
-H "Authorization: Bearer $FDC_API_KEY" \
-G \
-d venue=hyperliquid \
-d symbol=BTC-PERP \
-d start=2026-09-15 \
-d end=2026-09-16 \
-d format=parquet \
-o BTC-PERP-2026-09-15.parquetformat accepts json (default), csv and parquet. Parquet responses are not paginated: one request returns one file per UTC day, up to 31 days per request. For long ranges, use Bulk S3.
Next steps
- Schema reference for every column you just pulled.
- Timestamps & clocks before you join venues or measure latency.
- Python SDK for the full method reference.
- Rate limits before you put a REST client into production.