Skip to Main Content
POST/NorenWClientAPI/CancelOrder

Cancel Order

Cancel an existing open or trigger-pending order before it is filled at the exchange.

API Endpoint

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

Overview

Cancel Order pulls an order that is still Open or Trigger Pending off the exchange. Unlike Modify Order, it takes only the order identifier — there's no order state to resend. Call it whenever a signal invalidates a resting order, at end-of-strategy cleanup, or as part of a modify-then-fail fallback path.

Cancel can lose the race to a fillIf the order fills at the exchange before your cancel request arrives, the cancel will be rejected with an exchange-side reason rather than silently succeeding. Always confirm the final state via Order Book or the Order Update Feed rather than assuming stat: "Ok" means nothing filled.

Rate Limits

Shares the same 10 orders/second (OPS) per-client throttle as Place Order and Modify Order, 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
norenordno string Required Noren order number of the order to cancel, as returned by Place Order or Order Book. Existing open / trigger-pending order
ordersource string Required Order source identifier. API

Request Examples

import requests
import json

payload = {
    "uid": "AB1234",
    "norenordno": orderNumber,   # from PlaceOrder response
    "ordersource": "API",
}
data = f"jData={json.dumps(payload)}&jKey={accessToken}"

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

if result.get("stat") == "Ok":
    print("Order cancelled:", result["result"])   # note: field is "result", not "norenordno"
else:
    print("Cancellation rejected:", result.get("emsg"))
const payload = {
  uid: "AB1234",
  norenordno: orderNumber,   // from PlaceOrder response
  ordersource: "API",
};

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

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

  if (result.stat === "Ok") {
    console.log("Order cancelled:", result.result); // note: field is "result", not "norenordno"
  } else {
    console.error("Cancellation rejected:", result.emsg);
  }
} catch (err) {
  console.error("Network/timeout error cancelling order:", err);
}
curl -X POST https://api.shoonya.com/NorenWClientAPI/CancelOrder \
  -H "Content-Type: application/x-www-form-urlencoded" \
  --data-urlencode 'jData={"uid":"AB1234","norenordno":"24121500001234","ordersource":"API"}' \
  --data-urlencode "jKey=$ACCESS_TOKEN"

Response

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

// Rejection — HTTP 200
{ "stat": "Not_Ok", "emsg": "Rejected : ORA:Order not found" }
Field name differs from Place OrderOn success, the cancelled order number is returned in result, not norenordno. As with Place Order and Modify Order, HTTP 200 is returned for both success and failure; always check stat, never the HTTP status alone.
FieldDescription
statOk or Not_Ok.
resultNoren order number of the cancelled order, present only on success.
emsgRejection reason, present only on failure — see below.

Common Error Responses

ErrorReasonFix
Order not foundnorenordno doesn't exist, belongs to another user, or is not in a cancellable state.Re-check current state via Order Book before cancelling.
Already CompleteOrder filled (fully or partially, then completed) before the cancel reached the exchange.Reconcile via Order Book; a cancel racing a fill is expected behavior, not a bug.
Already CancelledOrder was already cancelled — by a prior call, session logout, or EOD.Treat as a benign no-op if your own reconciliation shows the order is gone.
Session ExpiredjKey/AccessToken invalid or expired.Re-authenticate via Token Renewal.
Exchange RejectionCancel reached the exchange but was rejected there.Inspect the exchange-side reason in emsg.

Best Practices

  • Treat a cancel rejection due to "already complete" or "already cancelled" as informational, not exceptional — reconcile against Order Book to find the order's true final state rather than retrying blindly.
  • Parse the success order number from result, not norenordno — the same field-naming difference applies here as with Modify Order.
  • On a network timeout, don't assume the cancel failed or succeeded — re-fetch the order's state from Order Book before deciding whether to resend.
  • Confirm cancellation via the Order Update Feed rather than the HTTP response alone, since a fill can complete moments after you receive stat: "Ok" for an in-flight race.
  • Respect the shared 10 OPS rate limit — cancel calls draw from the same per-client bucket as Place Order and Modify Order.
  • For bulk cleanup (e.g. end-of-day flatten), iterate Order Book for all open/trigger-pending orders rather than tracking order numbers client-side, so you don't miss orders placed outside the current session.