Realtime Market Data (WebSocket)¶
This section documents Nubra's WebSocket streams for real-time market data in the REST API. Use these streams for low-latency updates on indexes, instruments, order books, option chains, and Greeks.
Realtime market-data subscriptions can be built for supported NSE, BSE, and MCX instruments, depending on the stream type and subscription key format.
Method: WebSocket
Endpoint: /apibatch/ws
Example WebSocket Subscribe Messages¶
WebSocket streams are subscription messages sent after connecting to /apibatch/ws. These examples show the NSE, BSE, and MCX variants for the main market-data stream types.
batch_subscribe [token] index {"indexes":["NIFTY","HDFCBANK"]} NSE
batch_subscribe [token] index {"indexes":["SENSEX"]} BSE
batch_subscribe [token] index {"indexes":["FUT_CRUDEOIL_20260618"]} MCX
batch_subscribe [token] index_bucket {"indexes":["NIFTY"]} 5m NSE
batch_subscribe [token] index_bucket {"indexes":["SENSEX"]} 5m BSE
batch_subscribe [token] index_bucket {"indexes":["FUT_CRUDEOIL_20260618"]} 5m MCX
batch_subscribe [token] option [{"exchange":"NSE","asset":"NIFTY","expiry":"{expiry}"}]
batch_subscribe [token] option [{"exchange":"BSE","asset":"SENSEX","expiry":"{expiry}"}]
batch_subscribe [token] option [{"exchange":"MCX","asset":"CRUDEOIL","expiry":"{expiry}"}]
batch_subscribe [token] orderbook {"instruments":[{nse_ref_id},{bse_ref_id},{mcx_ref_id}]}
batch_subscribe [token] greeks {"instruments":[{nse_option_ref_id},{bse_option_ref_id},{mcx_option_ref_id}]}
Get WebSocket URL¶
After login, call the user info API with the same session_token and x-device-id.
Method: GET
Endpoint: /userinfo
curl --location 'https://api.nubra.io/userinfo' \
--header 'Authorization: Bearer <session_token>' \
--header 'x-device-id: <device_id>'
Use env_info.market_ws_url from the response as the realtime market-data WebSocket URL.
{
"env_info": {
"market_ws_url": "wss://api.nubra.io/apibatch/ws"
}
}
Available WebSocket Streams¶
| Stream | Channel | Description |
|---|---|---|
| Index Data | index |
Live index and instrument ticks including LTP, volume, and percentage change. |
| Index Bucket (OHLCV) | index_bucket |
Time-bucketed OHLCV data for indexes and instruments. |
| Order Book | orderbook |
Market depth with bid/ask levels, LTP, LTQ, and volume. |
| Greeks | greeks |
Tick-level option Greeks for option instruments. |
| Option Chain | option |
Full option chain updates by asset and expiry. |
WebSocket Stream Controls¶
These commands modify stream behavior across channels.
| Feature | Command | Scope | Description |
|---|---|---|---|
| Stream Interval | socket_interval |
Per channel | Controls the update frequency of WebSocket streams. |
| Post Market Data | post_market |
Connection-level | Enables static post-market data for testing and validation after market hours. |
| Order Book Depth | orderbook_depth |
Per connection | Controls the number of order-book levels streamed. |
Message Envelope (GenericData)¶
All WebSocket payloads are wrapped in a common envelope.
message GenericData {
string key = 1;
google.protobuf.Any data = 2;
}
keyidentifies the message type.datacontains one of the stream payloads defined below.
1. Index Data¶
Channel: index
Subscribe / Unsubscribe¶
SUBSCRIBE: batch_subscribe [token] index {"indexes":["BANKNIFTY","TCS","RELIANCE"]} NSE
UNSUBSCRIBE: batch_unsubscribe [token] index {"indexes":["BANKNIFTY","TCS","RELIANCE"]} NSE
Notes:
- exchange is sent at the message level, for example NSE, BSE, or MCX.
- Both index symbols and instrument symbols are sent in the indexes array.
- The response separates them into indexes and instruments.
- The JSON object must not contain spaces.
Payload (Proto)¶
message BatchWebSocketIndexMessage {
int64 timestamp = 1;
repeated WebSocketMsgIndex indexes = 2;
repeated WebSocketMsgIndex instruments = 3;
}
message WebSocketMsgIndex {
string indexname = 1;
int64 timestamp = 2;
int64 index_value = 3;
int64 high_index_value = 4;
int64 low_index_value = 5;
int64 volume = 6;
float changepercent = 7;
int64 tick_volume = 8;
int64 prev_close = 9;
string exchange = 10;
int64 volume_oi = 11;
int64 indicative_close_price = 12;
}
Indicative Close Price¶
indicative_close_price is an optional field for applicable NSE and BSE cash-market instruments. It is returned when the exchange provides an indicative close price, such as during an indicative or special market session. The field may be omitted when no indicative price is available. It is not expected on every index update, including regular NIFTY or BANKNIFTY updates.
2. Index Bucket (OHLCV)¶
Channel: index_bucket
Subscribe / Unsubscribe¶
SUBSCRIBE: batch_subscribe [token] index_bucket {"indexes":["BANKNIFTY","TCS","RELIANCE"]} 2m NSE
UNSUBSCRIBE: batch_unsubscribe [token] index_bucket {"indexes":["BANKNIFTY","TCS","RELIANCE"]} 2m NSE
Notes:
- interval and exchange are sent at the message level.
- Both index symbols and instrument symbols are sent in the indexes array.
- The response separates them into indexes and instruments.
- The JSON object must not contain spaces.
- Interval values are returned in the payload as an Interval enum.
Supported Intervals¶
The server accepts the following interval strings in the subscribe command:
1s,5s,10s,30s1m,2m,3m,5m,10m,15m,30m1h,2h,4h1d1w1mt1yr
Important: Although the
Intervalenum includes values fromINTERVAL_INVALID = 0throughINTERVAL_1_YEAR = 16, the following enum values are currently not available forindex_bucket: -INTERVAL_INVALID = 0-INTERVAL_1_SECOND = 1-INTERVAL_10_SECOND = 2-INTERVAL_1_YEAR = 16
Payload (Proto)¶
message BatchWebSocketIndexBucketMessage {
int64 timestamp = 1;
repeated WebSocketMsgIndexBucket indexes = 2;
repeated WebSocketMsgIndexBucket instruments = 3;
}
message WebSocketMsgIndexBucket {
string indexname = 1;
string exchange = 2;
Interval interval = 3;
int64 timestamp = 4;
int64 open = 5;
int64 high = 6;
int64 low = 7;
int64 close = 8;
int64 bucket_volume = 9;
int64 tick_volume = 10;
int64 cumulative_volume = 11;
int64 bucket_timestamp = 12;
}
Interval Enum (Proto)¶
enum Interval {
INTERVAL_INVALID = 0;
INTERVAL_1_SECOND = 1;
INTERVAL_10_SECOND = 2;
INTERVAL_1_MINUTE = 3;
INTERVAL_2_MINUTE = 4;
INTERVAL_3_MINUTE = 5;
INTERVAL_5_MINUTE = 6;
INTERVAL_10_MINUTE = 7;
INTERVAL_15_MINUTE = 8;
INTERVAL_30_MINUTE = 9;
INTERVAL_1_HOUR = 10;
INTERVAL_2_HOUR = 11;
INTERVAL_4_HOUR = 12;
INTERVAL_1_DAY = 13;
INTERVAL_1_WEEK = 14;
INTERVAL_1_MONTH = 15;
INTERVAL_1_YEAR = 16;
INTERVAL_5_SECOND = 17;
}
Interval Mapping (Subscribe String -> Enum)¶
Use these mappings to interpret WebSocketMsgIndexBucket.interval:
1m->INTERVAL_1_MINUTE (3)2m->INTERVAL_2_MINUTE (4)3m->INTERVAL_3_MINUTE (5)5m->INTERVAL_5_MINUTE (6)10m->INTERVAL_10_MINUTE (7)15m->INTERVAL_15_MINUTE (8)30m->INTERVAL_30_MINUTE (9)1h->INTERVAL_1_HOUR (10)2h->INTERVAL_2_HOUR (11)4h->INTERVAL_4_HOUR (12)1d->INTERVAL_1_DAY (13)1w->INTERVAL_1_WEEK (14)1mt->INTERVAL_1_MONTH (15)5s->INTERVAL_5_SECOND (17)
Note: Even if the subscribe command allows
1s,5s,10s,30s, the payload enum set shown above does not include30svalues.
3. Order Book¶
Channel: orderbook
Provides real-time market depth, LTP, LTQ, and traded volume for subscribed instruments.
Subscribe / Unsubscribe¶
SUBSCRIBE: batch_subscribe [token] orderbook {"instruments":[1120031,73009]}
UNSUBSCRIBE: batch_unsubscribe [token] orderbook {"instruments":[1120031,73009]}
By default, the order book stream sends up to 20 bid and ask levels per instrument.
Order Book Depth (Selective Levels)¶
Users can subscribe to a specific depth level from 1 to 20 instead of receiving all 20 levels.
MESSAGE: batch_subscribe [token] orderbook_depth 4
Notes:
- This setting applies to the orderbook channel.
- orderbook_depth 4 streams the top 4 bid and ask levels only.
- If not specified, the default depth is 20.
Payload (Proto)¶
message BatchWebSocketOrderbookMessage {
int64 timestamp = 1;
repeated WebSocketMsgOrderBook instruments = 2;
}
message WebSocketMsgOrderBook {
uint32 inst_id = 1;
int64 timestamp = 2;
repeated OrderBookLevel bids = 3;
repeated OrderBookLevel asks = 4;
int64 ltp = 5;
int64 ltq = 6;
int64 volume = 7;
int64 ref_id = 8;
}
message OrderBookLevel {
int64 price = 1;
int64 quantity = 2;
int64 orders = 3;
}
Notes¶
- The number of
bidsandasksentries depends on the subscribed order-book depth. bids[0]andasks[0]represent the best bid and best ask respectively.
4. Greeks¶
Channel: greeks
Subscribe / Unsubscribe¶
SUBSCRIBE: batch_subscribe [token] greeks {"instruments":[1120031,1120032]}
UNSUBSCRIBE: batch_unsubscribe [token] greeks {"instruments":[1120031,1120032]}
Payload (Proto)¶
message BatchWebSocketGreeksMessage {
int64 timestamp = 1;
repeated WebSocketMsgOptionChainItem instruments = 2;
}
message WebSocketMsgOptionChainItem {
int64 inst_id = 1;
int64 ts = 2;
int64 sp = 3;
int32 ls = 4;
int64 ltp = 5;
float ltpchg = 6;
float iv = 7;
float delta = 8;
float gamma = 9;
float theta = 10;
float vega = 11;
int64 oi = 12;
int64 volume = 13;
int64 ref_id = 14;
int64 prev_oi = 15;
int64 price_pcp = 16;
}
5. Option Chain¶
Channel: option
Subscribe / Unsubscribe¶
SUBSCRIBE: batch_subscribe [token] option [{"exchange":"NSE","asset":"RELIANCE","expiry":"20260224"},{"exchange":"BSE","asset":"SENSEX","expiry":"20260205"},{"exchange":"NSE","asset":"NIFTY","expiry":"20260203"}]
UNSUBSCRIBE: batch_unsubscribe [token] option [{"exchange":"NSE","asset":"RELIANCE","expiry":"20260224"},{"exchange":"BSE","asset":"SENSEX","expiry":"20260205"},{"exchange":"NSE","asset":"NIFTY","expiry":"20260203"}]
Notes:
- The JSON array must not contain spaces.
- Option chain updates are received in the older format: one packet per subscribed chain (not batched together).
- When deriving the underlying from the instruments master, use the asset field and pair it with the chosen expiry.
Payload (Proto)¶
message WebSocketMsgOptionChainUpdate {
string asset = 1;
string expiry = 2;
repeated WebSocketMsgOptionChainItem ce = 3;
repeated WebSocketMsgOptionChainItem pe = 4;
int64 atm = 5;
int64 currentprice = 6;
string exchange = 7;
}
Stream Interval Control¶
Users can control the update frequency of WebSocket streams by subscribing to a stream interval.
Set Stream Interval¶
MESSAGE: batch_subscribe [token] socket_interval option 1m
Notes:
- The stream interval applies to the specified channel, for example option, index, orderbook, greeks, or index_bucket.
- Interval settings are connection-level and affect subsequent subscriptions on that channel unless changed.
- If no interval is specified, the default behavior is tick-level streaming.
Supported Stream Intervals¶
The following interval strings are supported:
1s5s10s30s1m5m10m
Subscription Limits by Interval¶
Second-Based Intervals (Limited)¶
The following intervals have standard subscription limits:
1s5s10s30s
Notes: - These intervals are subject to per-connection and per-channel subscription limits. - Recommended for latency-sensitive strategies requiring near real-time updates.
Minute-Based Intervals (Unlimited)¶
The following intervals currently have no subscription limits:
1m5m10m
Notes: - You can subscribe to any number of instruments when using these intervals. - Ideal for strategies focused on candle-based logic, scans, or lower-frequency signals. - Significantly reduces bandwidth and processing overhead compared to second-level streams.
Example¶
Subscribe to the option chain stream with 1-minute updates:
MESSAGE: batch_subscribe [token] socket_interval option 1m
MESSAGE: batch_subscribe [token] option [{"exchange":"NSE","asset":"NIFTY","expiry":"20260203"}]
Best Practices¶
- Use second-based intervals only when necessary for execution or market-making strategies.
- Prefer minute-based intervals for monitoring, analytics, and signal generation.
- Combine
socket_intervalwith features like order book depth control to further optimize performance.
Post Market Data¶
Post-market data is available for testing and validation. This data represents an end-of-day static market snapshot and does not stream live updates.
Enable Post Market Mode¶
MESSAGE: batch_subscribe [token] post_market true
Notes: - When enabled, WebSocket streams return static post-market data instead of live ticks. - Data remains unchanged for the duration of the session. - This mode is intended for strategy testing, validation, and integration development. - Post-market data is available only after the market has closed.
Key Characteristics¶
- Static data with no live updates
- Same payload structures as live streams
- Useful for non-market-hour testing and demos
Example Workflow¶
Enable post-market mode and subscribe to an index stream:
MESSAGE: batch_subscribe [token] post_market true
MESSAGE: batch_subscribe [token] index {"indexes":["NIFTY","BANKNIFTY"]} NSE
Notes¶
- Post-market mode applies at the connection level.
- To resume live data, reconnect without enabling
post_market.