Skip to main content

Analysis API

The Analysis API is the market data half of the Stolo Developer API. It covers what an options script needs before it trades: the ATM strike and expiries for an underlying, the option chain for one expiry, and minute candles for any option. Every endpoint lives under /analysis. Data for the current trading day is free; a request for a past date is charged in Stolo Tokens, and the same request is free again for 24 hours (see token charges).

All four are GET requests. Send the fields as query parameters, such as ?symbol=NIFTY&date=2026-09-24, with no request body. URL-encode the values, so a symbol with a space like INDIA VIX goes as INDIA%20VIX (requests and URLSearchParams do this for you). A blank optional parameter, such as date=, counts as not sent. Calling one of these endpoints with POST returns 405, and isn't charged.

EndpointWhat it returns
GET /analysis/symbol/infoATM strike, exchange, sector, and the next five expiries for a spot symbol
GET /analysis/option-chainCalls and puts for 41 strikes around the ATM, live or for a past date, with IV and Greeks
GET /analysis/candles/intradayCandles for the latest completed session
GET /analysis/candles/historicalCandles for any date range, up to 30 days per call

The usual order is the order of this page: symbol info gives you the expiry, the option chain gives you the option symbol, and the candles use that symbol.

Symbol Info​

The Symbol Info API is usually your first call for an underlying. It tells you the at-the-money strike and the next five expiry dates, which are exactly the two things you need to ask for the right option chain. Pass a past date and you get both as they stood on that day.

GET /analysis/symbol/info​

Query parameters​

FieldTypeRequiredDescription
symbolstringYesA spot symbol, such as NIFTY, BANKNIFTY, or RELIANCE. Option and futures symbols are rejected
datestringNoYYYY-MM-DD. Defaults to the current market date
curl 'https://algoapi.stolo.in/v1/analysis/symbol/info?symbol=NIFTY&date=2026-09-24' \
-H 'Authorization: Bearer YOUR_TOKEN'

Response​

The data field of the response (values are illustrative):

{
"symbol": "NIFTY",
"name": "NIFTY",
"sector": "index",
"exchange": "NSE",
"date": "2026-09-24",
"atm": 25100,
"expiries": ["2026-09-29", "2026-10-06", "2026-10-13", "2026-10-20", "2026-10-27"]
}
FieldTypeDescription
symbolstringThe spot symbol
namestringDisplay name
sectorstringSector, or index for indices
exchangestringExchange, for example NSE
datestringThe date the answer applies to (YYYY-MM-DD). This is the date you sent, or the current market date if you didn't send one
atmnumber or nullThe at-the-money strike: the spot's last traded price on date, rounded to the nearest listed strike. null when there's no price or no strikes for that date
expiriesstring[]Up to the next five expiry dates on or after date, nearest first. An expiry that falls on date itself is included. Empty for a spot with no F&O contracts

This endpoint doesn't return the lot size.

Errors​

HTTPmessageCause
404Symbol not foundThe spot symbol isn't one Stolo tracks
422Only spot symbols are allowedYou sent an option or futures symbol
422Validation failedsymbol is missing, or date isn't a valid date

How to use it​

Picking the chain to load. Take expiries[0] for the current weekly, or expiries[1] to skip an expiry-day chain that's about to die. Pass it as expiry to /analysis/option-chain.

Finding the ATM contract. atm tells you which row of the option chain is at the money. With "atm": 25100, the NIFTY ATM call and put are the strike: 25100 row.

Looking back. With a past date, both atm and expiries are as of that session. For example, on an expiry Tuesday expiries[0] is that same day, because an expiry on date is still listed.

note

atm comes from the last price of the day for past dates, and from the latest price during a live session. It moves as the market moves, so re-read it before you rely on it.

Option Chain​

The Option Chain API returns calls and puts for one underlying and one expiry: up to 20 strikes above and 20 below the at-the-money strike, each with its last traded price (LTP), open interest (OI), volume, the day's opening values, and implied volatility and Greeks (delta, gamma, theta, vega). During market hours the prices are live. Pass a past date and you get the chain as it closed that day.

It's also where you get option symbols for the candle endpoints. If the terms are new, the guide on how to read an option chain covers them.

GET /analysis/option-chain​

Query parameters​

FieldTypeRequiredDescription
symbolstringYesA spot symbol, such as NIFTY or BANKNIFTY
datestringNoYYYY-MM-DD. Defaults to the current market date. A past date returns that day's closing chain
expirystringNoYYYY-MM-DD. Defaults to the nearest expiry on or after date. Must be one of the symbol's listed expiries; get them from /analysis/symbol/info
curl 'https://algoapi.stolo.in/v1/analysis/option-chain?symbol=NIFTY&expiry=2026-09-29' \
-H 'Authorization: Bearer YOUR_TOKEN'

Response​

data is an array with one row per strike, lowest strike first (values are illustrative and trimmed to one row):

[
{
"strike": 25100,
"call": {
"symbol": "NIFTY26092925100CE",
"strike": 25100,
"option_type": "CE",
"ltp": 142.35,
"oi": 5821125,
"volume": 48213900,
"iv": 13.42,
"delta": 0.5187,
"gamma": 0.0014,
"theta": -18.62,
"vega": 12.09,
"open_tick": {
"symbol": "NIFTY26092925100CE",
"price": 118.6,
"volume": 402150,
"oi": 4960500,
"time": "...",
"ohlc": { "...": "..." }
}
},
"put": {
"symbol": "NIFTY26092925100PE",
"strike": 25100,
"option_type": "PE",
"ltp": 96.8,
"oi": 6310875,
"volume": 51877500,
"iv": 13.85,
"delta": -0.4813,
"gamma": 0.0014,
"theta": -17.94,
"vega": 12.09,
"open_tick": { "...": "..." }
}
}
]
Row fields​
FieldTypeDescription
strikenumberThe strike price
callobjectThe call (CE) at this strike
putobjectThe put (PE) at this strike
Leg fields (call and put)​
FieldTypeDescription
symbolstringThe option symbol. Use it as-is for the candle endpoints
strikenumberStrike price
option_typestringCE or PE
ltpnumberLast traded price in rupees
oinumberOpen interest, as reported by the exchange feed
volumenumberTraded volume for the day so far
ivnumber or nullImplied volatility, annualized and in percent (13.42 means 13.42%, not 0.1342), solved independently for this leg from its own ltp. null when there's no reliable price to solve from (see IV and Greeks)
deltanumber or nullOption delta
gammanumber or nullOption gamma
thetanumber or nullOption theta, per calendar day
veganumber or nullOption vega, per 1 point of volatility
open_tickobjectThe option's first tick of the day: price, volume, oi, time, and ohlc

Legs carry a few more instrument fields than the ones listed here, and the set can grow. Ignore fields you don't use rather than failing on unknown ones.

IV and Greeks​

iv, delta, gamma, theta, and vega are computed server-side from Black-Scholes, using the leg's own ltp and the chain's spot price at the same instant — so a call and its matching put always get their own independently-solved IV (they trade at different implied vols in practice; Stolo never mirrors one side's IV onto the other). rho isn't returned.

A leg gets null for all five fields, instead of a misleading 0, when there's no reliable price to solve from: before the leg's first trade of the day, or within the last 2 minutes before expiry (implied vol is numerically unstable that close to expiry and isn't worth trusting). Treat null as "nothing to show," not "IV is zero."

What's in the chain​

  • Up to 41 strikes. The ATM strike plus 20 on each side. Near the edge of the listed strikes you get fewer.
  • Only complete strikes. A strike is included only when both its call and put exist. You'll never see a row with a missing leg.
  • Live during the session. With no date, or today's date, ltp, oi, and volume come from Stolo's continuously updated intraday tick store. There's no delay and no 3:40 PM cutoff here, unlike candles.
  • Closing values for past dates. With a past date, the values are the last ones recorded that session.
  • Before the open. Before the first tick of the day, expect missing or stale ltp, oi, and open_tick values, and null for iv/delta/gamma/theta/vega, rather than an error.

Errors​

HTTPmessageCause
422Invalid expiry for this symbolexpiry isn't a listed expiry for this symbol, or it's before date
422No expiry found for this symbolYou left out expiry and the symbol has no upcoming expiry, for example a spot with no F&O contracts
422No data available for select expiryNo strikes around the ATM have data for this expiry
422Validation failedsymbol is missing, date isn't a date, or expiry isn't YYYY-MM-DD
501Option Chain data not found for the selected Instrument and ExpiryStolo has no chain stored for this symbol, expiry, and date
502variesAn internal Stolo service didn't respond. Retry with backoff

Working with the chain​

Change in OI since the open​

There's no ready-made OI change field. Compute it from the opening tick:

for row in chain:
ce = row["call"]
oi_change = ce["oi"] - ce["open_tick"]["oi"]

In the example above, the 25100 CE opened the day at 4,960,500 OI and now shows 5,821,125: an addition of 860,625, or about 17%. Rising OI with a rising premium points to fresh long positions; rising OI with a falling premium points to fresh writing. The open interest guide goes deeper on reading these.

Put-call ratio for the visible strikes​

total_put_oi = sum(row["put"]["oi"] for row in chain)
total_call_oi = sum(row["call"]["oi"] for row in chain)
pcr = total_put_oi / total_call_oi

This is the PCR for the 41 strikes returned, not the whole expiry. It's close for liquid indices, where far strikes carry little OI, but not identical.

Finding a strike​

atm_row = next(r for r in chain if r["strike"] == info["atm"])
atm_ce_symbol = atm_row["call"]["symbol"] # feed this to /analysis/candles/historical

info here is the response from /analysis/symbol/info.

How often to poll​

Each chain call costs one request against your rate limit, and the limit is 3,000 calls a day. Three underlyings every 30 seconds uses about 2,250 of those in a session; eight underlyings once a minute would use all 3,000. One call already returns every strike you need, so ask for the chain rather than individual strikes, and poll only as often as your strategy actually acts.

Candles​

The Candles API returns price candles for a single option: open, high, low, close, volume, and open interest for each interval, built from Stolo's one-minute data. Pick any whole-minute resolution your strategy uses: 1, 3, 5, 15, or anything else. There are two endpoints: one for the latest completed session and one for any date range you choose, up to 30 days per request.

The 3:40 PM rule​

Read this before anything else in this section. A session's candles become available at 3:40 PM IST, after the market closes. Until then, a request for today's candles quietly falls back to the previous trading day.

When you callWhat /analysis/candles/intraday returns
Tuesday 11:00 AMMonday's candles
Tuesday 3:39 PMMonday's candles
Tuesday 3:40 PM onwardTuesday's candles
SaturdayFriday's candles

The same rule applies to /analysis/candles/historical when your range reaches today, or any date after the last available session: the end of the range is pulled back to the last available session. The response always tells you what happened by echoing the dates you asked for next to the dates actually used. If they differ, the fallback kicked in.

Need prices during the session?

Candles aren't built for live use. For prices while the market is open, read the option chain, which returns live LTP, OI, and volume for every strike.

GET /analysis/candles/intraday​

Candles for the latest completed session (see the 3:40 PM rule above).

FieldTypeRequiredDescription
symbolstringYesAn option symbol, such as NIFTY26092925100CE
resolutionintegerYesCandle size in minutes. Any whole number from 1 up

There's no date parameter; the server works out the session for you.

curl 'https://algoapi.stolo.in/v1/analysis/candles/intraday?symbol=NIFTY26092925100CE&resolution=5' \
-H 'Authorization: Bearer YOUR_TOKEN'

The response has requested_date (the current market date) and effective_date (the session you actually got):

{
"symbol": "NIFTY26092925100CE",
"requested_date": "2026-09-28",
"effective_date": "2026-09-25",
"resolution": 5,
"data": [
{ "timestamp": "2026-09-25 09:15:00", "open": 131.4, "high": 138.0, "low": 127.9, "close": 135.2, "volume": 2104500, "oi": 6118875 }
]
}

That example was called on Monday morning, so it fell back to Friday's session.

GET /analysis/candles/historical​

Candles for one session, or every session in a date range.

FieldTypeRequiredDescription
symbolstringYesAn option symbol, such as NIFTY26092925100CE
start_datestringYesFirst session, YYYY-MM-DD
end_datestringNoLast session, YYYY-MM-DD. Leave it out for just the start_date session
resolutionintegerYesCandle size in minutes. Any whole number from 1 up

The range is inclusive and can cover at most 30 calendar days, so 2026-09-01 to 2026-09-30 is the longest range starting on 1 September. Weekends and holidays inside the range just contribute no candles. For a longer history, split it into 30-day requests.

curl 'https://algoapi.stolo.in/v1/analysis/candles/historical?symbol=NIFTY26092925100CE&start_date=2026-09-21&end_date=2026-09-25&resolution=5' \
-H 'Authorization: Bearer YOUR_TOKEN'

Response​

Values are illustrative and trimmed to two candles:

{
"symbol": "NIFTY26092925100CE",
"start_date": "2026-09-21",
"end_date": "2026-09-25",
"effective_start_date": "2026-09-21",
"effective_end_date": "2026-09-25",
"resolution": 5,
"data": [
{ "timestamp": "2026-09-21 09:15:00", "open": 96.2, "high": 101.5, "low": 93.8, "close": 99.4, "volume": 1520325, "oi": 3902250 },
{ "timestamp": "2026-09-25 15:25:00", "open": 162.9, "high": 164.0, "low": 160.1, "close": 162.4, "volume": 948750, "oi": 6205125 }
]
}
FieldTypeDescription
symbolstringThe symbol you asked for
start_datestringThe start date you sent
end_datestringThe end date you sent, or the same as start_date if you didn't send one
effective_start_datestringThe first session actually queried
effective_end_datestringThe last session actually queried, after the 3:40 PM rule
resolutionnumberCandle size in minutes
dataarrayCandles for every session in the range, oldest first. Use each timestamp to tell sessions apart

When end_date is past the last available session, only the end moves back. The start moves too only when the whole range lies past that session. For example, on Monday 28 September at 11 AM:

You sendYou get
start_date 2026-09-21, end_date 2026-09-2821 to 25 September (Monday's session isn't ready yet)
start_date 2026-09-28, no end_date25 September only

Candle fields​

Both endpoints return the same candle objects in data:

FieldDescription
timestampStart of the candle, in IST. The 9:15 candle at 5-minute resolution covers 9:15:00 to 9:19:59
openFirst price in the candle
highHighest price in the candle
lowLowest price in the candle
closeLast price in the candle
volumeTotal volume traded in the candle
oiOpen interest at the end of the candle

Cast numeric fields with float() or Number() rather than assuming their JSON type.

How many candles to expect​

Candles are aligned to the clock in IST, not to the market open. For sizes that fit evenly into 9:15 (1, 3, 5, and 15 minutes), the first candle starts at 9:15 AM and a full session from 9:15 AM to 3:30 PM (375 minutes) gives:

ResolutionCandles in a full session
1 minute375
3 minutes125
5 minutes75
15 minutes25

For other sizes, such as 30 or 45 minutes, the first candle can be stamped before 9:15 (for example 9:00 at 30 minutes) and holds only the minutes after the open. Its open is still the first traded price of the day. If you need candles anchored exactly on 9:15, request 1, 3, 5, or 15-minute candles and combine them yourself.

A thinly traded strike can have fewer candles, because a minute with no trades produces no row and an interval with no rows produces no candle. Don't assume a fixed count; use the timestamps.

Empty results​

An empty data array is not an error. It usually means one of these:

  • The symbol string is wrong. Copy it from the option chain rather than building it.
  • The contract didn't exist or hadn't started trading on that date.
  • Every day in the range was a weekend or holiday. Check the effective dates against the calendar.

Errors​

HTTPmessageCause
422Validation failedsymbol is missing, or resolution isn't a whole number of 1 or more
422Validation failedHistorical only: start_date is missing, a date isn't valid, end_date is before start_date (End date must be on or after the start date), or the range is longer than 30 days (Date range can't exceed 30 days)
402You don't have enough Stolo Tokens for this actionThe balance can't cover every new past day returned. See token cost

The detail for each failed field is in data, as described in validation errors.

Token cost​

Both candle endpoints are charged 1 Stolo Token per symbol per past day that returns candles, whatever the resolution. The current trading day, weekends, and holidays are free, so /analysis/candles/intraday costs nothing once today's session is served (after 3:40 PM); before that it returns the previous session, which is charged. The same symbol and day is free to request again, through either endpoint, for 24 hours after it was charged. If your balance can't cover every new day, the request fails with 402 and nothing is charged. Token charges has a worked example.

Worked example: an opening range on the ATM call​

You want the 9:15 to 9:30 range of the NIFTY 25100 CE on 24 September 2026, then how it closed.

  1. Request 15-minute candles: {"symbol": "NIFTY26092925100CE", "start_date": "2026-09-24", "resolution": 15}.
  2. The first candle (09:15:00) has high: 131.2 and low: 115.2. That's the opening range: 16 points wide, about 13% of the premium.
  3. The last candle (15:15:00) closes at 162.4, 31.2 points above the range high.

Widen the request to a range, for example start_date 2026-09-01 and end_date 2026-09-30, and group the candles by session. Now you have the raw data to test an opening range breakout rule on options across a month, in one call. Remember that each option contract only trades until its expiry, so for longer studies pick the contract that was near the money in each week. Stolo's ORB screener does the same study on stocks.