# Litmus Unify/Configuration - LE, LEM, LUNS API Docs

> **Applies to:** Litmus Unify **2.0.x** only. None of these operations exist in **<v2.0.0** -- node backup and the update-file / upgrade lifecycle (`backup`, `listUpdFiles`, `uploadUpdFile`, `executeUpgrade`, `upgradeProgress`, etc.) were introduced in 2.0.x.

> **Naming inconsistency**: several types here use PascalCase field names unlike the camelCase used elsewhere in the schema; send and select them exactly as shown: `getUpdateLogRequest` `{ OffsetLine, LimitLine }`; `UpdateLog` `{ Lines, Eof }`; `UpgradeLogItem` `{ Line }`; and `UPDFile.ID` (the rest of `UPDFile` is camelCase: `productName`, `name`, `size`, `hash`, `version`, `date`). `deleteUpdFile` / `executeUpgrade` take a bare `UUID!` scalar as `input` (not an object) and return the `Empty` scalar; `Upload` is likewise a scalar.

## Table of Contents

- [Backup](#backup)
- [Is Upgrade Enabled](#is-upgrade-enabled)
- [List Update Files](#list-update-files)
- [Get Update Log](#get-update-log)
- [Upload Update File](#upload-update-file)
- [Delete Update File](#delete-update-file)
- [Execute Upgrade](#execute-upgrade)
- [Upgrade Progress](#upgrade-progress)

---

## Backup

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

# Backup

Prepare a backup of the node and return it as a base64 string. 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

Returns `String!`, the base64-encoded backup archive.
## 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 Backup {
    backup
}

```

### Response

**Status**: 200 OK

```json
{
  "errors": [
    {
      "message": "masked error",
      "path": [
        "backup"
      ]
    }
  ],
  "data": null
}
```

---

## Is Upgrade Enabled

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

# Is Upgrade Enabled

Report whether a node upgrade is currently available. 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

Returns `Boolean!`.
## 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 IsUpgradeEnabled {
    isUpgradeEnabled
}

```

### Response

**Status**: 200 OK

```json
{
  "data": {
    "isUpgradeEnabled": true
  }
}
```

---

## List Update Files

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

# List Update Files

List the update (`.upd`) files available to upgrade the node. 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

Returns `[UPDFile!]!`. Each `UPDFile` carries `ID`, `productName`, `name`, `size`, `hash`, `version`, and `date`. Use the `ID` with `Execute Upgrade` or `Delete Update File`.

## 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 ListUpdFiles {
    listUpdFiles {
        ID
        productName
        name
        size
        hash
        version
        date
    }
}

```

### Response

**Status**: 200 OK

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

---

## Get Update Log

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

# Get Update Log

Read the node update log, paged by line.
## 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

| Field (`getUpdateLogRequest`) | Type | Required | Notes |
|---|---|---|---|
| `OffsetLine` | `Int!` | yes | First line to return (0-based). |
| `LimitLine` | `Int!` | yes | Maximum number of lines. |

## Response

Returns `UpdateLog`: `Lines` (the log lines) and `Eof` (whether the end of the log was reached).
## 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 GetUpdateLog($input: getUpdateLogRequest!) {
    getUpdateLog(input: $input) {
        Lines
        Eof
    }
}

```

**Variables**

```json
{
  "input": {
    "OffsetLine": 0,
    "LimitLine": 100
  }
}
```

### Response

**Status**: 200 OK

```json
{
  "data": {
    "getUpdateLog": {
      "Lines": null,
      "Eof": true
    }
  }
}
```

---

## Upload Update File

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

# Upload Update File

Upload a node update (`.upd`) file via the GraphQL multipart-request specification.
## 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 |
|---|---|---|---|
| `file` | `Upload!` | yes | The `.upd` file, sent as `multipart/form-data`. |

## Request

Send `multipart/form-data` per the GraphQL multipart spec:

- `operations`: `{"query":"mutation UploadUpdFile($file: Upload!){uploadUpdFile(file:$file){ID name version}}","variables":{"file":null}}`
- `map`: `{"0":["variables.file"]}`
- `0`: the file part.

## Response

Returns the created `UPDFile!`.
## 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
mutation UploadUpdFile($file: Upload!) {
    uploadUpdFile(file: $file) {
        ID
        productName
        name
        size
        hash
        version
        date
    }
}

```

**Variables**

```json
{
  "file": "<binary .upd file>"
}
```

### Response

**Status**: 200 OK

```json
{
  "errors": [
    {
      "message": "masked error",
      "path": [
        "uploadUpdFile"
      ]
    }
  ],
  "data": null
}
```

---

## Delete Update File

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

# Delete Update File

Delete an update file by id.
## 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 |
|---|---|---|---|
| `input` | `UUID!` | yes | The `UPDFile` id (its `ID` field). |

## Response

Returns `Empty`.
## 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
mutation DeleteUpdFile($input: UUID!) {
    deleteUpdFile(input: $input)
}

```

**Variables**

```json
{
  "input": "00000000-0000-0000-0000-000000000000"
}
```

### Response

**Status**: 200 OK

```json
{
  "data": {
    "deleteUpdFile": null
  }
}
```

---

## Execute Upgrade

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

# Execute Upgrade

Start the node upgrade using a previously uploaded update file.
## 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 |
|---|---|---|---|
| `input` | `UUID!` | yes | The `UPDFile` id to upgrade with. |

## Response

Returns `Empty`.
> **Disruptive**: this replaces the running node software. Watch progress with the `Upgrade Progress` subscription.
## 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
mutation ExecuteUpgrade($input: UUID!) {
    executeUpgrade(input: $input)
}

```

**Variables**

```json
{
  "input": "00000000-0000-0000-0000-000000000000"
}
```

### Response

**Status**: 200 OK

```json
{
  "errors": [
    {
      "message": "masked error",
      "path": [
        "executeUpgrade"
      ]
    }
  ],
  "data": {
    "executeUpgrade": null
  }
}
```

---

## Upgrade Progress

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

# Upgrade Progress

Subscription that streams upgrade-log lines while an upgrade runs. 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

Streams `UpgradeLogItem` (`{ Line }`).
> GraphQL **subscription**, delivered over WebSocket; it cannot be exercised with a plain HTTP POST.
## 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
subscription UpgradeProgress {
    UpgradeProgress {
        Line
    }
}

```

---

