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

# WebSocket API

> Real-time Solana subscriptions for accounts, slots, logs, and more

## Overview

OrbitFlare supports persistent WebSocket connections for real-time Solana data. WebSocket subscriptions push updates to your client as they occur on-chain — no polling required.

WebSocket endpoints use the `wss://` scheme with the same region codes as the HTTP API:

```
wss://{region}.rpc.orbitflare.com?api_key=YOUR_LICENSE_KEY
```

For the auto-routed mainnet endpoint:

```
wss://mainnet.rpc.orbitflare.com?api_key=YOUR_LICENSE_KEY
```

<Tip>
  Your license key is found in the **Licenses** section of your [OrbitFlare Dashboard](https://orbitflare.com/dashboard). Pass it as the `api_key` query parameter — the same key used for HTTP RPC.
</Tip>

## Connecting

```javascript theme={null}
const WebSocket = require("ws");

const ws = new WebSocket(
  "wss://mainnet.rpc.orbitflare.com?api_key=YOUR_LICENSE_KEY"
);

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

ws.on("message", (data) => {
  const msg = JSON.parse(data);
  console.log("Received:", msg);
});

ws.on("error", (err) => {
  console.error("WebSocket error:", err);
});

ws.on("close", (code, reason) => {
  console.log(`Connection closed: ${code} ${reason}`);
});
```

<Note>
  WebSocket connections idle for more than **60 seconds** without any message exchange are closed by the server. Send a ping or keep your subscriptions active to maintain the connection.
</Note>

## Subscription Methods

### accountSubscribe

Receive updates whenever a specific account's lamport balance or data changes.

```javascript theme={null}
ws.on("open", () => {
  ws.send(JSON.stringify({
    jsonrpc: "2.0",
    id: 1,
    method: "accountSubscribe",
    params: [
      "83astBRguLMdt2h5U1Tpdq5tjFoJ6noeGwaY3mDLVcri",
      { encoding: "base64", commitment: "confirmed" }
    ],
  }));
});
```

**Update fields:**

| Field        | Description                                                |
| ------------ | ---------------------------------------------------------- |
| `lamports`   | Current lamport balance                                    |
| `data`       | Account data (encoding determined by the `encoding` param) |
| `owner`      | Owning program public key                                  |
| `executable` | Whether the account is an executable program               |
| `rentEpoch`  | Epoch at which rent is next owed                           |

***

### logsSubscribe

Receive transaction log messages in real time. Optionally filter to a specific program.

```javascript theme={null}
// All transactions
ws.send(JSON.stringify({
  jsonrpc: "2.0",
  id: 2,
  method: "logsSubscribe",
  params: ["all"],
}));

// Filter to a specific program
ws.send(JSON.stringify({
  jsonrpc: "2.0",
  id: 3,
  method: "logsSubscribe",
  params: [
    { mentions: ["675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8"] }, // Raydium AMM
    { commitment: "confirmed" }
  ],
}));
```

**Update fields:**

| Field       | Description                                  |
| ----------- | -------------------------------------------- |
| `signature` | Transaction signature (base-58)              |
| `err`       | `null` if successful, error object if failed |
| `logs`      | Array of log message strings                 |

***

### slotSubscribe

Receive a notification each time a slot is processed.

```javascript theme={null}
ws.send(JSON.stringify({
  jsonrpc: "2.0",
  id: 4,
  method: "slotSubscribe",
  params: [],
}));
```

**Update fields:**

| Field    | Description                 |
| -------- | --------------------------- |
| `slot`   | Current slot number         |
| `parent` | Parent slot number          |
| `root`   | Highest confirmed root slot |

***

### signatureSubscribe

Receive a one-time notification when a specific transaction signature reaches a given commitment level.

```javascript theme={null}
ws.send(JSON.stringify({
  jsonrpc: "2.0",
  id: 5,
  method: "signatureSubscribe",
  params: [
    "TRANSACTION_SIGNATURE_HERE",
    { commitment: "finalized" }
  ],
}));
```

The subscription automatically closes after the first notification is sent.

***

### programSubscribe

Receive updates for all accounts owned by a specific program.

```javascript theme={null}
ws.send(JSON.stringify({
  jsonrpc: "2.0",
  id: 6,
  method: "programSubscribe",
  params: [
    "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", // SPL Token
    {
      encoding: "jsonParsed",
      commitment: "confirmed",
      filters: [{ dataSize: 165 }], // Standard token account size
    }
  ],
}));
```

***

### blockSubscribe

Receive full block data as each block is confirmed. **Requires an add-on — contact support to enable.**

```javascript theme={null}
ws.send(JSON.stringify({
  jsonrpc: "2.0",
  id: 7,
  method: "blockSubscribe",
  params: ["all", { commitment: "confirmed", encoding: "base64" }],
}));
```

***

### rootSubscribe

Receive the highest confirmed root slot each time it advances.

```javascript theme={null}
ws.send(JSON.stringify({
  jsonrpc: "2.0",
  id: 8,
  method: "rootSubscribe",
  params: [],
}));
```

***

### voteSubscribe

Receive raw vote transactions as they are observed in the gossip network. **High volume — filter carefully.**

```javascript theme={null}
ws.send(JSON.stringify({
  jsonrpc: "2.0",
  id: 9,
  method: "voteSubscribe",
  params: [],
}));
```

## Unsubscribing

Each subscription method has a corresponding `Unsubscribe` method. Pass the subscription ID returned in the initial subscription response.

```javascript theme={null}
// Subscribe and capture the subscription ID
ws.on("message", (data) => {
  const msg = JSON.parse(data);

  // Subscription confirmation contains the subscription ID
  if (msg.id === 1 && msg.result !== undefined) {
    const subscriptionId = msg.result;
    console.log("Subscribed, ID:", subscriptionId);

    // Unsubscribe later
    ws.send(JSON.stringify({
      jsonrpc: "2.0",
      id: 10,
      method: "accountUnsubscribe",
      params: [subscriptionId],
    }));
  }
});
```

Available unsubscribe methods: `accountUnsubscribe`, `logsUnsubscribe`, `slotUnsubscribe`, `signatureUnsubscribe`, `programUnsubscribe`, `blockUnsubscribe`, `rootUnsubscribe`, `voteUnsubscribe`.

## Keepalive

WebSocket connections are closed after 60 seconds of inactivity. Send a JSON-RPC ping periodically to keep the connection alive:

```javascript theme={null}
const pingInterval = setInterval(() => {
  if (ws.readyState === WebSocket.OPEN) {
    ws.send(JSON.stringify({ jsonrpc: "2.0", id: 0, method: "ping" }));
  }
}, 30_000);

ws.on("close", () => clearInterval(pingInterval));
```

## Reconnection

Implement automatic reconnection with exponential backoff for production applications:

```javascript theme={null}
function connect(url, onMessage) {
  let ws;
  let delay = 1000;
  let attempt = 0;

  function createConnection() {
    ws = new WebSocket(url);

    ws.on("open", () => {
      console.log("Connected (attempt", attempt + 1, ")");
      delay = 1000; // reset backoff on successful connection
      attempt = 0;
      // re-subscribe to all channels here
    });

    ws.on("message", onMessage);

    ws.on("close", () => {
      attempt++;
      const nextDelay = Math.min(delay * 2, 30_000);
      console.log(`Reconnecting in ${delay}ms...`);
      setTimeout(createConnection, delay);
      delay = nextDelay;
    });

    ws.on("error", (err) => console.error("WebSocket error:", err));
  }

  createConnection();
  return () => ws?.close();
}

const disconnect = connect(
  "wss://mainnet.rpc.orbitflare.com?api_key=YOUR_LICENSE_KEY",
  (data) => {
    const msg = JSON.parse(data);
    console.log("Update:", msg);
  }
);
```

## Connection Limits

WebSocket connections share the same per-IP limit as gRPC connections. See [Authentication & Limits](/authentication#websocket) for details.

## See Also

<CardGroup cols={2}>
  <Card title="HTTP RPC API" icon="server" href="/rpc/http">
    JSON-RPC 2.0 request format, batch requests, and all available methods.
  </Card>

  <Card title="Error Codes" icon="triangle-exclamation" href="/rpc/error-codes">
    HTTP status codes, JSON-RPC errors, and how to handle them.
  </Card>
</CardGroup>
