Get order status by order_id

Chapter 18 introduced the order book; this chapter is the focused, single-order lookup you'll actually call after every place_order().

def poll_order_status(kite, order_id: str, timeout_s: int = 10, interval_s: float = 0.5) -> dict:
    import time
    elapsed = 0.0
    while elapsed < timeout_s:
        history = kite.order_history(order_id)
        latest = history[-1]
        if latest["status"] in ("COMPLETE", "REJECTED", "CANCELLED"):
            return latest
        time.sleep(interval_s)
        elapsed += interval_s
    return kite.order_history(order_id)[-1]   # return best-known state even if still pending
order_id = kite.place_order(...)
result = poll_order_status(kite, order_id)
if result["status"] == "COMPLETE":
    print(f"Filled {result['filled_quantity']} @ avg {result['average_price']}")
elif result["status"] == "REJECTED":
    print(f"Rejected: {result['status_message']}")

Polling vs WebSocket order updates

Polling order_history() is simple and fine for a bot placing a handful of orders per day. For higher-frequency strategies, subscribe to order updates via the WebSocket ticker instead — much lower latency, no polling overhead:

def on_order_update(ws, data):
    print("Order update:", data["order_id"], data["status"])

kws.on_order_update = on_order_update

Order updates arrive on the *same* KiteTicker connection used for market data (chapter 36) — no separate connection needed.

Terminal vs non-terminal states — know which is which

  • Terminal (stop polling/waiting): COMPLETE, REJECTED, CANCELLED.
  • Non-terminal (keep waiting or act): OPEN, TRIGGER PENDING, OPEN PENDING, VALIDATION PENDING, MODIFY PENDING, CANCEL PENDING.

A bot that treats any non-COMPLETE status as "failed" will incorrectly abandon orders that are still legitimately in flight (e.g. OPEN resting on the book, or a pending modify/cancel request you just issued).

Next: 054 — Modify a pending order