Place OCO Order
Overview
The OCO Order APIs let you place a pair of linked limit orders around the current market price, where triggering one leg automatically cancels the other. This is commonly used to simultaneously protect against downside risk (stop-loss) and capture upside (target) on an existing position, without needing to manage two independent orders.
Key benefits:
- Single Request, Two Legs: Place a stop-loss and a target order together in one API call instead of coordinating two separate orders.
- Automatic Mutual Cancellation: Once either leg triggers, the other is cancelled automatically by the trading engine.
- LTP-Aware Validation: The API validates that your two trigger prices straddle the current market price (one above, one below) before accepting the order, preventing invalid configurations.
- Full Lifecycle Control: Place, modify, and cancel an OCO order pair through three dedicated endpoints.
Endpoint & Method
POST
/placeOcoOrder
URL:
https://api.firstock.in/V1/placeOcoOrderHeaders:
| Name | Value |
|---|---|
| Content-Type |
application/json |
Body:
| Field | Type | Mandatory | Description | Example |
|---|---|---|---|---|
| userId |
string |
Yes |
Unique identifier for |
AB1234 |
| jKey |
string |
Yes |
Active session token obtained from a successful login. |
6c83407h89jbt8om0n8... |
| exchange |
string |
Yes |
Exchange segment for |
NSE |
| tradingSymbol |
string |
Yes |
Trading symbol for |
VIKASECO-EQ |
| validity |
string |
No |
Order validity. Defaults |
GTT |
| ltp |
string |
No |
Last traded price to |
1.03 |
| OrderParamsLeg1 |
object |
Yes |
Parameters for the first |
- |
| OrderParamsLeg2 |
object |
Yes |
Parameters for the second leg |
- |
Request:
{
"userId": "{{userId}}",
"jKey": "{{jKey}}",
"exchange": "NSE",
"tradingSymbol": "VIKASECO-EQ",
"validity": "GTT",
"OrderParamsLeg1": {
"transactionType": "S",
"priceType": "LMT",
"product": "C",
"retention": "DAY",
"triggerPrice": "0.95",
"quantity": "1",
"price": "0.94"
},
"OrderParamsLeg2": {
"transactionType": "S",
"priceType": "LMT",
"product": "C",
"retention": "DAY",
"triggerPrice": "1.10",
"quantity": "1",
"targetPrice": "1.11"
}
}
Example Usage
curl --location 'https://api.firstock.in/V1/placeOcoOrder' \
--header 'Content-Type: application/json' \
--data '{
"userId": "{{userId}}",
"jKey": "{{jKey}}",
"exchange": "NSE",
"tradingSymbol": "VIKASECO-EQ",
"validity": "GTT",
"OrderParamsLeg1": {
"transactionType": "S",
"priceType": "LMT",
"product": "C",
"retention": "DAY",
"triggerPrice": "0.95",
"quantity": "1",
"price": "0.94"
},
"OrderParamsLeg2": {
"transactionType": "S",
"priceType": "LMT",
"product": "C",
"retention": "DAY",
"triggerPrice": "1.10",
"quantity": "1",
"targetPrice": "1.11"
}
}'
Response
{
"status": "success",
"message": "OCO order placed",
"data": {
"OCOid": "26100600000035",
"Status": "OI created"
}
}
{
"status": "failed",
"code": "400",
"name": "BAD_REQUEST",
"error": {
"field": "triggerPrice",
"message": "One leg trigger price must be above LTP and the other below LTP"
}
}
Usage & Best Practices
Exactly one leg's triggerPrice must be at/above the current LTP and the other strictly below it. Both legs on the same side of LTP will be rejected with a 400 before the order ever reaches the trading engine. If you don't send ltp in the payload, the server resolves it live from its own market-data feed, so your trigger prices must straddle the real current price, not a stale one you may be holding client-side.