Skip to content

Historical Data

The Historical Data API provides time-series OHLCV (Open, High, Low, Close, Volume) data for instruments across various intervals. This is ideal for charting, analysis, and building trading strategies.

Two endpoints share the same candle contract, the same intervals and the same per-call limits: one for instruments that are still trading, and one for F&O contracts that have expired. They differ only in how an instrument is identified. The expired-contract endpoint is coming soon; its contract is documented below so you can build against it ahead of time.

Request Type Path Description
GET /market/historical/{interval} Fetches historical OHLCV data.
GET /market/historical/expired/{interval} Fetches historical OHLCV data for expired F&O contracts. Coming soon.

Get Historical Data

Endpoint

Text Only
GET /market/historical/{interval}

Path Parameters

Parameter Description
interval The time interval for each candle. See the table of Supported Intervals below.

Query Parameters

Parameter Type Required Description
scrip-codes string Yes A comma-separated list of at most 5 instrument identifiers. Example: NSE_3045,NFO_51011
start_time int64 Yes Start timestamp (Unix epoch milliseconds, inclusive).
end_time int64 Yes End timestamp (Unix epoch milliseconds, exclusive).

Up to 5 instruments per request

scrip-codes takes a maximum of five identifiers; requests with more return 400 {"debug_info": "Invalid scrip codes", "message": "Bad Request"}. Repeated codes are de-duplicated and count once. For a larger universe, batch your instruments five at a time.

The segment travels in each code's prefix — NSE_ for cash, NFO_ for F&O — so there is no separate segment parameter to set.

Example Request

Bash
curl --location 'https://api.indstocks.com/market/historical/1minute?scrip-codes=NSE_3045&start_time=1750055540000&end_time=1750141940000' \
--header 'Authorization: YOUR_ACCESS_TOKEN'

Response Format The response uses a success boolean. data is keyed by scrip code, and each scrip's candles is an array of objects.

Candle field Description
ts Candle open time, Unix epoch seconds (IST). See Candle timestamps.
o Open price
h High price
l Low price
c Close price
v Volume
JSON
{
  "success": true,
  "data": {
    "NSE_1594": {
      "candles": [
        { "ts": 1782877500, "o": 1007, "h": 1013.9, "l": 999.3, "c": 1000.4, "v": 2847163 },
        { "ts": 1782881100, "o": 1000.4, "h": 1002, "l": 996.7, "c": 999.6, "v": 1389042 }
      ]
    }
  }
}

Request times are milliseconds, candle times are seconds

start_time and end_time are epoch milliseconds, while the ts on each returned candle is epoch seconds. Multiply by 1000 when using a returned ts to build the next request.

Candle fields

Candles carry ts, o, h, l, c and v across every interval and segment. For open interest, use the Option Chain, which returns OI and previous OI per leg.

Response shape

  • This endpoint wraps its response in a success boolean — check success rather than status when handling it.
  • Each requested code gets its own key under data with its own candles array — they are not merged into a single list.
  • Codes with no data in the requested window are not included under data, so read the keys returned rather than assuming one per code requested.

Candle timestamps

ts is the time at which the candle opens. Each candle covers the half-open interval [ts, ts + interval) — its own opening time is included, the next candle's opening time is not.

Worked example, on 5minute:

Candle ts Covers the minutes Next candle opens
09:15 09:15 – 09:19 09:20
09:20 09:20 – 09:24 09:25
09:25 09:25 – 09:29 09:30

The 09:20 candle opens on the first trade at or after 09:20:00 and closes on the last trade before 09:25:00. The rule is the same on every interval, and on both endpoints.

Deriving a closing time

If your charting or backtesting engine indexes bars by closing time rather than opening time, add the interval to ts as you read it: a 5minute candle stamped 09:20 closes at 09:25.

Intraday candles are anchored to the session open

Buckets are aligned to 09:15 IST, the start of the trading session, rather than to wall-clock :00/:05 boundaries. 5minute candles fall at 09:15, 09:20, 09:25 …, 15minute candles at 09:15, 09:30, 09:45 …, and 60minute candles at 09:15, 10:15, 11:15 …


Get Expired Contract Candles

Coming soon

This endpoint is not yet available on production. The contract below is settled and is published so you can build against it in advance; requests to it will start returning data once it is enabled. This page and the Changelog will be updated when it goes live.

The same OHLCV candles, for F&O contracts whose expiry has already passed — Get Historical Data covers instruments that are still trading. Together the two endpoints will give a strategy the full price history of a contract, from listing through to expiry.

Contracts here are identified by trading_symbol, the identifier returned by Search Expired Contracts and Contracts for an Expired Expiry. Exchanges reuse numeric instrument tokens once a contract has expired, so trading_symbol is the stable way to address a contract that is no longer trading.

Endpoint

Text Only
GET /market/historical/expired/{interval}

Path Parameters

Parameter Description
interval The time interval for each candle. Same values and same per-call maximums as the live endpoint — see Supported Intervals & Maximum Time Range.

Query Parameters

Parameter Type Required Description
trading-symbols string Yes A comma-separated list of 1 to 50 trading_symbols. Example: NIFTY26AUG2523950CE
start_time int64 Yes Start timestamp (Unix epoch milliseconds, inclusive).
end_time int64 Yes End timestamp (Unix epoch milliseconds, exclusive).
segment string The exchange derivatives segment the contracts belong to.
Enum: NFO, BFO
Default: NFO

Up to 50 symbols per request

trading-symbols takes between one and fifty identifiers; requests with more return 400 {"debug_info": "trading-symbols must contain 1-50 symbols.", "message": "Bad request"}. Get Historical Data takes up to five scrip-codes, so size your batching per endpoint rather than sharing one constant across both.

Set segment to reach BSE derivatives

segment selects the exchange's derivatives segment. Only F&O contracts expire, so two values apply:

Value Segment
NFO NSE Derivatives (F&O)
BFO BSE Derivatives (F&O)

NFO is the default, so NSE contracts need no segment at all. BSE contracts must be requested with segment=BFO — a BSE trading_symbol sent without it is looked up against NSE, finds no match, and comes back absent from data.

These are the exchange-segment codes used across the API, the same ones that prefix a scrip-code or a WebSocket instrument — see Instrument Code Formats. They are not the segment=DERIVATIVE value taken by Contracts & Expiries.

trading-symbols, start_time, end_time and segment are the complete query contract; your account is resolved from the access token.

Example Request

These calls will work once the endpoint is enabled. NSE derivatives, using the default segment:

Bash
curl --location 'https://api.indstocks.com/market/historical/expired/1minute?trading-symbols=NIFTY26AUG2523950CE&start_time=1787542200000&end_time=1787652000000' \
--header 'Authorization: YOUR_ACCESS_TOKEN'

BSE derivatives, with segment=BFO:

Bash
curl --location 'https://api.indstocks.com/market/historical/expired/1minute?trading-symbols=SENSEX26AUG2581000CE&segment=BFO&start_time=1787542200000&end_time=1787652000000' \
--header 'Authorization: YOUR_ACCESS_TOKEN'

Response Format Identical in shape to Get Historical Data — a success boolean, data keyed per instrument, each with an array of {ts, o, h, l, c, v} candle objects. The only difference is the key: trading_symbol rather than scrip code.

JSON
{
  "success": true,
  "data": {
    "NIFTY26AUG2523950CE": {
      "candles": [
        { "ts": 1787543100, "o": 374.1, "h": 395.15, "l": 374.1, "c": 390, "v": 19955 },
        { "ts": 1787543160, "o": 390, "h": 402.5, "l": 388.2, "c": 399.7, "v": 14320 }
      ]
    }
  }
}

The candle contract is identical to the live endpoint. ts is the candle's open time in epoch seconds and covers [ts, ts + interval) (see Candle timestamps), start_time and end_time are epoch milliseconds, intraday buckets are anchored to the 09:15 IST session open, and each interval carries the same per-call maximum range.

Read the keys returned

data carries an entry for each requested symbol that has candles in the window. A symbol with no data in that window, and any symbol the endpoint does not recognise — a numeric security_id sent in place of a trading symbol, or a BSE contract requested without segment=BFO — is absent from data rather than returned empty. Match the keys in the response against the symbols you requested.

A zero-width window, where start_time equals end_time, returns "candles": null.

Candle fields

Candles carry ts, o, h, l, c and v, the same set as the live endpoint. For open interest, use the Option Chain, which returns OI and previous OI per leg.


Supported Intervals & Maximum Time Range

Interval Label Value Max Range Per Call
1 Minute 1minute 7 Days
2 Minutes 2minute 7 Days
3 Minutes 3minute 7 Days
4 Minutes 4minute 7 Days
5 Minutes 5minute 7 Days
10 Minutes 10minute 7 Days
15 Minutes 15minute 7 Days
30 Minutes 30minute 7 Days
1 Hour 60minute 15 Days
2 Hours 120minute 15 Days
3 Hours 180minute 15 Days
4 Hours 240minute 15 Days
1 Day 1day 1 Year
1 Week 1week 1 Year
1 Month 1month 1 Year

These intervals and maximums apply to both Get Historical Data and Get Expired Contract Candles.

This is the ceiling on a single call, not the depth of history available. Reaching further back is a matter of making more calls — one per window, walking backwards — not of asking for a wider window.

The maximum applies to the window you request, not to the span you get back. On 1week and 1month the returned candles land on week and month boundaries, so a full one-year request comes back spanning slightly less than a year.

Use the exact interval values

The table above is the complete set. Hour intervals are expressed in minutes — 60minute, 120minute, 180minute, 240minute — and the daily, weekly and monthly intervals take the 1 prefix: 1day, 1week, 1month. Other values return 400 {"debug_info": "invalid interval.", "message": "Bad request"}.

Paging by date range

A wider request returns the maximum window, not an error

The maximum is applied to every call. A request for a window wider than the interval's maximum returns 200 with "success": true and the maximum window's data, so the width of the request is what determines the coverage you receive.

Both Get Historical Data and Get Expired Contract Candles work this way, and neither returns a continuation token — paging is by date range. Size each request to the maximum for its interval, and check the candles you receive against the candles the window should contain.

To build a series longer than one window, issue one request per maximum-width window and walk backwards, stitching the results together.


Notes

  • start_time/end_time query parameters are in IST and Unix epoch milliseconds; the ts field inside each returned candle is in Unix epoch seconds.
  • Keep each request within the maximum range for the chosen interval. A wider window returns the maximum range's data rather than an error, so size each request to the limit in the table above and page by date range for longer histories.
  • start_time must not be later than end_time, which returns 400 {"debug_info": "start_time must not be after end_time.", "message": "Bad request"}.
  • If requesting multiple instruments, each one gets its own candles array under data — they are not merged into a single list.
  • The two endpoints take different identifiers and different batch sizes: scrip-codes with a maximum of five for live instruments, trading-symbols with a maximum of fifty for expired contracts.
  • Both endpoints return the same candle fields, ts, o, h, l, c and v. For open interest, use the Option Chain.

See Also