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

# Quickstart

> Connect, subscribe, receive updates, and unsubscribe from BlockDB WSS streams in minutes.

## What you'll do

* **Connect** to `wss://api.blockdb.io/v1/evm/`
* **Authenticate** with `Authorization: Bearer <API_KEY>` (or `?api_key=` fallback)
* **Subscribe** to a dataset (example: Blocks `dataset_id: "0101"`)
* **Receive** `update` messages
* **Unsubscribe** cleanly without closing the socket

## Prerequisites

* A valid BlockDB API key (set as `BLOCKDB_API_KEY`)
* A WebSocket client (CLI or SDK)

## 1) Connect

<CodeGroup>
  ```bash bash theme={null}
  # CLI: connect (wscat)
  export BLOCKDB_API_KEY="..."
  wscat -c wss://api.blockdb.io/v1/evm/ \
    -H "Authorization: Bearer $BLOCKDB_API_KEY"
  ```

  ```c C theme={null}
  #include <libwebsockets.h>
  #include <string.h>
  #include <stdio.h>

  static int callback_blockdb(struct lws *wsi, enum lws_callback_reasons reason,
                              void *user, void *in, size_t len) {
      switch (reason) {
          case LWS_CALLBACK_CLIENT_ESTABLISHED:
              printf("connected\n");
              break;
          case LWS_CALLBACK_CLIENT_RECEIVE:
              printf("Received: %.*s\n", (int)len, (const char *)in);
              break;
          case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
              printf("connection error\n");
              break;
          default:
              break;
      }
      return 0;
  }

  static struct lws_protocols protocols[] = {
      { "blockdb", callback_blockdb, 0, 4096, 0, NULL, 0 },
      { NULL, NULL, 0, 0, 0, NULL, 0 }
  };

  int main(void) {
      struct lws_context_creation_info info;
      memset(&info, 0, sizeof(info));
      info.port = CONTEXT_PORT_NO_LISTEN;
      info.protocols = protocols;

      struct lws_context *context = lws_create_context(&info);
      if (!context) return 1;

      struct lws_client_connect_info ccinfo;
      memset(&ccinfo, 0, sizeof(ccinfo));
      ccinfo.context = context;
      ccinfo.address = "api.blockdb.io";
      ccinfo.port = 443;
      ccinfo.path = "/v1/evm/?api_key=YOUR_API_KEY"; // fallback for clients without custom headers
      ccinfo.host = ccinfo.address;
      ccinfo.origin = ccinfo.address;
      ccinfo.ssl_connection = LCCSCF_USE_SSL;

      if (!lws_client_connect_via_info(&ccinfo)) return 1;

      while (lws_service(context, 0) >= 0) {}
      lws_context_destroy(context);
      return 0;
  }
  ```

  ```csharp .NET theme={null}
  using System;
  using System.Net.WebSockets;
  using System.Threading;
  using System.Threading.Tasks;

  class Program {
      static async Task Main() {
          using var ws = new ClientWebSocket();
          ws.Options.SetRequestHeader("Authorization", $"Bearer {Environment.GetEnvironmentVariable("BLOCKDB_API_KEY")}");
          await ws.ConnectAsync(new Uri("wss://api.blockdb.io/v1/evm/"), CancellationToken.None);
          Console.WriteLine("connected");
      }
  }
  ```

  ```python Python theme={null}
  # pip install websocket-client
  import os
  import websocket

  def on_open(ws):
      print("connected")

  ws = websocket.WebSocketApp(
      "wss://api.blockdb.io/v1/evm/",
      header={"Authorization": f"Bearer {os.getenv('BLOCKDB_API_KEY')}"},
      on_open=on_open,
  )
  ws.run_forever()
  ```

  ```javascript Node.js theme={null}
  // npm i ws
  const WebSocket = require('ws');

  const ws = new WebSocket('wss://api.blockdb.io/v1/evm/', {
    headers: { Authorization: `Bearer ${process.env.BLOCKDB_API_KEY}` }
  });

  ws.on('open', () => console.log('connected'));
  ws.on('close', (code, reason) => console.log('closed', code, reason?.toString?.()));
  ws.on('error', (err) => console.error('error', err));
  ```

  ```go Go theme={null}
  package main

  import (
  	"log"
  	"net/http"
  	"os"

  	"github.com/gorilla/websocket"
  )

  func main() {
  	header := http.Header{"Authorization": []string{"Bearer " + os.Getenv("BLOCKDB_API_KEY")}}
  	c, _, err := websocket.DefaultDialer.Dial("wss://api.blockdb.io/v1/evm/", header)
  	if err != nil {
  		log.Fatal("dial:", err)
  	}
  	defer c.Close()
  	log.Println("connected")
  }
  ```
</CodeGroup>

<Note>
  If your client cannot send headers during the handshake, use the query parameter fallback:
  `wss://api.blockdb.io/v1/evm/?api_key=YOUR_API_KEY`
</Note>

## 2) Subscribe (client → server)

This starts a stream. You must provide:

* `action: "subscribe"`
* `chain_id` (EVM chain)
* `dataset_id` (stream dataset)
* `params` (stream-specific filters; use `{}` if none)

<CodeGroup>
  ```bash bash theme={null}
  # Subscribe to Blocks (dataset_id 0101) on Ethereum mainnet (chain_id 1)
  wscat -c wss://api.blockdb.io/v1/evm/ \
    -H "Authorization: Bearer $BLOCKDB_API_KEY" \
    -x '{"action":"subscribe","chain_id":1,"dataset_id":"0101","params":{}}'
  ```

  ```c C theme={null}
  #include <libwebsockets.h>
  #include <string.h>
  #include <stdio.h>

  static int callback_blockdb(struct lws *wsi, enum lws_callback_reasons reason,
                              void *user, void *in, size_t len) {
      switch (reason) {
          case LWS_CALLBACK_CLIENT_ESTABLISHED:
              lws_callback_on_writable(wsi);
              break;
          case LWS_CALLBACK_CLIENT_WRITEABLE: {
              unsigned char buf[LWS_PRE + 256];
              unsigned char *p = &buf[LWS_PRE];
              size_t n = sprintf((char *)p, "{\"action\":\"subscribe\",\"chain_id\":1,\"dataset_id\":\"0101\",\"params\":{}}");
              lws_write(wsi, p, n, LWS_WRITE_TEXT);
              break;
          }
          case LWS_CALLBACK_CLIENT_RECEIVE:
              printf("Received: %.*s\n", (int)len, (const char *)in);
              break;
          default:
              break;
      }
      return 0;
  }
  ```

  ```csharp .NET theme={null}
  using System;
  using System.Net.WebSockets;
  using System.Text;
  using System.Threading;
  using System.Threading.Tasks;

  class Program {
      static async Task Main() {
          using var ws = new ClientWebSocket();
          ws.Options.SetRequestHeader("Authorization", $"Bearer {Environment.GetEnvironmentVariable("BLOCKDB_API_KEY")}");
          await ws.ConnectAsync(new Uri("wss://api.blockdb.io/v1/evm/"), CancellationToken.None);

          var subMsg = "{\"action\":\"subscribe\",\"chain_id\":1,\"dataset_id\":\"0101\",\"params\":{}}";
          await ws.SendAsync(new ArraySegment<byte>(Encoding.UTF8.GetBytes(subMsg)), WebSocketMessageType.Text, true, CancellationToken.None);
      }
  }
  ```

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

  def on_open(ws):
      ws.send(json.dumps({
          "action": "subscribe",
          "chain_id": 1,
          "dataset_id": "0101",
          "params": {}
      }))
  ```

  ```javascript Node.js theme={null}
  ws.on('open', () => {
    ws.send(JSON.stringify({
      action: 'subscribe',
      chain_id: 1,
      dataset_id: '0101',
      params: {}
    }));
  });
  ```

  ```go Go theme={null}
  package main

  import (
  	"log"
  	"net/http"
  	"os"

  	"github.com/gorilla/websocket"
  )

  func main() {
  	header := http.Header{"Authorization": []string{"Bearer " + os.Getenv("BLOCKDB_API_KEY")}}
  	c, _, err := websocket.DefaultDialer.Dial("wss://api.blockdb.io/v1/evm/", header)
  	if err != nil {
  		log.Fatal("dial:", err)
  	}
  	defer c.Close()

  	sub := `{"action":"subscribe","chain_id":1,"dataset_id":"0101","params":{}}`
  	if err := c.WriteMessage(websocket.TextMessage, []byte(sub)); err != nil {
  		log.Fatal("write:", err)
  	}
  }
  ```
</CodeGroup>

## 3) Handle messages (server → client)

After subscribing you will receive:

* `subscribe_response` (ack, success or error)
* `update` messages (the live data)

```json subscribe_response (success) theme={null}
{
  "action": "subscribe",
  "chain_id": 1,
  "dataset_id": "0101",
  "status": "success"
}
```

```json update theme={null}
{
  "chain_id": 1,
  "dataset_id": "0101",
  "is_reorg": false,
  "data": {
    "block_number": 12345678,
    "block_hash": "7b5c0972efb6a0b5be4a4d4a0de5d1abd922478a53f32b2c717a800c862ba9e0",
    "timestamp_utc": "2025-11-11T18:42:15.123Z",
    "_tracing_id": "010100000000000000000000000000000000"
  }
}
```

## 4) Unsubscribe (client → server)

Unsubscribe stops a stream without closing the WebSocket.

<CodeGroup>
  ```bash bash theme={null}
  wscat -c wss://api.blockdb.io/v1/evm/ \
    -H "Authorization: Bearer $BLOCKDB_API_KEY" \
    -x '{"action":"unsubscribe","chain_id":1,"dataset_id":"0101"}'
  ```

  ```c C theme={null}
  #include <libwebsockets.h>
  #include <string.h>
  #include <stdio.h>

  static int callback_blockdb(struct lws *wsi, enum lws_callback_reasons reason,
                              void *user, void *in, size_t len) {
      switch (reason) {
          case LWS_CALLBACK_CLIENT_ESTABLISHED:
              lws_callback_on_writable(wsi);
              break;
          case LWS_CALLBACK_CLIENT_WRITEABLE: {
              unsigned char buf[LWS_PRE + 256];
              unsigned char *p = &buf[LWS_PRE];
              size_t n = sprintf((char *)p, "{\"action\":\"unsubscribe\",\"chain_id\":1,\"dataset_id\":\"0101\"}");
              lws_write(wsi, p, n, LWS_WRITE_TEXT);
              break;
          }
          default:
              break;
      }
      return 0;
  }
  ```

  ```csharp .NET theme={null}
  using System;
  using System.Net.WebSockets;
  using System.Text;
  using System.Threading;
  using System.Threading.Tasks;

  class Program {
      static async Task Main() {
          using var ws = new ClientWebSocket();
          ws.Options.SetRequestHeader("Authorization", $"Bearer {Environment.GetEnvironmentVariable("BLOCKDB_API_KEY")}");
          await ws.ConnectAsync(new Uri("wss://api.blockdb.io/v1/evm/"), CancellationToken.None);

          var msg = "{\"action\":\"unsubscribe\",\"chain_id\":1,\"dataset_id\":\"0101\"}";
          await ws.SendAsync(new ArraySegment<byte>(Encoding.UTF8.GetBytes(msg)), WebSocketMessageType.Text, true, CancellationToken.None);
      }
  }
  ```

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

  def unsubscribe(ws):
      ws.send(json.dumps({
          "action": "unsubscribe",
          "chain_id": 1,
          "dataset_id": "0101"
      }))
  ```

  ```javascript Node.js theme={null}
  ws.send(JSON.stringify({
    action: 'unsubscribe',
    chain_id: 1,
    dataset_id: '0101'
  }));
  ```

  ```go Go theme={null}
  package main

  import (
  	"log"
  	"net/http"
  	"os"

  	"github.com/gorilla/websocket"
  )

  func main() {
  	header := http.Header{"Authorization": []string{"Bearer " + os.Getenv("BLOCKDB_API_KEY")}}
  	c, _, err := websocket.DefaultDialer.Dial("wss://api.blockdb.io/v1/evm/", header)
  	if err != nil {
  		log.Fatal("dial:", err)
  	}
  	defer c.Close()

  	unsub := `{"action":"unsubscribe","chain_id":1,"dataset_id":"0101"}`
  	if err := c.WriteMessage(websocket.TextMessage, []byte(unsub)); err != nil {
  		log.Fatal("write:", err)
  	}
  }
  ```
</CodeGroup>

**unsubscribe\_response (success):**

```json theme={null}
{
  "action": "unsubscribe",
  "chain_id": 1,
  "dataset_id": "0101",
  "status": "success"
}
```

## Next steps

* Browse available streams: [EVM Streams Overview](/wss-reference/evm/overview)
* Common error patterns and payload shape: [Errors](/wss-reference/overview/errors)
* Reconnect strategy and timeouts: [Connection Management](/wss-reference/overview/connection-management)
