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

# WebSocket Quickstart

> Connect to your first WebSocket channel in under five minutes.

<Steps>
  <Step title="Get an API key">
    If you don't already have one, sign up or log in at [ngnmarket.com](https://ngnmarket.com), go to your [developer dashboard](https://ngnmarket.com/developer), and click **Generate API key**. The same key you use for REST calls works here too, so there's no separate credential to generate.

    <Note>
      Free accounts can hold **1 concurrent WebSocket connection**. See [Limits](/websocket/limits) for the full breakdown by plan.
    </Note>
  </Step>

  <Step title="Connect to a channel">
    Start with `/v1/ws/snapshot`. It takes no parameters, so it's the fastest way to see a message come through.

    <CodeGroup>
      ```javascript Browser theme={null}
      const ws = new WebSocket(
        'wss://api.ngnmarket.com/v1/ws/snapshot?api_key=ngm_live_YOUR_KEY'
      );

      ws.onopen = () => console.log('connected');
      ws.onmessage = (event) => console.log(JSON.parse(event.data));
      ws.onerror = (err) => console.error('error', err);
      ```

      ```javascript Node.js theme={null}
      import WebSocket from 'ws';

      const ws = new WebSocket(
        'wss://api.ngnmarket.com/v1/ws/snapshot?api_key=ngm_live_YOUR_KEY'
      );

      ws.on('open', () => console.log('connected'));
      ws.on('message', (data) => console.log(JSON.parse(data.toString())));
      ws.on('error', (err) => console.error('error', err));
      ```

      ```python Python theme={null}
      import asyncio
      import json
      import websockets

      async def main():
          url = "wss://api.ngnmarket.com/v1/ws/snapshot?api_key=ngm_live_YOUR_KEY"
          async with websockets.connect(url) as ws:
              print("connected")
              async for raw in ws:
                  print(json.loads(raw))

      asyncio.run(main())
      ```
    </CodeGroup>
  </Step>

  <Step title="Read the first message">
    The moment you connect, you'll get a `snapshot` message with the current data:

    ```json theme={null}
    {
      "type": "snapshot",
      "snapshot": {
        "date": "2026-08-21",
        "asi": 104250.30,
        "asi_change_percent": 0.82,
        "deals": 6420,
        "volume": 412300000,
        "value_traded": 8930000000,
        "updated_at": "2026-08-21T11:40:00.000Z"
      }
    }
    ```

    After that you won't hear from it again until the data actually changes. When it does change, you get an `update` message with the same shape. Each channel's own page explains exactly what's in its payload. See the [channel list](/websocket/introduction#channels).
  </Step>

  <Step title="Try a channel with parameters">
    `/v1/ws/prices` is the one channel that requires a query parameter: a comma-separated `symbols` list. A live feed of every NGX-listed company at once isn't useful to most integrations, so you pick the tickers you want.

    ```javascript Node.js theme={null}
    import WebSocket from 'ws';

    const ws = new WebSocket(
      'wss://api.ngnmarket.com/v1/ws/prices?api_key=ngm_live_YOUR_KEY&symbols=DANGCEM,GTCO,MTNN'
    );

    ws.on('message', (data) => console.log(JSON.parse(data.toString())));
    ```

    Omit `symbols`, ask for an unknown ticker, or request more symbols than your plan allows, and the connection fails immediately with a specific error. See [Prices](/websocket/prices) and [Errors](/websocket/errors).
  </Step>
</Steps>

<Warning>
  Your API key is visible in the connection URL. In a production app, don't connect to a WebSocket channel directly from browser code. Proxy the connection through your own backend instead, the same way you'd avoid shipping a REST API key in frontend code.

  See [Proxy a WebSocket connection through your backend](/guides/websocket-proxy) for a working example.
</Warning>

## Next steps

<CardGroup cols={2}>
  <Card title="Authentication" icon="key" href="/websocket/authentication">
    Why the key is a query parameter, and how rejections work
  </Card>

  <Card title="All channels" icon="satellite-dish" href="/websocket/introduction#channels">
    Prices, snapshot, indices, forex, disclosures, dividends
  </Card>

  <Card title="Limits" icon="gauge-high" href="/websocket/limits">
    Concurrent connections and symbol caps by plan
  </Card>

  <Card title="Errors" icon="circle-exclamation" href="/websocket/errors">
    Every WebSocket-specific error code, and how to fix it
  </Card>
</CardGroup>
