Skip to Main Content
POST/NorenWClientAPI/PlaceOrder

Place Order

Submit a new order for execution on the exchange — limit and stop-loss-limit orders only, across equity, F&O, currency, and commodity segments.

API Endpoint

MethodPOST
URLhttps://api.shoonya.com/NorenWClientAPI/PlaceOrder
Content-Typeapplication/x-www-form-urlencoded
PayloadjData=<JSON payload>&jKey=<AccessToken> — requires a valid AccessToken from Login.

Overview

Place Order is the core trading endpoint: every supported order type (LMT, SL-LMT) and every product (intraday, delivery, margin) routes through this one call, differentiated by parameters. Call it from your strategy engine whenever a signal needs to hit the exchange, and pair it with Order Book and the Order Update Feed to track state.

Not supportedMKT orders are rejected — only LMT and SL-LMT are accepted. Cover Order (CO) and Bracket Order (BO) are also not available as prd values.

Rate Limits

10 orders/second (OPS) per client, enforced at the OMS layer per SEBI's algo-trading OPS threshold framework.

Need more than 10 OPS?Submit your strategy to the exchange for approval and obtain an Algo ID. Once empanelled, higher OPS thresholds apply under the exchange's Algo ID framework.

Parameters

Field Type Required Description Allowed Values
uid string Required User ID of the authenticated account. Account-specific
actid string Required User ID of the authenticated account. Account-specific
exch string Required Exchange segment. Refer to Exchange Segment Codes. NSE, BSE, NFO, BFO, CDS, MCX
tsym string Required Unique id of contract on which order to be placed. (Use the results from Search Script to get the trading symbol & use URL encoding to avoid special-char errors for symbols like M&M.) Must exist in Symbol Master
qty integer Required Order quantity. For derivatives, quantity must be in multiples of the exchange lot size. > 0, lot-size multiple for derivatives
prc number Required Order price. Mandatory for both LMT and SL-LMT orders. > 0, within exchange circuit band
prd string Required Product type. CO and BO are not supported. C (CNC), M (NRML), I (MIS)
prctyp string Required Order type. MKT orders are not supported. LMT, SL-LMT
trantype string Required Transaction type. Refer to Transaction Type Codes. B (Buy), S (Sell)
ret string Required Order validity. DAY, IOC
trgprc number Conditional Trigger price. Mandatory when prctyp is set to SL-LMT. > 0; omit when prctyp = LMT
dscqty integer Optional Disclosed quantity visible to the market. 0 to qty
remarks string Optional User-defined remarks for order tracking and identification. Free text
ordersource string Required Order source identifier. API
algo_id string Conditional Exchange-approved Algo ID. Mandatory for orders placed under a registered algo strategy per SEBI's algo trading framework; omit for manual/non-algo orders. Exchange-issued

Request Examples

import requests
import json

payload = {
    "uid": "AB1234",
    "actid": "AB1234",
    "exch": "NSE",
    "tsym": "RELIANCE-EQ",
    "qty": "1",
    "dscqty": "0",
    "prc": "180.0",
    "prd": "C",          # C, M, I only — CO/BO not accepted
    "trantype": "B",
    "prctyp": "LMT",      # LMT or SL-LMT only — MKT is rejected
    "ret": "DAY",
    "ordersource": "API",
}
data = f"jData={json.dumps(payload)}&jKey={accessToken}"

response = requests.post(
    "https://api.shoonya.com/NorenWClientAPI/PlaceOrder",
    data=data,
)
result = response.json()

if result.get("stat") == "Ok":
    print("Order placed:", result["norenordno"])
else:
    print("Order rejected:", result.get("emsg"))
const payload = {
  uid: "AB1234",
  actid: "AB1234",
  exch: "NSE",
  tsym: "RELIANCE-EQ",
  qty: "1",
  dscqty: "0",
  prc: "180.0",
  prd: "C",          // C, M, I only — CO/BO not accepted
  trantype: "B",
  prctyp: "LMT",      // LMT or SL-LMT only — MKT is rejected
  ret: "DAY",
  ordersource: "API",
};

const data = `jData=${JSON.stringify(payload)}&jKey=${accessToken}`;

try {
  const res = await fetch("https://api.shoonya.com/NorenWClientAPI/PlaceOrder", {
    method: "POST",
    headers: { "Content-Type": "application/x-www-form-urlencoded" },
    body: data,
  });
  const result = await res.json();

  if (result.stat === "Ok") {
    console.log("Order placed:", result.norenordno);
  } else {
    console.error("Order rejected:", result.emsg);
  }
} catch (err) {
  console.error("Network/timeout error placing order:", err);
}
curl -X POST https://api.shoonya.com/NorenWClientAPI/PlaceOrder \
  -H "Content-Type: application/x-www-form-urlencoded" \
  --data-urlencode 'jData={"uid":"AB1234","actid":"AB1234","exch":"NSE","tsym":"RELIANCE-EQ","qty":"1","dscqty":"0","prc":"180.0","prd":"C","trantype":"B","prctyp":"LMT","ret":"DAY","ordersource":"API"}' \
  --data-urlencode "jKey=$ACCESS_TOKEN"

Response

json
// Success — HTTP 200
{ "stat": "Ok", "norenordno": "24121500001234" }

// Rejection — HTTP 200
{ "stat": "Not_Ok", "emsg": "RMS:Margin Exceeds" }
HTTP status alone isn't enoughThe OMS returns HTTP 200 for both accepted and rejected orders — rejection is signalled in the JSON body via stat, not the HTTP status code. Always parse stat; never treat a 200 as confirmation of order placement. Track via Order Book and the Order Update Feed.
FieldDescription
statOk or Not_Ok — always check before trusting norenordno.
norenordnoOrder number, present only on success. Track via Order Book and the Order Update Feed.
emsgRejection reason, present only on failure — see below.

Common Error Responses

ErrorReasonFix
Invalid Symboltsym not found in Instrument Master, or malformed expiry/option suffix.Re-fetch symbol from Instrument Master before ordering.
Invalid Quantityqty is zero, negative, or not a lot-size multiple.Round to nearest valid lot multiple.
Price Outside Circuit Limitprc outside the exchange circuit band.Fetch current circuit band before pricing.
Freeze Quantity Exceededqty exceeds the per-order freeze limit.Split into multiple orders under the limit.
Session ExpiredjKey/AccessToken invalid or expired.Re-authenticate via Token Renewal.
Exchange RejectionReached exchange but rejected there (no liquidity for IOC, halted, etc).Inspect the exchange-side reason in emsg.

Order Lifecycle

Strategy → Place Order API → Shoonya OMS → RMS Check → Exchange → Order Update WebSocket → Filled / Rejected / Cancelled
StateMeaning
Pending Validation → OpenOrder validated, passed RMS, resting at the exchange.
Trigger PendingSL-LMT waiting for trgprc to be touched.
Partially Filled → CompleteQuantity matching in progress, then fully filled.
RejectedFailed validation, RMS, or exchange check — see emsg.
CancelledCancelled by client, session logout, or EOD (for DAY orders).

Best Practices

  • Always check stat before trusting norenordno — the OMS returns HTTP 200 for both accepted and rejected orders, so a successful HTTP call is not confirmation of a placed order.
  • Since MKT isn't supported, price LMT orders with a small buffer beyond the current LTP for reliable fills on liquid symbols.
  • On a network timeout, don't assume the order failed. Shoonya has no dedicated idempotency/client-order-ID field, so tag every order with a unique remarks value at send time, then reconcile against Order Book by matching tsym + qty + remarks before deciding whether to resend.
  • Enforce your own client-side risk checks (max qty, max notional per order) — don't rely on RMS as your only guardrail, since RMS rejections happen after the order has already left your system.
  • Respect the 10 OPS rate limit with a client-side token-bucket limiter; if a strategy needs sustained throughput above that, get it registered for an Algo ID rather than working around the limit.
  • Validate tsym against a freshly-fetched Symbol Master immediately before placing F&O orders — don't cache symbols across expiries.