Skip to main content

Stolo Trading API

The Stolo Trading API lets your code place and cancel option orders through the broker you've connected on Stolo, and read back your positions, order book, and margins. It sits next to the market data endpoints and uses the same key, secret, and bearer token. A typical script reads the option chain, decides on a strike, and sends the order here.

Every endpoint lives under /trade and needs the token from authentication. Placing is POST with a JSON body. Cancelling is DELETE, and positions, orders, and margins only read, so they're GET; these send their fields in the query string. Using the wrong method returns 405.

EndpointWhat it doesAnswer
POST /trade/placePlaces a buy or sell order for an optionQueued, not filled (see below)
DELETE /trade/cancelCancels an open orderQueued
GET /trade/positionsToday's positions at the brokerStraight from the broker
GET /trade/ordersToday's order book at the brokerStraight from the broker
GET /trade/marginsBalance, used margin, and available fundsStraight from the broker
Real orders, real money

/trade/place sends a live order to your broker. There is no sandbox. Test with one lot and a limit price you're comfortable with.

Before your first order​

Trade calls go through extra checks the market data calls don't. All of these must hold:

  1. Your broker is connected on Stolo and logged in today. Most brokers expire the session daily. See brokers supported for the list and setup guides.
  2. You send broker_slug on every call, and it matches the broker currently active on your Stolo account. If Zerodha is active and you send fyers, the call fails.
  3. The account that owns the app has an active Stolo Pro or Stolo Trial (15 days) plan, the same as for every other endpoint.

The accepted broker_slug values are zerodha, fyers, upstox, tradesmart, dhan, fivepaisa, shoonya, kotakneo, angelone, sharekhan, nuvama, flattrade, and bigul.

Placing an order​

POST /trade/place takes the option you want, which side, and how much:

FieldTypeRequiredDescription
broker_slugstringYesYour active broker, from the list above
symbolstringYesAn option symbol, such as NIFTY26100625100CE. Copy it from the option chain
bid_typestringYesBUY or SELL
product_typestringBroker dependentMIS (intraday, squared off by the broker) or NRML (carry forward)
order_typestringNoLIMIT or MARKET. Leaving it out means a market order
quantityintegerYesUnits, not lots: lots × lot size
limitnumberFor LIMITYour limit price in rupees. Rounded to the nearest 0.05 tick

Two rules catch most first-time callers. quantity is in units, so two lots of NIFTY at a lot size of 75 is 150, not 2. And only options are accepted: a stock or futures symbol comes back as 422 Only options trading is allowed at this moment.

curl -X POST 'https://algoapi.stolo.in/v1/trade/place' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer YOUR_TOKEN' \
-d '{"broker_slug":"zerodha","symbol":"NIFTY26100625100CE","bid_type":"BUY","product_type":"MIS","order_type":"LIMIT","quantity":75,"limit":142.5}'

A 200 means queued, not filled​

The response data is only this:

{ "status": "queued" }

Stolo accepts the order, records it, and hands it to its order pipeline, which sends it to the broker in the background. So the HTTP call returns before the broker has seen the order, and a 200 tells you nothing about whether it was filled or rejected. The result arrives on the order update WebSocket, covered below.

Two things happen in that pipeline that you don't have to code yourself:

  • Market orders become limit orders. Exchange rules don't allow a true market order from an API, so a MARKET order (or one with no order_type) is sent as a LIMIT a small buffer away from the last traded price. If the exact price matters, send your own LIMIT.
  • Big orders are split at the freeze limit. If your quantity is above the exchange's freeze quantity for that contract, Stolo splits it into several broker orders. Each slice gets its own broker order id.

Cancelling an order​

DELETE /trade/cancel takes broker_slug and the broker's own order id, broker_order_id, in the query string. Don't send them as a JSON body: it's ignored on a DELETE, and you get Please specify the broker.

curl -X DELETE 'https://algoapi.stolo.in/v1/trade/cancel?broker_slug=zerodha&broker_order_id=261006000123456' \
-H 'Authorization: Bearer YOUR_TOKEN'

Take broker_order_id from /trade/orders or from an order_update message. Like placing, the answer is {"status": "queued"}, and the order update tells you when the broker actually cancelled it. There's no modify endpoint: to change the price, cancel and place again.

Positions, orders, and margins​

These three are GET requests. They take only broker_slug, in the query string, and answer straight from your broker, so a 200 here is the broker's current view.

curl 'https://algoapi.stolo.in/v1/trade/positions?broker_slug=zerodha' \
-H 'Authorization: Bearer YOUR_TOKEN'

/trade/orders and /trade/margins work the same way.

EndpointdataFields you'll use
/trade/positionsArray of positionssymbol, product_type, open_quantity, average_entry_price, average_exit_price, realised_pnl, status (ongoing or complete)
/trade/ordersArray of orders, newest firstsymbol, broker_order_id, bid_type, order_type, quantity, filled_quantity, pending_quantity, price, limit_price, status, time
/trade/marginsOne objecttotal_balance, used_margin, available_balance, realized_pnl
{ "total_balance": 100000, "used_margin": 20000, "available_balance": 80000, "realized_pnl": 1500 }

Stolo maps each broker's response to these field names, but the content still varies a little by broker: status wording, how broker_symbol looks, decimal precision. Any margins field can be null when the broker doesn't report it. Before you hardcode anything, place one small order and read the raw responses for your broker.

Tracking orders with the order update WebSocket​

The Communication WebSocket is a separate connection from the HTTP API. It pushes an order_update message every time one of your app's orders changes at the broker. Connect and log in before you place anything:

wss://<communication-socket-host>
  1. Send {"action": "app-login", "token": "<your token>"} as soon as the socket opens. A bad or expired token gets {"type": "invalid-credentials"} and the socket closes.
  2. Read order_update messages as they arrive:
{
"type": "order_update",
"data": {
"broker": "zerodha",
"symbol": "NIFTY26100625100CE",
"broker_order_id": "261006000123456",
"status": "COMPLETED",
"bid_type": "BUY",
"quantity": 75,
"price": 142.5,
"message": "Order Executed"
}
}
  1. Answer the server's ping, sent every 60 seconds, with {"action": "pong"}.

You only get updates for orders placed through your own app, never your manual trades on Stolo or another app's orders. And updates aren't stored for you: if the socket was down when an order filled, that message is gone. After every reconnect, call /trade/orders once to catch up.

Worked example: buying the NIFTY ATM call​

It's 10:20 AM on a Tuesday, NIFTY is near 25,090, and your script wants one lot of the ATM call for the 6 October expiry.

  1. /analysis/symbol/info returns "atm": 25100. The option chain row for 25100 has "call": {"symbol": "NIFTY26100625100CE", "ltp": 141.8}.
  2. /trade/margins shows available_balance: 80000. One lot of 75 at about ₹142 needs roughly ₹10,650, so there's room.
  3. /trade/place with quantity: 75, order_type: "LIMIT", and limit: 142.5. The answer is {"status": "queued"} straight away.
  4. A moment later the socket delivers an order_update for 261006000123456 with status COMPLETED at 142.5.
  5. /trade/positions now shows the contract with open_quantity: 75.

If step 4 had shown a rejection instead, message carries the broker's reason, such as insufficient margin or a price outside the circuit band.

Errors​

Every trade call first runs the broker check, and each failure is a 422:

messageCause
Please specify the brokerNo broker_slug: in the body for place, in the query string for cancel, positions, orders, and margins
Sorry, but currently trading is not supported with <slug> brokerbroker_slug isn't one of the 13 above
Please connect your broker to tradeNo broker is connected on your Stolo account
Looks like your current active broker is <X>, please switch to <Y>...A different broker is active on Stolo
Please connect your brokerThe broker is active, but its login on Stolo has expired. Log in again on Stolo
Quantity cannot be 0/trade/place with a zero quantity
Symbol not found in <broker>The option isn't listed for that broker, often a typo or an expired contract

Missing fields come back as 422 Validation failed with the detail in data, as on every other endpoint (see requests, responses, and errors). Unattended scripts should treat any 422 from a trade call as "stop and tell a human", not something to retry in a loop.

Rate limits and cost​

Trade calls have their own fixed limit, 10 requests per second and 300 per minute per app, counted separately from the market data limits. They are not charged Stolo Tokens. See rate limits and usage for the headers and 429 handling, which work the same way.

Try the Trading API in your browser

Open the API Playground, authenticate, and switch to the Trades tab to call positions, orders, margins, and place or cancel an order.

Open the API Playground

Frequently asked questions​

What is the Stolo Trading API?
It is the part of the Stolo Developer API that trades through your connected broker. It has five endpoints: place an order, cancel an order, and read your positions, order book, and margins. It uses the same app key, secret, and bearer token as the market data endpoints.
Which brokers can I trade through with the API?
Zerodha, Fyers, Upstox, TradeSmart, Dhan, 5paisa, Shoonya, Kotak Neo, Angel One, Sharekhan, Nuvama, Flattrade, and Bigul. You pass the broker as broker_slug on every call, and it must be the broker currently active on your Stolo account.
Does a successful place order response mean my order was filled?
No. /trade/place returns {"status": "queued"} as soon as Stolo accepts the order and hands it to its order pipeline. The broker hasn't seen it yet at that point. Watch the order update WebSocket or call /trade/orders to learn whether it was filled, left open, or rejected.
How do I find out whether my order was filled or rejected?
Keep the Communication WebSocket connected and logged in with your token before you place orders. Each change at the broker arrives as an order_update message with the broker order id and status. If your socket was disconnected when an update happened, it is not replayed, so call /trade/orders after reconnecting to catch up.
Can I send a market order through the Stolo API?
You can send order_type MARKET, but Stolo converts it to a limit order a little away from the last traded price before it reaches the broker, because exchange rules don't allow a true market order from an API. If you care about the exact price, send LIMIT with your own limit price.
Is quantity in lots or in units?
Units. Send the number of lots multiplied by the lot size. With a NIFTY lot size of 75, two lots is quantity 150. Sending 2 asks for 2 units, which isn't a whole lot.
What happens if my order is bigger than the freeze limit?
Stolo splits it into several broker orders that each stay under the exchange's freeze quantity for that contract. You still send one /trade/place call. Each slice gets its own broker order id, so expect more than one order_update and more than one row in /trade/orders.
Can I modify an open order with the API?
Not today. The API supports placing and cancelling orders plus the three read endpoints. To change a price or quantity, cancel the open order with /trade/cancel and place a new one.
Why do trade calls fail with Please connect your broker?
Your broker login on Stolo has expired or is missing. Most brokers need you to log in again every day, and the API can't do that for you. Log in to the broker on app.stolo.in, then retry. If you run unattended automation, treat this 422 as a signal to stop and alert yourself.
Can the API trade stocks or futures?
No, only options. /trade/place rejects any symbol that isn't an option contract. Copy the option symbol from the option chain endpoint so it is in the exact format Stolo expects.
Do trading calls cost Stolo Tokens?
No. The five /trade endpoints are not charged Stolo Tokens. They still need an active Stolo Pro or Stolo Trial (15 days) plan on the account that owns the app, and they have their own fixed rate limit of 10 requests per second and 300 per minute.
Can I test the trading endpoints without writing code?
Yes. Open the API Playground on app.stolo.in, authenticate, and switch to the Trades tab. Positions, Orders, and Margins are safe to try. Place Order sends a real order with real money, so use a small quantity and a limit price well away from the market if you only want to see the flow.