I was running into the same issue and worked out that it can be done without the need for a socket connection to monitor whether or not one of the TP/SL has been filled, in order to cancel the other.
It does require three separate calls to the api to create each as the solved answer points out, but the parameters sent in the calls can be set as such that one will cancel the other two if it executes.
For example, the SL being hit will cancel the original order and the TP and the TP being hit will cancel the original order and the SL, etc. Here are the parameters I used in each call to achieve this (with example values):
Original order -
-
symbol=BNBUSDT
-
side=BUY
-
positionSide=BOTH
-
type=MARKET
-
quantity=1
-
reduceOnly=false
SL Order -
-
symbol=BNBUSDT
-
side=SELL
-
positionSide=BOTH
-
type=STOP_MARKET
-
timeInForce= GTE_GTC
-
quantity=1
-
reduceOnly=true
-
stopPrice=(your stop price)
-
workingType= MARK_PRICE
TP Order -
-
symbol=BNBUSDT
-
side=SELL
-
positionSide=BOTH
-
type=TAKE_PROFIT_MARKET
-
timeInForce= GTE_GTC
-
quantity=1
-
reduceOnly=true
-
stopPrice=(your take profit price)
-
workingType= MARK_PRICE
There isn’t two separate calls in the UI as pointed out in this thread, rather one call with a payload with three parts, one for each order entered in the UI (the trade, stop loss, take profit).
To see this, have a look in the network call in developer tools. In the call (place-order) under its payload tab, you’ll see it passes a list called ‘subOrderList’. Inside this are the three JSON blobs for each respective order. You’ll find the parameters needed in there.
Hopefully this helps anyone else running into this issue