Skip to content

Historical REST

All time-series data the platform persists is available through five REST endpoints with identical pagination and filtering semantics. Response payloads mirror the WebSocket message shapes — a parser that handles a live print frame can consume historical trade rows unchanged.

Authentication is optional but tier-determines lookback: free tier = last 1 day; paid (api) tier = full retention (~90 days today, expanding to inception as backfill completes).


Endpoints

GET /v1/history/{exchange}/{symbol}/quotes ?from=&to=&limit=&cursor=
GET /v1/history/{exchange}/{symbol}/trades ?from=&to=&limit=&cursor=
GET /v1/history/{exchange}/{symbol}/funding ?from=&to=&limit=&cursor=
GET /v1/history/{exchange}/{symbol}/liquidity ?from=&to=&limit=&cursor=&action=mint|burn
GET /v1/history/rates/{address} ?from=&to=&limit=&cursor=
EndpointReturnsMessage type
.../quotes5-second sampled top-of-book rowsQuoteMessage
.../tradesOne row per tradePrintMessage
.../fundingFunding rate rowsFundingRateMessage
.../liquidityLP mint/burn eventsLiquidityMessage
/rates/{address}Yield-market snapshots (Pendle + Spectra UNION)RateMarketMessage

The .../liquidity endpoint is meaningful only for AMM venues (uni, univ4, univ4chain, sushi, pancake, balancer).

The /rates/{address} endpoint is keyed by contract address (lowercase), not by venue + symbol. The same address uniquely identifies a market across both Pendle and Spectra. Historical queries for yield markets require the address; use GET /v1/instruments or GET /v1/symbols/pendle to resolve PT symbols to addresses.


Path parameters

ParameterTypeNotes
exchangestringLowercase venue id. See Venues & Symbols.
symbolstringCanonical per-venue symbol. URL-encode slashes: WETH/USDCWETH%2FUSDC. Most HTTP libraries handle this automatically when using a params dict.
addressstringLowercase EVM address (0x + 40 hex).

Query parameters

ParameterTypeDefaultNotes
fromstringnow − 24hISO 8601 (2026-04-01T00:00:00Z or 2026-04-01) or epoch ms
tostringnowSame formats as from
limitinteger1000Rows per page. Hard cap: 10,000.
cursorstringOpaque cursor from the previous page’s next_cursor.
actionstringLiquidity endpoint only. Filter to mint or burn; omit for both.

Response shape

{
"data": [ /* array of message objects, oldest first */ ],
"next_cursor": "MTc0ODI3NTIwMDAwMA=="
}

data is ordered oldest first. next_cursor is null when no further pages exist. Pass it back as ?cursor=... to get the next page. Do not decode or construct the cursor manually — the format is internal and may change.


Lookback limits

TierLookback
none (free / anonymous)1 day
api (paid)Full DB retention (no hard cap; ~90 days today, expanding to inception)

Querying outside your tier’s window returns HTTP 403:

{
"error": "lookback_too_far_for_tier",
"message": "Free tier limited to 1 day of history. Authenticate with an API key for full historical access.",
"tier": "none",
"freeLookbackMs": 86400000
}

Authentication: Authorization: Bearer <JWT>. Tier is resolved from the JWT’s tier claim. Anonymous requests default to none. See Authentication for how to obtain a JWT or API key.


Pagination

import httpx
def fetch_all(exchange, symbol, kind, start, end,
base="https://api.mackinac.io", headers=None):
cursor = None
while True:
params = {"from": start, "to": end, "limit": 10_000}
if cursor:
params["cursor"] = cursor
r = httpx.get(
f"{base}/v1/history/{exchange}/{symbol}/{kind}",
params=params, headers=headers or {}
)
r.raise_for_status()
body = r.json()
yield from body["data"]
cursor = body["next_cursor"]
if cursor is None:
return
# Example: all HL ETH trades for a date range
jwt = "eyJhbGciOi..."
for row in fetch_all("hl", "ETH", "trades", "2026-04-01", "2026-04-08",
headers={"Authorization": f"Bearer {jwt}"}):
print(row["price"], row["size"], row["side"])

Examples

Pull recent HL ETH trades

GET /v1/history/hl/ETH/trades?from=2026-04-01&to=2026-04-08&limit=10000
{
"data": [
{"type": "print", "exchange": "hl", "symbol": "ETH",
"price": 3450.5, "size": 1.2, "side": 1, "time": 1743465601000},
...
],
"next_cursor": "MTc0Mz..."
}

Pull AMM trades (URL-encoded slash)

GET /v1/history/uni/WETH%2FUSDC/trades?from=2026-04-01

Pull LP events, mints only

GET /v1/history/uni/WETH%2FUSDC/liquidity?action=mint&from=2026-04-01

Pull yield-market history by address

GET /v1/history/rates/0xc62d75593dad6c451173553593f86d80bf29dfe6

Returns rate_market rows from both Pendle and Spectra history tables (UNION). The exchange field on each row identifies which venue produced it.

Pull funding history

GET /v1/history/hl/ETH/funding?from=2026-04-01&to=2026-04-08

Error codes

HTTPerror codeMeaning
400invalid_timefrom or to couldn’t be parsed
400invalid_limitlimit outside [1, 10000]
400invalid_cursorCursor base64 decode failed
403lookback_too_far_for_tierRequested window exceeds the caller’s tier limit
404not_foundUnknown exchange/symbol — the backend has never persisted any rows for this key
500db_errorTimescaleDB query failed; retry with exponential backoff

See Errors for the full error reference and retry decision matrix.