# Litmus Unify - Dashboard

> **Applies to:** Litmus Unify **2.0.x** (current). The version map shows which operations also exist in **<v2.0.0** and how they differ. Full `<v2.0.0` request bodies are in collections.json.

### Version map

| 2.0.x operation | In <v2.0.0? | Difference |
|---|---|---|
| `Version` (`version`) | Yes -- "Get Version" | None |
| `Server` (`server`) | Yes -- "Dashboard Data" | Renamed. 2.0.x selects `server { config sumInfo nodes }`. There is no `mode` or `info` field; the counters live on `sumInfo` (aggregate) and per-node `nodes`, both of type `ServerInfo` |
| `Clients` (`clients`) | Yes -- "Clients" | None |
| `Topics` (`topics`) | Yes -- "Topics" | None |

## Table of Contents

- [Version](#version)
- [Server](#server)
- [Clients](#clients)
- [Topics](#topics)

---

## Version

**POST** `{{uns_url}}/mqtt/gql`

# Version

Software version of the broker, injected at build time. Takes no arguments. Useful as a connectivity / health check.
## Endpoint

```http
POST {{uns_url}}/mqtt/gql
```
## Authentication

OAuth2 Bearer token (Keycloak password grant). In Postman the token is inherited from the collection auth; see the collection overview for the raw token request.
## Response

Returns `Version!`: `version` (semantic version, e.g. `2.0.1`), `hash` (build commit), and `backendVersion`.

## Errors

GraphQL operations return `200 OK` even on logical errors. Inspect the `errors` array in the response body:

```json
{ "errors": [ { "message": "...", "path": ["..."], "extensions": { "code": "..." } } ] }
```

> **Masked errors**: Litmus Unify masks error detail by default, most failures surface as `{"message": "masked error"}` with `data: null`. The `path` identifies which field failed. Validation failures additionally carry `extensions.code = GRAPHQL_VALIDATION_FAILED` and return HTTP `422`.

A missing or expired Bearer token returns HTTP `401` with the body `bad token`.


### Request Body

**GraphQL Query**

```graphql
query Version {
    version {
        version
        hash
        backendVersion
    }
}

```

### Response

**Status**: 200 OK

```json
{
  "data": {
    "version": {
      "version": "2.0.1",
      "hash": "",
      "backendVersion": "0.0.0"
    }
  }
}
```

---

## Server

**POST** `{{uns_url}}/mqtt/gql`

# Server

Full broker server state: socket / TLS configuration and the MQTT statistics (cluster-wide aggregate plus per-node) that drive the dashboard counters. Takes no arguments.
## Endpoint

```http
POST {{uns_url}}/mqtt/gql
```
## Authentication

OAuth2 Bearer token (Keycloak password grant). In Postman the token is inherited from the collection auth; see the collection overview for the raw token request.
## Response

| Field | Meaning |
|---|---|
| `config` | `ServerConfig`: listener configuration -- `updateEnabled`, `socketTCP`, `socketWS`, `socketHealthCheck`, `sslEnabled`, and the `ssl` block (TLS / WSS sockets, cert, CA). |
| `sumInfo` | `ServerInfo`: cluster-wide aggregate counters (`version`, `uptime`, byte / message / packet counts, `clientsConnected/Disconnected/Max/Total`, `subscriptions`, `host`, and the `mqttConfig` protocol limits). |
| `nodes` | `[ServerInfo!]!`: the same `ServerInfo` counters broken down per cluster node (one entry per broker node; three on this deployment). |

```graphql
query Server {
    server {
        config { sslEnabled socketTCP { port enabled } socketWS { port enabled } }
        sumInfo { version uptime clientsConnected subscriptions }
        nodes { host uptime clientsConnected }
    }
}
```

> `Server` has no `mode` or `info` field on 2.0.1 (verified against the live schema). `ServerInfo` itself has no `mode` or `nodes` field. `sumInfo.mqttConfig` is in the schema but its resolver returns a masked error on this broker, so omit it.
## Errors

GraphQL operations return `200 OK` even on logical errors. Inspect the `errors` array in the response body:

```json
{ "errors": [ { "message": "...", "path": ["..."], "extensions": { "code": "..." } } ] }
```

> **Masked errors**: Litmus Unify masks error detail by default, most failures surface as `{"message": "masked error"}` with `data: null`. The `path` identifies which field failed. Validation failures additionally carry `extensions.code = GRAPHQL_VALIDATION_FAILED` and return HTTP `422`.

A missing or expired Bearer token returns HTTP `401` with the body `bad token`.


### Request Body

**GraphQL Query**

```graphql
query Server {
    server {
        config {
            updateEnabled
            sslEnabled
        }
        sumInfo {
            version
            uptime
            bytesSent
            bytesRcvd
            msgSent
            msgRcvd
            msgDropped
            packetsSent
            packetsRcvd
            clientsConnected
            clientsDisconnected
            clientsMax
            clientsTotal
            subscriptions
            host
        }
        nodes {
            version
            uptime
            bytesSent
            bytesRcvd
            msgSent
            msgRcvd
            msgDropped
            packetsSent
            packetsRcvd
            clientsConnected
            clientsDisconnected
            clientsMax
            clientsTotal
            subscriptions
            host
        }
    }
}

```

### Response

**Status**: 200 OK

```json
{
  "data": {
    "server": {
      "config": {
        "updateEnabled": false,
        "sslEnabled": true
      },
      "sumInfo": {
        "version": "",
        "uptime": "",
        "bytesSent": 48,
        "bytesRcvd": 6758,
        "msgSent": 0,
        "msgRcvd": 0,
        "msgDropped": 0,
        "packetsSent": 7,
        "packetsRcvd": 12,
        "clientsConnected": 0,
        "clientsDisconnected": 0,
        "clientsMax": 0,
        "clientsTotal": 0,
        "subscriptions": 0,
        "host": ""
      },
      "nodes": [
        {
          "version": "2.0.1",
          "uptime": "2h6m30s",
          "bytesSent": 4,
          "bytesRcvd": 18,
          "msgSent": 0,
          "msgRcvd": 0,
          "msgDropped": 0,
          "packetsSent": 1,
          "packetsRcvd": 1,
          "clientsConnected": 0,
          "clientsDisconnected": 0,
          "clientsMax": 0,
          "clientsTotal": 0,
          "subscriptions": 0,
          "host": ".mqtt-2."
        },
        {
          "version": "2.0.1",
          "uptime": "2h7m0s",
          "bytesSent": 40,
          "bytesRcvd": 6720,
          "msgSent": 0,
          "msgRcvd": 0,
          "msgDropped": 0,
          "packetsSent": 5,
          "packetsRcvd": 10,
          "clientsConnected": 0,
          "clientsDisconnected": 0,
          "clientsMax": 0,
          "clientsTotal": 0,
          "subscriptions": 0,
          "host": ".mqtt-0."
        },
        {
          "version": "2.0.1",
          "uptime": "2h7m0s",
          "bytesSent": 4,
          "bytesRcvd": 20,
          "msgSent": 0,
          "msgRcvd": 0,
          "msgDropped": 0,
          "packetsSent": 1,
          "packetsRcvd": 1,
          "clientsConnected": 0,
          "clientsDisconnected": 0,
          "clientsMax": 0,
          "clientsTotal": 0,
          "subscriptions": 0,
          "host": ".mqtt-1."
        }
      ]
    }
  }
}
```

---

## Clients

**POST** `{{uns_url}}/mqtt/gql`

# Clients

List the MQTT clients known to the broker and their live connection state. Omit `ids` for the full list, or pass specific client ids to narrow it.
## Endpoint

```http
POST {{uns_url}}/mqtt/gql
```
## Authentication

OAuth2 Bearer token (Keycloak password grant). In Postman the token is inherited from the collection auth; see the collection overview for the raw token request.
## Arguments

| Argument | Type | Required | Notes |
|---|---|---|---|
| `ids` | `[String!]` | no | Client ids to fetch; omit for all clients. |

## Response

Returns `[Client!]!`. Each `Client` carries `id`, the owning `account`, `connected`, `protoLevel`, `remote` (IP), `lastSeen`, and the client's `pubTopics` / `pubTopicsRejected` / `subTopics`.

## Errors

GraphQL operations return `200 OK` even on logical errors. Inspect the `errors` array in the response body:

```json
{ "errors": [ { "message": "...", "path": ["..."], "extensions": { "code": "..." } } ] }
```

> **Masked errors**: Litmus Unify masks error detail by default, most failures surface as `{"message": "masked error"}` with `data: null`. The `path` identifies which field failed. Validation failures additionally carry `extensions.code = GRAPHQL_VALIDATION_FAILED` and return HTTP `422`.

A missing or expired Bearer token returns HTTP `401` with the body `bad token`.


### Request Body

**GraphQL Query**

```graphql
query Clients {
    clients {
        id
        account {
            id
            username
            enabled
            rules {
                id
                path
                perm
            }
            clients {
                id
                connected
                protoLevel
                remote
                lastSeen
                pubTopics {
                    path
                    byteCount
                    msgCount
                    pubRate
                    lastSeen
                    lastVal {
                        timestamp
                        deviceName
                        tagName
                        datatype
                        value
                    }
                    clients
                    UNS
                }
                pubTopicsRejected {
                    path
                    byteCount
                    msgCount
                    pubRate
                    lastSeen
                    lastVal {
                        timestamp
                        deviceName
                        tagName
                        datatype
                        value
                    }
                    clients
                    UNS
                }
                subTopics {
                    path
                    byteCount
                    msgCount
                    pubRate
                    lastSeen
                    lastVal {
                        timestamp
                        deviceName
                        tagName
                        datatype
                        value
                    }
                    clients
                    UNS
                }
            }
            acType
        }
        connected
        protoLevel
        remote
        lastSeen
        pubTopics {
            path
            byteCount
            msgCount
            pubRate
            lastSeen
            lastVal {
                timestamp
                deviceName
                tagName
                datatype
                value
            }
            clients
            UNS
        }
        pubTopicsRejected {
            path
            byteCount
            msgCount
            pubRate
            lastSeen
            lastVal {
                timestamp
                deviceName
                tagName
                datatype
                value
            }
            clients
            UNS
        }
        subTopics {
            path
            byteCount
            msgCount
            pubRate
            lastSeen
            lastVal {
                timestamp
                deviceName
                tagName
                datatype
                value
            }
            clients
            UNS
        }
    }
}

```

### Response

**Status**: 200 OK

```json
{
  "data": {
    "clients": []
  }
}
```

---

## Topics

**POST** `{{uns_url}}/mqtt/gql`

# Topics

List broker topics, optionally narrowed by an MQTT topic filter expression (wildcards `+` and `#` are supported).
## Endpoint

```http
POST {{uns_url}}/mqtt/gql
```
## Authentication

OAuth2 Bearer token (Keycloak password grant). In Postman the token is inherited from the collection auth; see the collection overview for the raw token request.
## Arguments

| Argument | Type | Required | Notes |
|---|---|---|---|
| `filter` | `String` | no | MQTT filter expression, e.g. `enterprise/#`. Omit for all topics. |

## Response

Returns `[Topic!]!`. Each `Topic` carries `path`, `byteCount`, `msgCount`, `pubRate`, `lastSeen`, the last `lastVal`, `clients` (`[String!]`, the publishing client ids, distinct from the top-level `Client` type), and its `UNS` classification (`TopicType`, one of `UNS`, `NonUNS`, `Raw`).

## Errors

GraphQL operations return `200 OK` even on logical errors. Inspect the `errors` array in the response body:

```json
{ "errors": [ { "message": "...", "path": ["..."], "extensions": { "code": "..." } } ] }
```

> **Masked errors**: Litmus Unify masks error detail by default, most failures surface as `{"message": "masked error"}` with `data: null`. The `path` identifies which field failed. Validation failures additionally carry `extensions.code = GRAPHQL_VALIDATION_FAILED` and return HTTP `422`.

A missing or expired Bearer token returns HTTP `401` with the body `bad token`.


### Request Body

**GraphQL Query**

```graphql
query Topics {
    topics {
        path
        byteCount
        msgCount
        pubRate
        lastSeen
        lastVal {
            timestamp
            deviceName
            tagName
            datatype
            value
        }
        clients
        UNS
    }
}

```

### Response

**Status**: 200 OK

```json
{
  "data": {
    "topics": []
  }
}
```

---

