Stolo Developer API
The Stolo Developer API lets your own code read the same NSE F&O data you see in the Stolo app. Pull a live option chain for NIFTY, look up the ATM strike and upcoming expiries for any F&O underlying, and fetch 5-minute candles for any strike on any past date. When your code has decided on a trade, it can place the order through your connected broker and track it. It is built for traders who write their own scanners, dashboards, backtests, and algos.
This section is the reference for the API. Start here for the big picture and a working first call, then use the pages in the sidebar for the detail on each endpoint.
What you can do with it
| Area | Endpoints | Typical use |
|---|---|---|
| Reference data | GET /analysis/symbol/info | Find the ATM strike and the next five expiries for NIFTY, BANKNIFTY, or any F&O stock |
| Option chain | GET /analysis/option-chain | Live or end-of-day calls and puts, 20 strikes either side of ATM, with LTP, OI, and volume |
| Candles | GET /analysis/candles/intraday, GET /analysis/candles/historical | OHLC, volume, and OI candles at any minute resolution for one option, for one session or up to 30 days per call |
| Trading | POST /trade/place, DELETE /trade/cancel, GET /trade/positions, /trade/orders, /trade/margins | Place and cancel option orders through your connected broker, and read positions, the order book, and margins |
Endpoints that only read data (all of Analysis, plus trading positions, orders, and
margins) are GET, and cancelling an order is DELETE, both with their fields in the query
string. /authenticate and placing an order are POST with a JSON body.
Before you start
To use the API at all, you need just two things:
- An active Stolo Pro or Stolo Trial (15 days) plan on your account. See the subscription plans.
- An API app. Create it on the API App page in your Stolo account. Give it a name and you get an app key and an app secret straight away. Each account has one app.
Then, depending on which endpoints you call:
- Historical analysis data needs Stolo Tokens. A request under
/analysis(symbol info, option chain, candles) for a past date is paid for from your Stolo Tokens balance, and repeating it within 24 hours is free. Current-day data is free. See token charges. - Trading endpoints need a broker connected on Stolo, logged in for the day. They don't use Stolo Tokens. See trading.
Base URL and versioning
https://algoapi.stolo.in/v1
Every path in this reference is relative to that base, so GET /analysis/option-chain means
GET https://algoapi.stolo.in/v1/analysis/option-chain. The v1 segment is the API version and
is echoed back in every response as response_meta.api_version.
Quickstart: your first option chain
The flow is always the same: exchange your key and secret for a token once, then send that token with every other call.
- Call
POST /authenticatewith your key and secret. Keep thetokenit returns. - Call any other endpoint with the header
Authorization: Bearer <token>. - Read the result from the
datafield of the response.
- curl
- Python
- JavaScript
# 1. Get a token (valid until 5 AM IST)
TOKEN=$(curl -s -X POST 'https://algoapi.stolo.in/v1/authenticate' \
-H 'Content-Type: application/json' \
-d '{"key":"YOUR_APP_KEY","secret":"YOUR_APP_SECRET"}' | jq -r '.data.token')
# 2. Ask for the ATM strike and upcoming expiries
curl -s 'https://algoapi.stolo.in/v1/analysis/symbol/info?symbol=NIFTY' \
-H "Authorization: Bearer $TOKEN"
# 3. Pull the option chain for the nearest expiry
curl -s 'https://algoapi.stolo.in/v1/analysis/option-chain?symbol=NIFTY' \
-H "Authorization: Bearer $TOKEN"
import requests
BASE = "https://algoapi.stolo.in/v1"
def call(method, path, data, token=None):
headers = {"Authorization": f"Bearer {token}"} if token else {}
# GET endpoints (analysis) take query params; POST endpoints take a JSON body.
fields = {"params": data} if method == "GET" else {"json": data}
res = requests.request(method, BASE + path, headers=headers, timeout=10, **fields)
payload = res.json()
if res.status_code != 200 or payload.get("status") != "success":
raise RuntimeError(f"{path} failed ({res.status_code}): {payload.get('message')}")
return payload["data"]
token = call("POST", "/authenticate", {"key": "YOUR_APP_KEY", "secret": "YOUR_APP_SECRET"})["token"]
info = call("GET", "/analysis/symbol/info", {"symbol": "NIFTY"}, token)
print("ATM", info["atm"], "next expiry", info["expiries"][0])
chain = call("GET", "/analysis/option-chain", {"symbol": "NIFTY", "expiry": info["expiries"][0]}, token)
for row in chain:
print(row["strike"], row["call"]["ltp"], row["put"]["ltp"])
const BASE = "https://algoapi.stolo.in/v1";
// GET endpoints (analysis) take query params; POST endpoints take a JSON body.
async function call(method, path, data, token) {
const isGet = method === "GET";
const res = await fetch(BASE + path + (isGet ? `?${new URLSearchParams(data)}` : ""), {
method,
headers: {
...(isGet ? {} : { "Content-Type": "application/json" }),
...(token ? { Authorization: `Bearer ${token}` } : {}),
},
body: isGet ? undefined : JSON.stringify(data),
});
const payload = await res.json();
if (!res.ok || payload.status !== "success") {
throw new Error(`${path} failed (${res.status}): ${payload.message}`);
}
return payload.data;
}
const { token } = await call("POST", "/authenticate", { key: "YOUR_APP_KEY", secret: "YOUR_APP_SECRET" });
const info = await call("GET", "/analysis/symbol/info", { symbol: "NIFTY" }, token);
const chain = await call("GET", "/analysis/option-chain", { symbol: "NIFTY", expiry: info.expiries[0] }, token);
console.log(info.atm, chain.length, "strikes");
The API Playground page runs these same calls from a form and shows the exact request and raw response for each. It's the fastest way to check your key works and see real response shapes before writing any code.
A worked example: from symbol to candles
Say you want to study how the NIFTY ATM call traded last Thursday at 5-minute resolution. Each step feeds the next:
GET /analysis/symbol/info?symbol=NIFTY&date=2026-09-24returns"atm": 25100and"expiries": ["2026-09-29", "2026-10-06", ...].GET /analysis/option-chain?symbol=NIFTY&date=2026-09-24&expiry=2026-09-29returns 41 rows. The row with"strike": 25100has"call": {"symbol": "NIFTY26092925100CE", ...}.GET /analysis/candles/historical?symbol=NIFTY26092925100CE&start_date=2026-09-24&resolution=5returns 75 candles, one per 5 minutes from 9:15 AM to 3:25 PM.
Copying option symbols from the option chain, instead of building the string yourself, avoids the most common source of empty results.
Why a request can fail
Before any endpoint returns data, Stolo checks your request. Each problem has its own HTTP status code, so the code alone tells you what went wrong:
| You get | What it means | What to do |
|---|---|---|
401 | Your token is missing, expired, or was replaced by a newer /authenticate call | Authenticate again and retry |
403 | The account that owns the app has no active Stolo Pro or Stolo Trial (15 days) plan | Renew the plan |
429 | You've sent too many requests in a short time | Wait the number of seconds in the Retry-After header |
402 | The account that owns the app has run out of Stolo Tokens | Top up the balance |
422 | Something in your request is wrong, for example a missing field or an invalid date | Read message and data in the response, fix the request |
404 | What you asked for doesn't exist, for example an unknown symbol | Check the symbol |
5xx | A problem on Stolo's side | Retry after a short wait |
If a request has more than one problem, you get the first one in the order of this table.
/authenticate only returns 401, 403, or 422. The
requests, responses, and errors page covers the response
format and every error message in detail.
Make your first API call
Open the API Playground, enter your app key and secret, and call every endpoint from your browser.
Open the API Playground