> ## Documentation Index
> Fetch the complete documentation index at: https://docs.qfex.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Websocket Overview

QFEX provides 2 endpoints for websocket:

* [mds.qfex.com](wss://mds.qfex.com) for public market and reference data.
* [trade.qfex.com](wss://trade.qfex.com) for order entry and private data.

MDS is public and does not require authentication.
Trade requires an API key and a connection must [authenticate](/websocket/channels/trade/authenticate) within 1 minute of connecting.

If you want the Trade WebSocket session to operate on a subaccount, include `account_id` in the auth payload. When omitted, the connection uses the primary account.

## Getting Started

To access private data or place orders, you must connect to `trade.qfex.com` and authenticate. The following examples show how to connect, authenticate using HMAC-SHA256, and maintain the connection.

<AccordionGroup>
  <Accordion icon="python" title="Setup Python">
    ```python theme={null}
    # pip install websocket-client
    import hashlib
    import hmac
    import json
    import secrets
    import time
    import websocket

    PUB_KEY = "qfex_pub_xxxxx"
    SECRET_KEY = "qfex_secret_yyyyyy"

    def build_auth_message():
        nonce = secrets.token_hex(16)
        unix_ts = int(time.time())
        payload = f"{nonce}:{unix_ts}".encode()
        signature = hmac.new(SECRET_KEY.encode(), payload, hashlib.sha256).hexdigest()
        return {
            "type": "auth",
            "params": {
                "hmac": {
                    "public_key": PUB_KEY,
                    "nonce": nonce,
                    "unix_ts": unix_ts,
                    "signature": signature,
                }
            },
        }

    def on_open(ws):
        print("Connected")
        ws.send(json.dumps(build_auth_message()))

    def on_message(ws, message):
        print("Received:", message)

    ws = websocket.WebSocketApp(
        "wss://trade.qfex.com?api_key=" + PUB_KEY,
        on_open=on_open,
        on_message=on_message
    )

    ws.run_forever()
    ```
  </Accordion>

  <Accordion icon="node" title="Setup Node">
    ```javascript theme={null}
    // npm i ws
    import crypto from "crypto";
    import WebSocket from "ws";

    const pubKey = "qfex_pub_xxxxx";
    const secretKey = "qfex_secret_yyyyyy";

    function buildAuthMessage() {
      const nonce = crypto.randomBytes(16).toString("hex");
      const unixTs = Math.floor(Date.now() / 1000);
      const payload = `${nonce}:${unixTs}`;
      const signature = crypto
        .createHmac("sha256", secretKey)
        .update(payload)
        .digest("hex");

      return {
        type: "auth",
        params: {
          hmac: {
            public_key: pubKey,
            nonce,
            unix_ts: unixTs,
            signature,
          },
        },
      };
    }

    const ws = new WebSocket(`wss://trade.qfex.com?api_key=${pubKey}`);

    ws.on("open", () => {
      console.log("Connected");
      ws.send(JSON.stringify(buildAuthMessage()));
    });

    ws.on("message", (msg) => {
      console.log("Received:", msg.toString());
    });
    ```
  </Accordion>

  <Accordion icon="golang" title="Setup Go">
    ```go theme={null}
    // go get github.com/gorilla/websocket
    package main

    import (
      "crypto/hmac"
      "crypto/rand"
      "crypto/sha256"
      "encoding/hex"
      "fmt"
      "log"
      "time"
      "github.com/gorilla/websocket"
    )

    func main() {
      pubKey := "qfex_pub_xxxxx"
      secretKey := []byte("qfex_secret_yyyyyy")

      c, _, err := websocket.DefaultDialer.Dial("wss://trade.qfex.com?api_key="+pubKey, nil)
      if err != nil {
        log.Fatal("dial:", err)
      }
      defer c.Close()

      // Build Auth Message
      nonceBytes := make([]byte, 16)
      rand.Read(nonceBytes)
      nonce := hex.EncodeToString(nonceBytes)
      unixTs := time.Now().Unix()
      message := fmt.Sprintf("%s:%d", nonce, unixTs)

      h := hmac.New(sha256.New, secretKey)
      h.Write([]byte(message))
      signature := hex.EncodeToString(h.Sum(nil))

      auth := map[string]any{
        "type": "auth",
        "params": map[string]any{
          "hmac": map[string]any{
            "public_key": pubKey,
            "nonce":      nonce,
            "unix_ts":    unixTs,
            "signature":  signature,
          },
        },
      }

      c.WriteJSON(auth)

      for {
        _, message, err := c.ReadMessage()
        if err != nil {
          log.Println("read:", err)
          return
        }
        fmt.Printf("recv: %s\n", message)
      }
    }
    ```
  </Accordion>
</AccordionGroup>

## Authentication

Authentication is required for the `trade.qfex.com` endpoint.

1. **Connect**: Include your public API key as a query parameter:

   ```
   wss://trade.qfex.com?api_key=YOUR_PUBLIC_KEY
   ```

2. **Authenticate**: Send an authentication message signed with your secret key within 1 minute.
   You can use either an **HMAC-SHA256 signature** (recommended) or a valid **JWT token**.

For full details on the authentication payload and parameters, see the [Authenticate](/websocket/channels/trade/authenticate) documentation.
