Skip to content

Broker Real-time Order Updates Module - Websocket

Section Description
EndPoint Connection EndPoint details

Base Endpoint

wss://server.quantsapp.com/order-updates

Query Params

Name Value
ws_msg_type etoken
etoken etoken_value 1
portal api
sub_portal api
version 1.0.0
country in
uid mac_address of connected network 2
ref_id unique random alphanumeric string of len 16
Sample WS Url
Bash
wss://server.quantsapp.com/order-updates?
    ws_msg_type=etoken
    &etoken=spW48ZXL0uFa497...RXWQBpBd64EfHF424eAU9pp6MHuflZhtm26GM5
    &portal=api
    &sub_portal=api
    &version=1.0.0
    &country=in
    &uid=15%3AA6%3AD8%3ACC%3A31%3A11
    &ref_id=vsU5oDc9aRfAfbZi

Websocket Connection Response

Name Description Allowed Values
status
str
Status code -1 | 0 | 1
msg
str
Message Success | Failure Message
ws_msg_type
str
Login token to be used for further Authentication qapp_api_gateway_options_etoken_authorized

Sample Response

JSON
{
    "status": "1",
    "msg": "success",
    "ws_msg_type": "qapp_api_gateway_options_etoken_authorized",
}

On Failure Websocket will be closed with any of the below Error Codes

Error Code Error Description Actions to be done
4000 Invalid Session Relogin and try with new jwt_token
4001 User Already disconnected Retry again
4002 Query Params Missing Please make sure all required query params are passed
4003 Invalid Data Value of Query params are invalid
4004 Account Not Exists Create a new account
4005 Account Locked Please contact [email protected]
4006 Force disconnect due to max active connections reached Retry again with the disconnected conn to make it active again
4007 Force disconnect due to ideal state for sometime Retry again
4008 UID Mismatch Retry again
4009 Force Disconnect due to other device login Some other device use the secret key, Retry again to make this connection active
4500 Server Error Retry again after sometime

Broker Order Update Data binary

It's a byte encoded data with little-endian byte-order. The message structure is of below

Data Ref Data Type Byte Data Range Data Name
α short (2 bytes) 0 : 2 Length of Broker ClientID
β int32 (4 bytes) 2 : 6 Length of Broker Update data
γ char[] (α bytes) 6 : 6+α Broker ClientID
δ char[] (β bytes) 6+α : 6+α+β Broker Update data

Broker Order Update decoding example

sample data

Binary data = b"\x0e\x00\x05\x01\x00\x00choice,X253314\x1f\x8b\x08\x00K\x8eJh\x02\xffUPMK\x031\x10\xfd+%\xe7V\xf2\xb9!K/^\x04=(B\x05=\x85m6\xc5\xc0~5\x99\x1c\x8a\xf8\xdf\xcdd\xa9\xd6\x9c\xde\xcc{\xf3\xe6M\xbeH\xe7H\xbb!\xees\x0e\xceo\xdf\xb9\x12\x82I\xb2\xdd\x90\xa3\x9dc\xefc\xe8\x91\xbe?\xbc\xbe\xbc\xd1\xf2\xd8\xbeA\xd2\xdf\x92L\xd2J\t\xddHe\xb8F\xc1\xd9F\x7f\xb2\x95gX\xc2\xc5\x9e\xc20xl\xd0\xb5Q\x90V\x05\x86)A\xcc\xa3\x9f\x00\xcd\x9e\x1f\x1f\x0e\x1f-\xe3\xbb\xa7<\xed\xb8j]\xcb\x15U\xb4&J(8"\bI\x8bVwL]\xcb\xff\x0b\x8e6\'\xefl^\xfa\x0eP\xc9\xb44\x9a\t\xae\xe9\xfa\xea\xd4\xdcg\x07\x16.\x0b*\xc8\x14\xc7\x01\xcd\xebi6A\x07\xb9n\x84\xd8M)@\xa5\xac\x83Xz\xa2\xe0\xe2\xbf~@\xc3\xb92\xf2w\xf0j7\x84q\x1d:\xd7(7\x19\x84\xd4\xdc\x18\xc3\x0b\x97`^\xec\xdf5\xf4\xfb\x07\xff\xf2\xc6\xbe\x91\x01\x00\x00"

Base64 data = "DgAFAQAAY2hvaWNlLFgyNTMzMTQfiwgAS45KaAL/VVBNSwMxEP0rJedW8rkhSy9eBD0oQgU9hW02xcB+NZkcivjfzWSp1pzezHvz5k2+SOdIuyHucw7Ob9+5EoJJst2Qo51j72Pokb4/vL680fLYvkHS35JM0koJ3UhluEbB2UZ/spVnWMLFnsIweGzQtVGQVgWGKUHMo58AzZ4fHw4fLeO7pzztuGpdyxVVtCZKKDgiXGJJi1Z3TF3L/wuONifvbF76DlDJtDSaCa7p+urU3GcHFi4LKsgUxwHN62k2QQe5boTYTSlApayDWHqi4OK/fkDDuTLyd/BqN4RxHTrXKDcZhNTcGMMLl2Be7N819PsH//LGvpEBAAA="

Byte array data = [14, 0, 5, 1, 0, 0, 99, 104, 111, 105, 99, 101, 44, 88, 50, 53, 51, 51, 49, 52, 31, 139, 8, 0, 75, 142, 74, 104, 2, 255, 85, 80, 77, 75, 3, 49, 16, 253, 43, 37, 231, 86, 242, 185, 33, 75, 47, 94, 4, 61, 40, 66, 5, 61, 133, 109, 54, 197, 192, 126, 53, 153, 28, 138, 248, 223, 205, 100, 169, 214, 156, 222, 204, 123, 243, 230, 77, 190, 72, 231, 72, 187, 33, 238, 115, 14, 206, 111, 223, 185, 18, 130, 73, 178, 221, 144, 163, 157, 99, 239, 99, 232, 145, 190, 63, 188, 190, 188, 209, 242, 216, 190, 65, 210, 223, 146, 76, 210, 74, 9, 221, 72, 101, 184, 70, 193, 217, 70, 127, 178, 149, 103, 88, 194, 197, 158, 194, 48, 120, 108, 208, 181, 81, 144, 86, 5, 134, 41, 65, 204, 163, 159, 0, 205, 158, 31, 31, 14, 31, 45, 227, 187, 167, 60, 237, 184, 106, 93, 203, 21, 85, 180, 38, 74, 40, 56, 34, 92, 98, 73, 139, 86, 119, 76, 93, 203, 255, 11, 142, 54, 39, 239, 108, 94, 250, 14, 80, 201, 180, 52, 154, 9, 174, 233, 250, 234, 212, 220, 103, 7, 22, 46, 11, 42, 200, 20, 199, 1, 205, 235, 105, 54, 65, 7, 185, 110, 132, 216, 77, 41, 64, 165, 172, 131, 88, 122, 162, 224, 226, 191, 126, 64, 195, 185, 50, 242, 119, 240, 106, 55, 132, 113, 29, 58, 215, 40, 55, 25, 132, 212, 220, 24, 195, 11, 151, 96, 94, 236, 223, 53, 244, 251, 7, 255, 242, 198, 190, 145, 1, 0, 0]

import base64, json, gzip

def decode_broker_update_data(byte_data: bytes) -> dict:
    len_broker_client, len_data = struct.unpack('<hi', byte_data[:6])

    broker_client = struct.unpack(f"<{len_broker_client}s", byte_data[6:6+len_broker_client])[0].decode()

    broker_updated_data = json.loads(gzip.decompress(struct.unpack(f"<{len_data}s", byte_data[6+len_broker_client:6+len_broker_client+len_data])[0]))

    return broker_updated_data
// Import pako for GZIP decompression
const pako = require('pako'); // For Node.js

/**
* Decodes broker update data from a byte array.
* @param {ArrayBuffer} byteData - The raw binary data as an ArrayBuffer.
* @returns {Promise<Object>} - A promise that resolves with the decoded JSON object.
*/
async function decodeBrokerUpdateData(byteData) {
    // Create a DataView to read primitive types (like integers) with specific byte order.
    const dataView = new DataView(byteData);

    // 1. Read len_broker_client (2-byte short, little-endian) and len_data (4-byte int, little-endian)
    // The 'true' argument specifies little-endian byte order.
    const lenBrokerClient = dataView.getInt16(0, true); // Reads 2 bytes at offset 0
    const lenData = dataView.getInt32(2, true);     // Reads 4 bytes at offset 2

    // Calculate start and end offsets for various parts of the data.
    const brokerClientStart = 6;
    const brokerClientEnd = brokerClientStart + lenBrokerClient;
    const gzippedJsonStart = brokerClientEnd;
    const gzippedJsonEnd = gzippedJsonStart + lenData;

    // Basic validation to prevent reading beyond buffer bounds
    if (gzippedJsonEnd > byteData.byteLength) {
        throw new Error("Provided byte data is too short for the declared lengths.");
    }

    // 2. Extract and decode broker_client string
    // Create a Uint8Array view of the specific slice for broker_client.
    const brokerClientBytes = new Uint8Array(byteData, brokerClientStart, lenBrokerClient);
    // Use TextDecoder to convert bytes to a string (UTF-8 is common for .decode())
    const brokerClient = new TextDecoder('utf-8').decode(brokerClientBytes);

    // 3. Extract and decompress the GZIPped JSON data
    // Create a Uint8Array view of the specific slice for gzipped JSON data.
    const gzippedJsonBytes = new Uint8Array(byteData, gzippedJsonStart, lenData);

    let decompressedJsonString;
    try {
        // Use pako's ungzip function. 'to: "string"' tells pako to return a string.
        decompressedJsonString = pako.ungzip(gzippedJsonBytes, { to: 'string' });
    } catch (error) {
        console.error("Error during GZIP decompression:", error);
        throw new Error("Failed to decompress GZIP data. It might be corrupted or not valid GZIP.");
    }

    // 4. Parse the decompressed JSON string
    let brokerUpdatedData;
    try {
        brokerUpdatedData = JSON.parse(decompressedJsonString);
    } catch (error) {
        console.error("Error during JSON parsing:", error);
        throw new Error("Failed to parse JSON data. Decompressed data might not be valid JSON.");
    }

    return brokerUpdatedData;
}

Broker Order Update Structure

Name Description Allowed Values
ac
str
Broker Account BrokerClient
b_orderid
str
Broker OrderID str
e_orderid
str
Exchange OrderID str
q_ref_id
int
Quantsapp Reference ID int
qty
int
Quantity int
qty_filled
int
Quantity Filled int
instrument
str
Instrument str
bs
str
Buy or Sell OrderBuySell
price
float
Order Price float
price_filled
float
Order Price filled float
product_type
str
Order Product type ProductType
order_status
str
Order status OrderStatus
order_type
int
Order Type OrderType
o_ctr
int
Order update counter int
user_id
int
UserID placed the Order int
b_usec_update
int
Broker order update microseconds (µsec) int
q_usec
int
Quantsapp order update microseconds (µsec) int
stop_price
float
Stop Price float

Sample decodeed data

{
    "ac": "choice,X253314",
    "b_orderid": "ATQOU00001<6",
    "e_orderid": "1400000137645927",
    "q_ref_id": 1,
    "qty_filled": 0,
    "qty": 75,
    "instrument": "NIFTY:12-Jun-25:c:25050",
    "bs": "b",
    "price": 0.15,
    "price_filled": 0,
    "product_type": "nrml",
    "order_status": "transit",
    "order_type": "limit",
    "o_ctr": 3,
    "userid": 622594,
    "b_usec_update": 1749713270000000,
    "q_usec": 1749713234729992,
    "stop_price": 0.0
}

  1. EToken received from Execution Process 

  2. MAC Address Retrieval Code
    Python
    import uuid
    
    def get_mac_address() -> str:
        """Retreive the mac address of the connected network interface"""
    
        # Get the hardware address as a 48-bit positive integer
        mac_num = uuid.getnode()
    
        # 1. Convert the number to hex
        # 2. Pad it to 12 chars
        # 3. Convert it to a series of two char strings
        # 4. Join them with colons
        # 5. convert to uppercase
        return ':'.join(f"{b:02x}" for b in mac_num.to_bytes(6)).upper()
    
    print(get_mac_address)
    # 15:A2:C8:DD:31:11
    
    JavaScript
    const os = require('os');
    
    /**
    * Retrieves the MAC address of a connected non-internal network interface.
    * Prioritizes non-internal (e.g., Ethernet, Wi-Fi) interfaces with a MAC address.
    *
    * @returns {string | null} The MAC address in 'XX:XX:XX:XX:XX:XX' format, or null if not found.
    */
    function getMacAddress() {
        const interfaces = os.networkInterfaces();
        let macAddress = null;
    
        // Iterate over all network interfaces
        for (const interfaceName in interfaces) {
            const networkInterface = interfaces[interfaceName];
    
            for (const iface of networkInterface) {
                // Filter out internal (loopback) interfaces and ensure it has a MAC address
                if (!iface.internal && iface.mac && iface.mac !== '00:00:00:00:00:00') {
                    macAddress = iface.mac.toUpperCase();
                    // Found a valid MAC address, you might want to return the first one found
                    // or continue iterating if you have a specific interface in mind.
                    // For simplicity, we return the first valid one here.
                    return macAddress;
                }
            }
        }
    
        return macAddress; // Return null if no suitable MAC address was found
    }
    
    // --- Usage Example ---
    const mac = getMacAddress();
    
    if (mac) {
        console.log(`MAC Address: ${mac}`);
    } else {
        console.log("No MAC address found for a non-internal interface.");
    }
    
    // MAC Address: 15:A2:C8:DD:31:11