# WebSocket API

> Stream crypto market data from f1ow over WebSocket — JSON-RPC 2.0 tool calls and subscriptions that push only when a result changes.

Source: https://www.f1ow.com/docs/api/websocket

The WebSocket API speaks **JSON-RPC 2.0** with the same methods as MCP, plus **subscriptions**: the server re-runs a tool on an interval and pushes only when the result changes.

| | |
| --- | --- |
| URL | `wss://mcp.f1ow.com/v1/ws` |
| Key in path | `wss://mcp.f1ow.com/key/<your-key>/v1/ws` |
| Subprotocol | `jsonrpc-2.0` |
| Auth | `Authorization: Bearer <your-key>` at the handshake, or the key in the path |
| Spec | [AsyncAPI 3.0](https://mcp.f1ow.com/asyncapi.json) |

## Methods

`initialize`, `tools/list`, `tools/call`, `ping`, `subscriptions/subscribe`, `subscriptions/unsubscribe`.

## Call a tool

```json
{ "jsonrpc": "2.0", "id": 1, "method": "tools/call",
  "params": { "name": "flow_orderbook", "arguments": { "symbol": "BTC" } } }
```

The `result` is the tool's JSON object, the same one the REST API returns as its body. There is no text report; that is MCP-only. A tool whose data source fails answers with JSON-RPC error `-32004`.

## Subscribe

```json
{ "jsonrpc": "2.0", "id": 2, "method": "subscriptions/subscribe",
  "params": { "name": "funding_current", "arguments": { "symbol": "BTC" }, "intervalSeconds": 60 } }
```

The reply returns `{ "subscriptionId", "intervalSeconds" }`. Each time the result changes, the server sends a `notifications/subscriptions/update` notification carrying `{ "subscriptionId", "result" }` (`result` is the same JSON object, or `error` when the data source failed). `intervalSeconds` defaults to and must be at least 15. Stop with:

```json
{ "jsonrpc": "2.0", "id": 3, "method": "subscriptions/unsubscribe",
  "params": { "subscriptionId": "<id>" } }
```

## Example: Node.js

```ts
import WebSocket from "ws";

const ws = new WebSocket("wss://mcp.f1ow.com/v1/ws", "jsonrpc-2.0", {
  headers: { Authorization: `Bearer ${process.env.F1OW_API_KEY}` },
});

ws.on("open", () => {
  ws.send(JSON.stringify({
    jsonrpc: "2.0", id: 1, method: "subscriptions/subscribe",
    params: { name: "derivatives_open_interest", arguments: { symbol: "ETH" }, intervalSeconds: 60 },
  }));
});

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

## Metering

A `tools/call` costs one unit. A subscription costs one unit **per pushed change**; checks that find nothing new are free. See [pricing & limits](https://www.f1ow.com/docs/pricing-limits).

> Get an API key: https://www.f1ow.com/dashboard
