# Relayer WebSocket API

The XOXNO Relayer is a high-performance transaction co-signing and broadcast service for the MultiversX blockchain. It exposes a WebSocket API for real-time data subscriptions and transaction submission, and a REST API for batch operations.

**Core capabilities:**

* Co-sign transactions using shard-specific Ed25519 relayer keys (Relayer V3 pattern)
* Broadcast fully signed or co-signed transactions via P2P gossipsub directly to validators
* Stream real-time gas statistics, network state, account updates, and transaction status

***

## Connection Endpoints

| Endpoint                           | Purpose                                            |
| ---------------------------------- | -------------------------------------------------- |
| `wss://relayer.xoxno.com/ws`       | Full-duplex WebSocket: subscribe, relay, broadcast |
| `wss://relayer.xoxno.com/ws/stats` | Read-only network stats stream, pushed every 250ms |

All messages are JSON. The `/ws/stats` endpoint requires no authentication and delivers `networkStats` messages unconditionally — no subscribe action needed.

***

## Connection Limits

| Parameter                     | Value                  |
| ----------------------------- | ---------------------- |
| Max topics per connection     | 64                     |
| Rate limit (control messages) | 64 per 5-second window |
| Max message size              | 4 MB                   |
| Ping/pong heartbeat interval  | 30 seconds             |

{% hint style="warning" %}
Exceeding 64 control messages within a 5-second window will result in a rate-limit error. Subscribe and unsubscribe actions count against this limit.
{% endhint %}

***

## Supported Topics

| Topic              | Delivery                                   | Update Frequency |
| ------------------ | ------------------------------------------ | ---------------- |
| `gasStats`         | Broadcast to all subscribers               | Every 50ms       |
| `networkStats`     | Broadcast to all subscribers               | Every 250ms      |
| `accounts`         | Broadcast, global account updates          | Event-driven     |
| `address/{bech32}` | Unicast to the subscribing connection only | Event-driven     |
| `tx-status/{hash}` | Unicast, auto-expires after 60 seconds     | Event-driven     |

***

## Client Actions

| Action        | Description                                                                |
| ------------- | -------------------------------------------------------------------------- |
| `subscribe`   | Subscribe to a topic                                                       |
| `unsubscribe` | Unsubscribe from a topic                                                   |
| `relay`       | Co-sign a transaction using the shard-specific relayer key, then broadcast |
| `broadcast`   | Broadcast a pre-signed transaction (no co-signing)                         |

***

## Quick Start

The example below opens a connection, subscribes to gas statistics, and submits a relayed transaction.

```javascript
const ws = new WebSocket('wss://relayer.xoxno.com/ws');

ws.onopen = () => {
  // Subscribe to gas statistics for all shards
  ws.send(JSON.stringify({
    action: 'subscribe',
    topic: 'gasStats'
  }));

  // Submit a relayed (co-signed) transaction
  // The `relayer` field must match the shard-specific relayer address for the sender
  ws.send(JSON.stringify({
    action: 'relay',
    requestId: 'relay-001',
    tx: {
      nonce: 42,
      value: '0',
      receiver: 'erd1qqqqqqqqqqqqqpgq...',
      sender: 'erd1user...',
      gasPrice: 1000000000,
      gasLimit: 50000000,
      data: 'c3dhcA==',
      chainID: '1',
      version: 2,
      signature: 'user-hex-signature...',
      relayer: 'erd1l0x0n5yxsfcy93gm0vyvx9m9f7cte9h9vuq4am33ugpw3d5r3hvqx6f59h'
    }
  }));
};

ws.onmessage = (event) => {
  const msg = JSON.parse(event.data);

  if (msg.type === 'gasStats') {
    console.log('Gas stats for shard', msg.data.shard, msg.data.gasPrice);
  }

  if (msg.action === 'relay' && msg.requestId === 'relay-001') {
    console.log('Relay result:', msg.status, msg.hashes);
  }
};

ws.onerror = (err) => console.error('WebSocket error:', err);
ws.onclose = () => console.log('Connection closed');
```

{% hint style="info" %}
Always include a unique `requestId` in relay and broadcast actions so you can correlate asynchronous responses when multiple requests are in-flight.
{% endhint %}

***

## REST Endpoints

| Method | Path                        | Description                            |
| ------ | --------------------------- | -------------------------------------- |
| `POST` | `/v1/sign`                  | Sign a batch of transactions           |
| `POST` | `/v1/broadcast`             | Broadcast pre-signed transactions      |
| `GET`  | `/v1/network-stats/history` | Retrieve historical network statistics |

***

## Documentation

* [Gas Statistics](/developers/relayer-api/gas-stats.md) — Per-shard gas price and PPU streams
* [Network Statistics](https://github.com/XOXNO/docs/blob/main/developers/relayer-api/network-stats.md) — Full network state stream via `/ws/stats`
* [Account Subscriptions](/developers/relayer-api/account-subscriptions.md) — Real-time balance and nonce updates
* [Transaction Broadcasting](/developers/relayer-api/transaction-broadcasting.md) — Submit pre-signed transactions
* [Transaction Relaying](/developers/relayer-api/transaction-relaying.md) — Co-signed relayed transactions
* [Error Reference](https://github.com/XOXNO/docs/blob/main/developers/relayer-api/error-reference.md) — All error codes and resolutions


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.xoxno.com/developers/relayer-api.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
