Skip to main content

The official Python client for the NEBSL B2C REST API

Project description

pycloudrestapi — Complete Guide

Northeast B2C Trading API — Python Client


What Is This?

pycloudrestapi is a Python library that connects your code to the Northeast B2C REST API — a trading system used by IBT and NEBSL brokers, powered by the Odin/Wave trading engine.

Think of it as a remote control for your trading account. Instead of logging into a trading app manually, you write Python code that logs in, places orders, checks your portfolio, and receives live prices — all automatically.


What Can You Do With It?

Account — Login, validate your session, check your balance and margins, and logout.

Orders — Place fresh buy or sell orders, modify pending orders (change price or quantity), and cancel orders you no longer want.

Order Types — Regular limit, stop loss limit.

Reports — Fetch your full order book (all orders placed today), trade book (all executed trades), and order history (status timeline of a single order).

Portfolio — View your open positions, convert positions from intraday to delivery (or vice versa), and check your demat holdings.


Official Documentation ( Recommended )

Full API reference with all endpoints, request schemas, and response structures:

🔗 https://developer.synapsewave.com/docs/category/b2c-api


Installation

pip install nebsl-b2c-api

Credentials You Need

Your broker provides four things when they onboard you:

Base URL — The server address where all API calls go. It looks like a long AWS or cloud URL.

API Key — Your application's identity key. Sent in the request body during login.

Second AUTH — A PAN number sent in every request header to authenticate your app.

User ID (UCC) — Your Unique Client Code. This is your broker account number. Example: NE2247

⚠️ Never share these credentials or put them in your code directly. Store them in environment variables or a .env file.


Quick Start

from pycloudrestapi import IBTConnect

client = IBTConnect({
    "baseurl": "<your_base_url>",
    "api_key": "<your_api_key>",
    "second_auth": "<your_pan_number>",
    "debug": True
})

How Login Works

Every API call (except login itself) requires an access token. You get this token by logging in. The library stores it automatically and sends it with every subsequent request.

  • User ID — Your Unique Client Code
  • Password — Your normal password
# Login
user = client.login({
    "userId": "<your_user_id>",
    "password": "<your_password>"
})
print(user)

Session Management

# Validate session (keep alive) — call periodically
client.validateSession()

# Check available margins
client.balance()

# Logout when done
client.logout()

Understanding Orders

scrip_token — What Is It?

Every stock, futures contract, or options contract on an exchange has a unique number called a scrip token. The API uses this number to identify what you want to trade. For example, IDEA on NSE_EQ has token 14366, and IDEA on BSE_EQ has token 532822.

You get the token from your broker's scrip master file.

exchange — Which Market?

Value Description
NSE_EQ NSE Equity (stocks on NSE)
BSE_EQ BSE Equity (stocks on BSE)
NSE_FO NSE Futures & Options
BSE_FO BSE Futures & Options
MCX_FO MCX Futures (commodities)
NSE_COMM NSE Commodity Derivatives
BSE_COMM BSE Commodity Derivatives

product_type — How Long You Hold It?

Value Description
INTRADAY Also called MIS. Must close before market closes (~3:20 PM for NSE equity). Lower margin required.
DELIVERY Also called CNC. Stock goes into your demat account. Hold as long as you want. Full margin required.

order_type — How Does It Execute?

Value Description
RL Regular Limit — Order sits at your specified price. Executes only when market reaches your price.
SL Stop Loss Limit — Set a trigger price and a limit price. When market hits trigger, order activates at limit price.

validity — How Long Is the Order Active?

Value Description
DAY Valid only for today. Automatically cancelled if not filled by end of day.

trigger_price — When to Use It?

Only needed for SL order types. For all other orders, always set trigger_price to 0.

strike_price — Important Note for Options

When placing options orders, strike_price must be in paise, not rupees. Multiply the rupee value by 100.

Example: ₹56,000 strike → 5600000 in the API (56000 × 100 = 5600000)


Placing Orders

Equity Order

res = client.place_order({
    "scrip_info": {
        "exchange":    "NSE_EQ",   # NSE_EQ / BSE_EQ / NSE_FO / BSE_FO / MCX_FO
        "scrip_token": 14366,      # BSE token = 532822
        "symbol":      "",     # Optional if scrip_token given
        "series":      "EQ"        # EQ for equity
    },
    "transaction_type":  "BUY",        # BUY or SELL
    "product_type":      "DELIVERY",   # INTRADAY / DELIVERY / BTST / MTF
    "order_type":        "RL",         # RL / SL / S
    "quantity":          1,
    "price":             8.59,      # Set 0 for market order 
    "trigger_price":     0,            # Only for SL orders
    "disclosed_quantity": 0,           # 0 = show full quantity
    "validity":          "DAY",        # DAY / IOC / GTD / GTC
  
})
#Always check status first
if res and res["status"] == "success":
    order_id = res["data"]["orderId"]
    print("Order placed! Order ID:", order_id)  #To know order_id
else:
    print("Order failed!")
    print("Reason:", res["message"])

Futures Order

res = client.place_order({
    "scrip_info": {
        "exchange":     "NSE_FO",
        "scrip_token":  66688,          # Token for the futures contract
        "symbol":       "BANKNIFTY",
        "expiry_date":  "2025-10-31",   # Format: yyyy-mm-dd
        "strike_price": 0,              # 0 for futures
        "option_type":  ""              # Blank for futures
    },
    "transaction_type": "BUY",
    "product_type":     "INTRADAY",
    "order_type":       "RL",       # Market order
    "quantity":         50,             # 1 lot NIFTY = 50
    "price":            56000.00,              # 0 for market
    "trigger_price":    0,                   # Only for SL orders
    "validity":         "DAY"
})

Options Order

res = client.place_order({
    "scrip_info": {
        "exchange":     "NSE_FO",
        "scrip_token":  67528,
        "symbol":       "BANKNIFTY",
        "expiry_date":  "2026-06-30",
        "strike_price": 5600000,   # In PAISE: ₹25000 × 100 = 2500000
        "option_type":  "CE"       # CE = Call Option, PE = Put Option
    },
    "transaction_type": "SELL",
    "product_type":     "INTRADAY",
    "order_type":       "RL",
    "quantity":         30,
    "price":            120.00,
    "trigger_price":    0,                                # Only for SL orders
    "validity":         "DAY"
})

Modify Order

⚠️ The API requires you to send all fields, not just the ones you want to change. Fetch the order from get_order_book() first to get current values. The traded_quantity field must be fresh from the order book every time.

res = client.modify_order({
    "exchange":        "NSE_EQ",        
    "order_id":        "NXHCO00006A4",  # 
    "order_type":      "RL",            # 
    "quantity":   1,   
    "traded_quantity":    0,  # required from order book
    "price":              9.00,                   # new price
    "trigger_price":      0,
    "disclosed_quantity": 0,
    "validity":           "DAY",         # DAY
    "validity_days":      0     # 0
})

Cancel Order

res = client.cancel_order({
    "exchange": "NSE_EQ",        # Exchange segment
    "order_id": "NXHCO00006A4"  # Order ID from place_order / order book
})

Reports

Order Book

Shows every order you placed today, regardless of status. Supports pagination and filtering.

res = client.get_order_book({
    "offset":      "1",
    "limit":       "20",
    "orderStatus": None,
    "order_id":    None
})

if res and "data" in res:
    for o in res["data"]:
        print(
            o["order_id"],           # e.g. NXHCO00003A4
            o["symbol"],             # e.g. IDEA
            o["exchange"],           # e.g. NSE_EQ
            o["transaction_type"],   # BUY or SELL
            o["status"],             # EXECUTED / PENDING / CANCELLED
            o["order_type"],         # RL / SL
            o["product_type"],       # INTRADAY / DELIVERY
            o["total_quantity"],     # total qty placed
            o["traded_quantity"],    # qty filled
            o["pending_quantity"],   # qty remaining
            o["order_price"],        # price (string)
            o["trigger_price"],      # trigger price (string)
            o["order_timestamp"],    # "2026-04-17 12:46:34"
            o["exchange_timestamp"], # exchange confirm time
            o["error_reason"],       # blank if no error
        )
    print("Total orders:", res["metadata"]["total_records"])

Order History

Shows the complete status timeline of a single order. Useful for debugging rejected or stuck orders.

res = client.get_order_history({"orderId": "NXHCO00002A4"})

if res and "data" in res:
    for h in res["data"]:
        print(
            h["order_id"],
            h["status"],             # OMSXMITTED / EXECUTED etc.
            h["order_timestamp"],
            h["exchange_timestamp"],
            h["traded_quantity"],
            h["pending_quantity"],
            h["order_price"],
        )

Real-Time Order & Trade Updates (Socket)

Instead of repeatedly calling get_order_book() to check if your order filled, you can connect to a live socket and get notified the instant it happens. This is much faster than polling.

Why Use It?

The socket is faster because it pushes the update to you immediately, instead of you repeatedly asking "is it done yet?"

Requirements

pip install aiohttp python-socketio websockets --break-system-packages

⚠️ Without aiohttp installed, the socket will silently fail to connect — no error will stop your script, it just never receives any messages. Always install this first.

How to Connect

import asyncio

async def on_ready(status):
    print("Socket connected and authenticated")

async def on_message(data):
    print("Received:", data)

client.on_ready_message_socket = on_ready
client.on_msg_message_socket = on_message

await client.connect_message_socket()

You must be logged in first — the socket uses your access token from client.login().

Two Types of Messages

Every message has a message_type field telling you what it is:

message_type Meaning
ORD_NRML Order status update (placed, pending, rejected, etc.)
TRD_MSG Trade executed — your order (or part of it) just filled

For fill detection, TRD_MSG is what you want. Its presence for your order_id means a trade just happened — you don't need to separately check status.

Fields You Get in a TRD_MSG

{
    'order_id': 'NXHCO00006A4',
    'exchange': 'NSE_EQ',
    'scrip_token': 14366,
    'exchange_order_no': '1100000025651757',
    'status': 'EXECUTED',
    'transaction_type': 'BUY',
    'product_type': 'DELIVERY',
    'order_type': 'RL',
    'total_quantity': 1,
    'pending_quantity': '0',
    'disclosed_quantity': '0',
    'order_price': 13.90,
    'validity_days': 0,
    'symbol': 'IDEA',
    'series': 'EQ',
    'instrument': '',
    'expiry_date': '',
    'strike_price': 0,
    'option_type': '',
    'initiated_by': 'APIWEB',
    'modified_by': 'APIWEB',
    'order_identifier': '--------z1',
    'message_type': 'TRD_MSG',
    'is_amo_order': False
}

Matching to Your Order

Use order_id — it's the same value returned by place_order():

async def on_message(data):
    if data.get('order_id') == my_order_id and data.get('message_type') == 'TRD_MSG':
        print("Order filled!", data)

What's NOT in a TRD_MSG

  • Exact trade price should still be confirmed via get_trade_book() by trade_price — the socket's order_price field has only order placed_price

Recommended Pattern

Use the socket to know when something happened (fast), then call get_order_book() or get_trade_book() once to confirm the exact price and quantity (accurate):

async def on_message(data):
    if data.get('order_id') == my_order_id and data.get('message_type') == 'TRD_MSG':
        # Fast notification - order just filled
        confirmed = client.get_order_book({"order_id": my_order_id})
        print("Confirmed fill:", confirmed)

Portfolio

Positions

# type: "DAY"
res = client.get_positions({"type": "DAY"})

Holdings

res = client.get_holdings()

Order Lifecycle

When you place an order, it goes through several stages. Track these using get_order_history().

Status Description
OMS_XMITTED Order reached the OMS and is being processed. Not yet sent to exchange.
EXCHANGE_XMITTED OMS sent your order to the exchange. Waiting for confirmation.
PENDING Exchange confirmed. Sitting in order book waiting to be matched.
EXECUTED Fully matched and filled. Trade is complete.
CANCELLED Cancelled by you or automatically at end of day.
OMS_REJECT OMS rejected before reaching exchange. Check error_reason.
ORDER_ERROR Exchange rejected. Common reasons: insufficient margin, invalid symbol, market closed.
ADMIN_REJECT Broker admin rejected the order.

You can only modify or cancel orders in PENDING or OMS_XMITTED status. Executed or cancelled orders cannot be changed.


Order Book — Field Reference

Field Description
order_id Unique ID like NXHCO00003A4
exchange Segment like NSE_EQ
scrip_token Instrument token number
symbol Stock symbol like IDEA
series Series like EQ
transaction_type BUY or SELL
product_type INTRADAY, DELIVERY, etc.
order_type RL, SL
status EXECUTED, PENDING, etc.
total_quantity Total shares ordered
traded_quantity Shares filled so far
pending_quantity Shares still waiting
disclosed_quantity Shares visible in market
order_price Price as string like "9.56"
trigger_price SL trigger price as string like "0.00"
validity DAY, etc.
validity_days Number of days for GTD orders
order_timestamp When placed, e.g. "2026-04-17 12:46:34"
exchange_timestamp When exchange confirmed, e.g. "2026-04-17 12:46:33"
error_reason Blank if no error, filled if rejected
exchange_order_no Exchange's own order number
client_id Your UCC like NE1234
bracket_details Nested object with bracket/cover order details

Scrip Master (Token Repository)

Get scrip tokens from the scrip master files:

Exchange URL
NSE Equity https://odinscripmaster.s3.ap-south-1.amazonaws.com/scripfiles/NSE_EQ.json
NSE F&O https://odinscripmaster.s3.ap-south-1.amazonaws.com/scripfiles/NSE_FO.json
BSE Equity https://odinscripmaster.s3.ap-south-1.amazonaws.com/scripfiles/BSE_EQ.json
BSE F&O https://odinscripmaster.s3.ap-south-1.amazonaws.com/scripfiles/BSE_FO.json

v2 URLs (alternate version):

Replace the path with /scripfiles/v2/<EXCHANGE>.json, e.g.: https://odinscripmaster.s3.ap-south-1.amazonaws.com/scripfiles/v2/NSE_FO.json

Complete API Reference

Method Description
client.login({...}) Login and get access token
client.validateSession() Keep session alive
client.balance() Check available margins
client.logout() End session
client.place_order({...}) Place a regular order
client.modify_order({...}) Modify a pending order
client.cancel_order({...}) Cancel a pending order
client.place_bracket_order({...}) Place a bracket order
client.modify_bracket_order({...}) Modify a bracket order
client.delete_bracket_order({...}) Delete a bracket order
client.get_order_book({...}) Fetch order book
client.get_trade_book({...}) Fetch trade book
client.get_order_history({...}) Fetch order status timeline
client.get_positions({...}) Fetch open positions
client.position_conversion({...}) Convert position type
client.get_holdings() Fetch demat holdings

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

nebsl_b2c_api-1.0.8.tar.gz (24.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

nebsl_b2c_api-1.0.8-py3-none-any.whl (25.2 kB view details)

Uploaded Python 3

File details

Details for the file nebsl_b2c_api-1.0.8.tar.gz.

File metadata

  • Download URL: nebsl_b2c_api-1.0.8.tar.gz
  • Upload date:
  • Size: 24.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.20

File hashes

Hashes for nebsl_b2c_api-1.0.8.tar.gz
Algorithm Hash digest
SHA256 4a17ed76e3cfc6507c0b783eb89312906637493dcf547b79a709d3fd1b1b5493
MD5 f70d6946ca921482e7c74469dd0082a0
BLAKE2b-256 0a763ca6810e30e262c7699b2fa0e6213dabd1507196190dd60e7a7561e7780c

See more details on using hashes here.

File details

Details for the file nebsl_b2c_api-1.0.8-py3-none-any.whl.

File metadata

  • Download URL: nebsl_b2c_api-1.0.8-py3-none-any.whl
  • Upload date:
  • Size: 25.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.20

File hashes

Hashes for nebsl_b2c_api-1.0.8-py3-none-any.whl
Algorithm Hash digest
SHA256 33f0563597e565a127d82e6e507766bde9ac5b31285cdffa45e3fdced7b63e12
MD5 c8f858273e95e48191cb9e6eaaddd003
BLAKE2b-256 fea66459daa4151ec5fe8890f89c5ce53439360a8affe1512e8a5dafb3c96cfa

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page