Skip to content

Pagination and ranges

oneapi.finance does not use cursor- or offset-style pagination. Instead, every range-aware endpoint accepts a triple of outputsize, start_date, and end_date. This is intentional: the natural unit of paging for time-series financial data is a date window, not a row count.

The three knobs

ParamTypeDefaultNotes
outputsizeint30 (intraday) / 365 (daily+)Maximum bars to return. Capped at 5,000.
start_dateISO date or datetimenoneInclusive lower bound.
end_dateISO date or datetimenowInclusive upper bound.

If both start_date and end_date are present, outputsize is treated as a ceiling on the result count and the window is the dominant filter. If only outputsize is present, the API returns the most recent outputsize bars ending at end_date (or now).

The endpoints that accept these knobs:

Date and datetime formats

We accept two ISO 8601 forms:

  • Date only for daily-and-coarser intervals: YYYY-MM-DD. Example: 2025-12-31.
  • Datetime with offset for intraday intervals: YYYY-MM-DDTHH:MM:SSZ or YYYY-MM-DDTHH:MM:SS+02:00. Example: 2026-05-04T14:30:00Z.

If you pass a bare datetime without an offset (2026-05-04T14:30:00), we treat it as UTC. Pass an explicit offset if you mean a local exchange time.

Paging a long window

To page 5 years of daily data without exceeding the 5,000-bar cap, walk the window in calendar slices client-side:

import httpx
from datetime import date, timedelta
def daily_series(symbol: str, start: date, end: date, api_key: str):
out = []
cursor = start
while cursor <= end:
chunk_end = min(cursor + timedelta(days=365 * 4), end)
r = httpx.get(
"https://api.oneapi.finance/v1/time_series",
params={
"symbol": symbol,
"interval": "1day",
"start_date": cursor.isoformat(),
"end_date": chunk_end.isoformat(),
"outputsize": 5000,
},
headers={"Authorization": f"Bearer {api_key}"},
timeout=30.0,
)
r.raise_for_status()
out.extend(r.json()["values"])
cursor = chunk_end + timedelta(days=1)
return out

A 4-year slice fits comfortably under the 5,000-bar cap (US trading days are roughly 252 per year). For 1-minute bars, walk in 3-day slices instead.

Result ordering

Time-series results are returned most-recent-first (descending by datetime). If you prefer chronological order, reverse the array client-side:

values = sorted(r.json()["values"], key=lambda b: b["datetime"])
const values = (await r.json()).values
.slice()
.sort((a, b) => a.datetime.localeCompare(b.datetime));

Inclusive bounds and trading days

Both start_date and end_date are inclusive. There is no implicit weekend/holiday filtering: if you ask for 2025-12-25 → 2025-12-26 on a US listing, you get an empty array because the exchange was closed both days.

Symbol-search and quote endpoints are not range-aware and ignore these parameters.

What’s next