Candles

OHLCV bars on seven timeframes, including the live in-flight bar, with cursor pagination that walks history all the way back to a pair's listing date.

GET/v1/candles/{symbol}

This is the same candle store the Osiris charts draw from. Our ingest maintains it directly from the Binance trade stream: closed bars are kept per symbol per timeframe, and the current bucket exists as a live bar that updates on every trade. When you request candles, the newest element of the array is that live bar (unless the pair hasn't traded in the current bucket yet). Its close is the last traded price and its high/low/volume are still growing.

History does not stop where our in-memory store ends. When you page back past the cached depth, the API transparently continues from the venue's own archive server-side; your pagination loop just keeps working, on the same response shape, until you reach the pair's listing date. You never talk to the exchange yourself, you never handle the seam, and bars are only ever sourced from the same venue the request names.

Request

ParameterInDescription
intervalqueryOne of 1m 5m 15m 1h 4h 1d 1w. Default 5m.
limitquery1-1000 bars. Default 300.
beforequeryMillisecond timestamp cursor: return only bars strictly older than this. Omit for the newest bars.
exchangequeryVenue to read. See Exchanges. Default: Binance.
Latest 100 hourly bars
curl "https://osiristrader.com/api/v1/candles/BTCUSDT?interval=1h&limit=100" \
  -H "Authorization: Bearer osk_YOUR_KEY"

Response

{
  "symbol": "BTCUSDT",
  "interval": "1h",
  "data": [
    { "time": 1783866400000, "open": 63822.0, "high": 63990.5, "low": 63780.1, "close": 63900.1, "volume": 1382.11 },
    { "time": 1783870000000, "open": 63900.1, "high": 64010.0, "low": 63850.2, "close": 63981.5, "volume": 1204.33 }
  ]
}
FieldDescription
timeBucket open time, Unix ms. Buckets are aligned to the timeframe (an 1h bar always opens on the hour, UTC).
open / high / low / closePrices at the pair's native precision.
volumeBase-asset volume for the bucket.

Bars are returned in chronological order (oldest first), the order charting libraries and TA code expect.

Working with the live bar

The last array element being live has two practical implications. First, it gives you the current price for free: data[data.length - 1].close is the last trade. Second, if you compute indicators, decide deliberately whether the live bar participates: an RSI over closed bars only is stable, an RSI including the live bar repaints until the bucket closes. Both are valid; mixing them by accident is the classic bug. A bar is closed once a newer bar's time exists, or once now ≥ time + interval.

On very quiet pairs the live bar may be missing entirely: the bucket opened but nothing has traded yet. The newest element is then the last closed bar; its close is still the last traded price.

Paging through history

Pass the oldest time you have as before and repeat. Each response is strictly older than the cursor; you are done when a page comes back empty (you reached the listing date).

JavaScript: full history walk
let cursor = undefined;
const all = [];
while (true) {
    const url = "https://osiristrader.com/api/v1/candles/BTCUSDT?interval=1d&limit=1000"
        + (cursor ? "&before=" + cursor : "");
    const { data } = await (await fetch(url, { headers })).json();
    if (data.length === 0) break;
    all.unshift(...data);
    cursor = data[0].time; // oldest bar of this page
}
Deep history pages are served partly from the Binance archive and are slower than hot-cache reads: expect hundreds of milliseconds instead of tens on those calls, and don't run history walks inside a latency-sensitive loop. Backfill once, store locally, then stay incremental via the newest page (or the WebSocket stream).