Charts
candles.get returns price candles of up to 200 tokens at once, and candles.subscribe keeps them live.
Fetching candles
Section titled “Fetching candles”Candles come as columns rather than one object per candle, so a chart library can often take them as they are:
{ "height": 219969220, "timestamp_millis": 1792003477277, "tokens": { "wrap.near": { "time": [1791921600000, 1791925200000], "usd": { "open": [4.79, 4.8], "high": [4.83, 4.82], "low": [4.77, 4.79], "close": [4.8, 4.81] } } }, "missing": []}time is when each candle opens, in milliseconds, oldest first.
const params = new URLSearchParams({ tokens: 'wrap.near', resolution: '60', count_back: '24', series: 'open,high,low,close',});const response = await fetch(`https://api.intea.rs/candles?${params}`);const result = await response.json();if (!response.ok) throw new Error(result.error.message);const { time, usd } = result.tokens['wrap.near'];const candles = [];for (const [i, openedAt] of time.entries()) { candles.push({ time: openedAt, open: usd.open[i], high: usd.high[i], low: usd.low[i], close: usd.close[i] });}Resolutions
Section titled “Resolutions”resolution |
Candle | Also accepted |
|---|---|---|
1S |
1 second | |
1 |
1 minute | 1m |
5 |
5 minutes | 5m |
15 |
15 minutes | 15m |
60 |
1 hour | 60m, 1h |
240 |
4 hours | 240m, 4h |
D |
1 day | 24h, 1d |
W |
1 week | 7d, 1w |
The aliases work in any case.
Each candle opens where the one before closed. There’s no candle for a time when the price didn’t change and nothing traded.
1S candles only exist for the seconds the token was swapped in, so there are gaps between them. Each opens at the price before the first block with a swap in its second, which isn’t necessarily where the one before closed. They’re worked out from trades on request, so they’re slower than the other resolutions.
In NEAR
Section titled “In NEAR”"quote": "near" gives prices in NEAR instead of USD: the token’s USD price over NEAR’s at the same block. A token traded against NEAR then stays flat while only NEAR moves. Ask for both with "quote": ["usd", "near"], and each token has a usd and a near object.
In near, values are null from before wrap.near had a price.
Live charts
Section titled “Live charts”candles.subscribe takes the same params, with count_back defaulting to 0. Set count_back to get the chart’s history in the reply too. Each push has the candles that changed in that block: the latest one, and a new one when it opens. A push can also carry the candle before the latest one. A candle replaces the one you have with the same time.
Example: TradingView
Section titled “Example: TradingView”chart-tradingview shows Intear API candles in the TradingView charting library. Its datafeed loads history with /candles and keeps the chart live with candles.subscribe, all charts sharing one connection:
/** * Turns a token's candle columns into TradingView bars */function toBars({ time, usd }) { return time.map((openedAt, i) => ({ time: openedAt, open: usd.open[i], high: usd.high[i], low: usd.low[i], close: usd.close[i], volume: usd.volume[i], }));}
/** * The newest bar TradingView has of each token and resolution. It can only update its newest * bar, and a push can also carry the candle before it */const newestBarTimes = new Map();
/** * History: one request per chunk TradingView asks for */async function getBars(symbolInfo, resolution, periodParams, onHistoryCallback, onErrorCallback) { const countBack = Math.min(periodParams.countBack, 5000); const params = new URLSearchParams({ tokens: symbolInfo.ticker, resolution, count_back: String(countBack), to_millis: String(periodParams.to * 1000 - 1), // TradingView's `to` is exclusive }); try { const response = await fetch(`https://api.intea.rs/candles?${params}`); const result = await response.json(); if (!response.ok) throw new Error(result.error.message); const candles = result.tokens[symbolInfo.ticker]; // not there if the token doesn't exist const bars = candles ? toBars(candles) : []; const key = `${symbolInfo.ticker}/${resolution}`; if (bars.length > 0) newestBarTimes.set(key, Math.max(newestBarTimes.get(key) ?? 0, bars[bars.length - 1].time)); onHistoryCallback(bars, { noData: bars.length < countBack }); } catch (error) { onErrorCallback(String(error)); }}
// Live candles: every chart shares one connection, with a subscription per chartconst streams = new Map();const streamIds = new Map(); // subscription id of each TradingView listenerGuidlet nextId = 1;let socket = connect();
*/function send(method, params, id = nextId++) { if (socket.readyState === WebSocket.OPEN) socket.send(JSON.stringify({ id, method, params }));}
function connect() { const ws = new WebSocket('wss://api.intea.rs/ws'); ws.addEventListener('open', () => { for (const [id, stream] of streams) send('candles.subscribe', stream.params, id); }); ws.addEventListener('message', (event) => { const message = JSON.parse(event.data); if (message.error) console.error(`Request ${message.id} failed: ${message.error.message}`); const stream = streams.get(message.sub); if (!stream || !message.tokens) return; for (const bar of Object.values(message.tokens).flatMap(toBars)) { if (bar.time < (newestBarTimes.get(stream.key) ?? 0)) continue; newestBarTimes.set(stream.key, bar.time); stream.onTick(bar); } }); ws.addEventListener('close', () => { if (closed) return; // Candles may have changed while disconnected, so TradingView fetches them again for (const stream of streams.values()) stream.onReset(); setTimeout(() => (socket = connect()), 1000); }); return ws;}
*/function subscribeBars(symbolInfo, resolution, onTick, listenerGuid, onResetCacheNeededCallback) { const id = nextId++; const params = { tokens: [symbolInfo.ticker], resolution, series: ['open', 'high', 'low', 'close', 'volume'] }; streams.set(id, { key: `${symbolInfo.ticker}/${resolution}`, params, onTick, onReset: onResetCacheNeededCallback }); streamIds.set(listenerGuid, id); send('candles.subscribe', params, id);}
function unsubscribeBars(listenerGuid) { const id = streamIds.get(listenerGuid); if (id === undefined) return; streamIds.delete(listenerGuid); streams.delete(id); send('unsubscribe', { sub: id });}TradingView can only update its newest bar, so candles older than it are skipped. The full page, with symbol search and a market cap mode, is index.html.