Requests, responses, and errors
Every Stolo API endpoint follows the same rules for requests, responses, errors, symbols, and dates. Learn them once here and each endpoint page only has to describe its own fields.
Requests
- The Analysis endpoints are
GET. Send their fields as query parameters (?symbol=NIFTY&resolution=5), URL-encoded, with no body. - Trading positions, orders, and margins are
GETtoo, and cancelling an order isDELETE. Both sendbroker_slug(and, for cancel,broker_order_id) in the query string. /authenticateand placing an order arePOST. Send the body as JSON withContent-Type: application/json.- Send
Authorization: Bearer <token>on everything except/authenticate. See Authentication. - CORS is open to any origin, so you can call the API from a browser page. Only do that with a token, never with your secret.
Unknown fields, in a query string or a body, are ignored, so a typo in an optional field name fails silently.
If an optional filter such as expiry seems to have no effect, check its spelling first.
The response envelope
Every response from a real endpoint, success or error, has the same four top-level fields:
{
"status": "success",
"message": "",
"response_meta": {
"api_version": "v1",
"message": "",
"elapsed_time": "12.34ms"
},
"data": {}
}
| Field | Description |
|---|---|
status | "success" or "error" |
message | What happened to this request. Empty on success, the error text on failure. Treat it as text to log, not something to parse |
data | The endpoint's result on success (each endpoint page documents this). On error it's null, except for validation errors, described below |
response_meta.api_version | The version from the URL, for example v1 |
response_meta.message | API-wide notices, such as a future deprecation warning. Normally empty. Worth logging when it isn't |
response_meta.elapsed_time | Server processing time for this request |
Check both the HTTP status and status. A 200 always comes with "status": "success",
and any error comes with a 4xx or 5xx status and "status": "error".
Two responses don't use this envelope:
- A path that matches no endpoint at all (for example a typo like
/optionchain) returns the platform's generic 404 body. - A
402for an empty Stolo Tokens balance has its own shape. See token charges.
HTTP status codes
| HTTP | Meaning | Retry? |
|---|---|---|
200 | Success. Read data | |
401 | Missing, invalid, expired, or replaced token | After re-authenticating, once |
402 | The app owner is out of Stolo Tokens | No, not until the balance is topped up |
403 | The app owner has no active Stolo Pro or Stolo Trial (15 days) plan | No |
404 | The thing you asked for doesn't exist, for example an unknown spot symbol | No |
405 | Wrong HTTP method, for example POST to an Analysis endpoint or to /trade/positions. The Allow header names the right one | No, switch the method |
422 | The request is invalid: a bad field, a wrong symbol type, an expiry that isn't listed | No, fix the request |
429 | Rate limit hit | Yes, after the Retry-After seconds |
500 | Unexpected server error | Yes, with backoff |
501 | Data for that symbol and expiry isn't available | Not for the same request |
502 | An internal Stolo service didn't respond correctly | Yes, with backoff |
Validation errors
When a field fails validation you get 422 with message: "Validation failed", and
data lists every bad field at once, not just the first:
{
"status": "error",
"message": "Validation failed",
"response_meta": { "api_version": "v1", "message": "", "elapsed_time": "1.05ms" },
"data": [
{ "message": "Please provide the symbol", "path": ["query", "symbol"] },
{ "message": "Resolution must be a positive integer (minutes)", "path": ["query", "resolution"] }
]
}
path points at the field: ["query", "resolution"] means the resolution query
parameter, and ["body", "quantity"] means quantity in a POST request's JSON body.
Show message to whoever is fixing the request.
Symbol formats
The API uses two kinds of symbol. They aren't interchangeable, and each endpoint says which one it wants.
| Kind | Format | Examples | Used by |
|---|---|---|---|
| Spot symbol | The plain underlying name | NIFTY, BANKNIFTY, FINNIFTY, RELIANCE | /analysis/symbol/info, /analysis/option-chain |
| Option symbol | <SPOT><YY><MM><DD><STRIKE><CE or PE> with no separators | NIFTY26092925100CE, BANKNIFTY26092955000PE | /analysis/candles/* |
Reading NIFTY26092925100CE left to right: NIFTY, expiry 2026-09-29, strike 25100, call.
Some strikes carry a decimal.
Take them from the call.symbol and put.symbol fields in the
option chain response. That guarantees the expiry and
strike actually exist, which a hand-built string doesn't.
Dates and times
- Dates are sent and returned as
YYYY-MM-DD. Fields that take adatealso accept a full ISO 8601 datetime, but only the day matters. - All market times are IST (Asia/Kolkata). Candle timestamps are IST too.
- When a
datefield is optional and you leave it out, the API uses the current market date: today on a trading day, or the last trading day on a weekend or holiday. - The market data for a session is treated as complete at 3:40 PM IST. This matters for the candle endpoints, which fall back to the previous trading day before that time.