Overview
The /v1/data/download endpoint returns time-limited signed URLs
for Parquet files stored in Google Cloud Storage. Each file contains one hour of
data for a single message type. Signed URLs expire after the requested duration
(default 12 hours) and can be used directly with DuckDB, pandas, or any HTTP client.
Authentication requires an API key with datasets:read scope,
passed via the X-API-Key header. Keys are scoped to specific feeds
and date ranges.
Available Feeds
| Feed | Stream | Message Types |
|---|---|---|
kalshi | crypto | ticker trade market_lifecycle_v2 |
kraken-futures | futures | ticker trade |
polymarket | markets | last_trade_price price_change book best_bid_ask |
API Reference
/v1/data/download Query Parameters
| Parameter | Required | Description |
|---|---|---|
feed | Yes | Feed name: kalshi, kraken-futures, or polymarket |
from | Yes | Start date in YYYY-MM-DD format |
to | Yes | End date in YYYY-MM-DD format |
type | No | Filter by message type (e.g. ticker, trade) |
expires | No | Signed URL expiry duration. Default 12h, range 1–12h |
Constraints
- Maximum 7-day date range per request
- Maximum 200 files per response
- API key must be authorized for the requested feed
- Key date range restrictions are enforced (dates are clamped to the key's allowed range)
Response
{
"feed": "kalshi",
"from": "2026-02-15",
"to": "2026-02-15",
"type": null,
"files": [
{
"path": "kalshi/crypto/2026-02-15/ticker_0000.parquet",
"name": "ticker_0000.parquet",
"type": "ticker",
"hour": "0000",
"bytes": 1234567,
"signedUrl": "https://storage.googleapis.com/...",
"expiresAt": "2026-02-16T00:00:00.000Z"
}
],
"expiresIn": "12h"
} Error Responses
| Status | Reason |
|---|---|
400 | Invalid or missing parameters (bad date format, unknown feed, range exceeds 7 days) |
403 | API key not authorized for the requested feed or date range |
503 | GCS backend not configured on the server |
curl Examples
List available feeds:
curl -H "X-API-Key: $API_KEY" https://api.varshtat.com/v1/data/feeds Get signed URLs for one day of Kalshi data:
curl -H "X-API-Key: $API_KEY" \
"https://api.varshtat.com/v1/data/download?feed=kalshi&from=2026-02-15&to=2026-02-15" Filter by message type:
curl -H "X-API-Key: $API_KEY" \
"https://api.varshtat.com/v1/data/download?feed=kalshi&from=2026-02-15&to=2026-02-15&type=ticker" Multi-day range with shorter URL expiry:
curl -H "X-API-Key: $API_KEY" \
"https://api.varshtat.com/v1/data/download?feed=kalshi&from=2026-02-10&to=2026-02-15&expires=6h" Download all files from a response:
curl -s -H "X-API-Key: $API_KEY" \
"https://api.varshtat.com/v1/data/download?feed=kalshi&from=2026-02-15&to=2026-02-15" \
| jq -r '.files[].signedUrl' \
| xargs -n1 -P4 curl -O DuckDB Examples
Query directly from a signed URL (no download needed):
SELECT * FROM read_parquet('https://storage.googleapis.com/...')
LIMIT 10; Query downloaded files with a time filter:
SELECT * FROM read_parquet('ticker_*.parquet')
WHERE ts BETWEEN '2026-02-15 14:00:00' AND '2026-02-15 15:00:00'; Aggregate across hours:
SELECT
date_trunc('hour', ts) AS hour,
count(*) AS ticks,
avg(yes_price) AS avg_price
FROM read_parquet('ticker_*.parquet')
GROUP BY 1 ORDER BY 1; Python Example
import pandas as pd
import requests
API_KEY = "sk_live_..."
API_HOST = "https://api.varshtat.com"
resp = requests.get(
f"{API_HOST}/v1/data/download",
params={"feed": "kalshi", "from": "2026-02-15", "to": "2026-02-15"},
headers={"X-API-Key": API_KEY},
)
files = resp.json()["files"]
dfs = [pd.read_parquet(f["signedUrl"]) for f in files]
df = pd.concat(dfs, ignore_index=True)
print(f"Loaded {len(df)} rows from {len(files)} files") File Naming Convention
Parquet files follow the pattern {type}_{HHMM}.parquet:
type— message type (ticker, trade, book, etc.)HHMM— UTC hour (0000, 0100, ... 2300)
For example, ticker_1430.parquet contains ticker data from 14:30–15:29 UTC.
A full day of one message type produces up to 24 files.
Limits
| Limit | Value |
|---|---|
| Max date range per request | 7 days |
| Max files per response | 200 |
| Signed URL expiry | 1–12 hours (default 12h) |
| Authentication | API key with datasets:read scope |
| Feed authorization | Per-key feed and date range restrictions |