diff --git a/.env b/.env
index 5d4e2bc6d0fcb3e591d87ea5e92ce6bc696622e8..7a97ff754791d4d7c5a6ab8ccde33a55be3e47c4 100644
--- a/.env
+++ b/.env
@@ -39,3 +39,8 @@ OAUTH2_REDIRECT_URL=https://wg-gen-web-demo.127-0-0-1.fr
 
 # set provider name to fake to disable auth, also the default
 OAUTH2_PROVIDER_NAME=fake
+
+# https://github.com/jamescun/wg-api integration, user and password (basic auth) are optional
+WG_STATS_API=
+WG_STATS_API_USER=
+WG_STATS_API_PASS=
\ No newline at end of file
diff --git a/README.md b/README.md
index be524a535e58e6ed1c839ca2d29a702ddbe70b43..51c1e8545a34087b22f8934151659f4e3b05ccef 100644
--- a/README.md
+++ b/README.md
@@ -46,7 +46,7 @@ The easiest way to run Wg Gen Web is using the container image
 ```
 docker run --rm -it -v /tmp/wireguard:/data -p 8080:8080 -e "WG_CONF_DIR=/data" vx3r/wg-gen-web:latest
 ```
-Docker compose snippet, used for demo server
+Docker compose snippet, used for demo server, wg-json-api service is optional
 ```
 version: '3.6'
   wg-gen-web-demo:
@@ -70,6 +70,14 @@ version: '3.6'
       - OAUTH2_REDIRECT_URL=https://wg-gen-web-demo.127-0-0-1.fr
     volumes:
       - /etc/wireguard:/data
+  wg-json-api:
+    image: james/wg-api:latest
+    container_name: wg-json-api
+    restart: unless-stopped
+    cap_add:
+      - NET_ADMIN
+    network_mode: "host"
+    command: wg-api --device wg0 --listen localhost:8182
 ```
 Please note that mapping ```/etc/wireguard``` to ```/data``` inside the docker, will erase your host's current configuration.
 If needed, please make sure to backup your files from ```/etc/wireguard```.
@@ -177,9 +185,21 @@ OAUTH2_CLIENT_SECRET=********************
 OAUTH2_REDIRECT_URL=https://wg-gen-web-demo.127-0-0-1.fr
 ```
 
-Please fell free to test and report any bugs.
 Wg Gen Web will only access your profile to get email address and your name, no other unnecessary scopes will be requested.
 
+## WireGuard Status Display
+Wg Gen Web integrates a [WireGuard API implementation](https://github.com/jamescun/wg-api) to display client stats.
+In order to enable the Status API integration, the following settings need to be configured:
+```
+# https://github.com/jamescun/wg-api integration, user and password (basic auth) are optional
+WG_STATS_API=http://localhost:8182
+WG_STATS_API_USER=
+WG_STATS_API_PASS=
+```
+To setup the WireGuard API take a look at [https://github.com/jamescun/wg-api/blob/master/README.md](https://github.com/jamescun/wg-api/blob/master/README.md).
+
+Please fell free to test and report any bugs.
+
 ## Need Help
 
  * Join us on [Discord](https://discord.gg/fjx7gGJ)
diff --git a/api/v1/status/status.go b/api/v1/status/status.go
new file mode 100644
index 0000000000000000000000000000000000000000..f61f82bf3d79cc41c1e0a81f8052c1a4df76a975
--- /dev/null
+++ b/api/v1/status/status.go
@@ -0,0 +1,50 @@
+package status
+
+import (
+	"net/http"
+	"os"
+
+	"github.com/gin-gonic/gin"
+	log "github.com/sirupsen/logrus"
+	"gitlab.127-0-0-1.fr/vx3r/wg-gen-web/core"
+)
+
+// ApplyRoutes applies router to gin Router
+func ApplyRoutes(r *gin.RouterGroup) {
+	g := r.Group("/status")
+	{
+		g.GET("/enabled", readEnabled)
+		g.GET("/interface", readInterfaceStatus)
+		g.GET("/clients", readClientStatus)
+	}
+}
+
+func readEnabled(c *gin.Context) {
+	c.JSON(http.StatusOK, os.Getenv("WG_STATS_API") != "")
+}
+
+func readInterfaceStatus(c *gin.Context) {
+	status, err := core.ReadInterfaceStatus()
+	if err != nil {
+		log.WithFields(log.Fields{
+			"err": err,
+		}).Error("failed to read interface status")
+		c.AbortWithStatusJSON(http.StatusInternalServerError, err.Error())
+		return
+	}
+
+	c.JSON(http.StatusOK, status)
+}
+
+func readClientStatus(c *gin.Context) {
+	status, err := core.ReadClientStatus()
+	if err != nil {
+		log.WithFields(log.Fields{
+			"err": err,
+		}).Error("failed to read client status")
+		c.AbortWithStatusJSON(http.StatusInternalServerError, err.Error())
+		return
+	}
+
+	c.JSON(http.StatusOK, status)
+}
diff --git a/api/v1/v1.go b/api/v1/v1.go
index c7d5df5a119f29a8ec02c2f7b709440655300bda..d44e515a5d67a49e1ddc9b4de1d7c96956a1fd0a 100644
--- a/api/v1/v1.go
+++ b/api/v1/v1.go
@@ -5,6 +5,7 @@ import (
 	"gitlab.127-0-0-1.fr/vx3r/wg-gen-web/api/v1/auth"
 	"gitlab.127-0-0-1.fr/vx3r/wg-gen-web/api/v1/client"
 	"gitlab.127-0-0-1.fr/vx3r/wg-gen-web/api/v1/server"
+	"gitlab.127-0-0-1.fr/vx3r/wg-gen-web/api/v1/status"
 )
 
 // ApplyRoutes apply routes to gin router
@@ -14,9 +15,9 @@ func ApplyRoutes(r *gin.RouterGroup, private bool) {
 		if private {
 			client.ApplyRoutes(v1)
 			server.ApplyRoutes(v1)
+			status.ApplyRoutes(v1)
 		} else {
 			auth.ApplyRoutes(v1)
-
 		}
 	}
 }
diff --git a/core/status.go b/core/status.go
new file mode 100644
index 0000000000000000000000000000000000000000..474e8a5034283125d0db82c5046aa5c1fb41d903
--- /dev/null
+++ b/core/status.go
@@ -0,0 +1,182 @@
+package core
+
+import (
+	"bytes"
+	"encoding/json"
+	"errors"
+	"io/ioutil"
+	"net/http"
+	"os"
+	"sort"
+	"time"
+
+	"gitlab.127-0-0-1.fr/vx3r/wg-gen-web/model"
+)
+
+// apiError implements a top-level JSON-RPC error.
+type apiError struct {
+	Code    int    `json:"code"`
+	Message string `json:"message"`
+
+	Data interface{} `json:"data,omitempty"`
+}
+
+type apiRequest struct {
+	Version string          `json:"jsonrpc"`
+	Method  string          `json:"method"`
+	Params  json.RawMessage `json:"params,omitempty"`
+}
+
+type apiResponse struct {
+	Version string          `json:"jsonrpc"`
+	Result  interface{}     `json:"result,omitempty"`
+	Error   *apiError       `json:"error,omitempty"`
+	ID      json.RawMessage `json:"id"`
+}
+
+func fetchWireGuardAPI(reqData apiRequest) (*apiResponse, error) {
+	apiUrl := os.Getenv("WG_STATS_API")
+	if apiUrl == "" {
+		return nil, errors.New("Status API integration not configured")
+	}
+
+	apiClient := http.Client{
+		Timeout: time.Second * 2, // Timeout after 2 seconds
+	}
+	jsonData, _ := json.Marshal(reqData)
+	req, err := http.NewRequest(http.MethodPost, apiUrl, bytes.NewBuffer(jsonData))
+	if err != nil {
+		return nil, err
+	}
+
+	req.Header.Set("User-Agent", "wg-gen-web")
+	req.Header.Set("Accept", "application/json")
+	req.Header.Set("Content-Type", "application/json")
+	req.Header.Set("Cache-Control", "no-cache")
+
+	if os.Getenv("WG_STATS_API_USER") != "" {
+		req.SetBasicAuth(os.Getenv("WG_STATS_API_USER"), os.Getenv("WG_STATS_API_PASS"))
+	}
+
+	res, getErr := apiClient.Do(req)
+	if getErr != nil {
+		return nil, getErr
+	}
+
+	if res.Body != nil {
+		defer res.Body.Close()
+	}
+
+	body, readErr := ioutil.ReadAll(res.Body)
+	if readErr != nil {
+		return nil, readErr
+	}
+
+	response := apiResponse{}
+	jsonErr := json.Unmarshal(body, &response)
+	if jsonErr != nil {
+		return nil, jsonErr
+	}
+
+	return &response, nil
+}
+
+// ReadInterfaceStatus object, create default one
+func ReadInterfaceStatus() (*model.InterfaceStatus, error) {
+	interfaceStatus := &model.InterfaceStatus{
+		Name:          "unknown",
+		DeviceType:    "unknown",
+		ListenPort:    0,
+		NumberOfPeers: 0,
+		PublicKey:     "",
+	}
+
+	data, err := fetchWireGuardAPI(apiRequest{
+		Version: "2.0",
+		Method:  "GetDeviceInfo",
+		Params:  nil,
+	})
+	if err != nil {
+		return interfaceStatus, err
+	}
+
+	resultData := data.Result.(map[string]interface{})
+	device := resultData["device"].(map[string]interface{})
+	interfaceStatus.Name = device["name"].(string)
+	interfaceStatus.DeviceType = device["type"].(string)
+	interfaceStatus.PublicKey = device["public_key"].(string)
+	interfaceStatus.ListenPort = int(device["listen_port"].(float64))
+	interfaceStatus.NumberOfPeers = int(device["num_peers"].(float64))
+
+	return interfaceStatus, nil
+}
+
+// ReadClientStatus object, create default one, last recent active client is listed first
+func ReadClientStatus() ([]*model.ClientStatus, error) {
+	var clientStatus []*model.ClientStatus
+
+	data, err := fetchWireGuardAPI(apiRequest{
+		Version: "2.0",
+		Method:  "ListPeers",
+		Params:  []byte("{}"),
+	})
+	if err != nil {
+		return clientStatus, err
+	}
+
+	resultData := data.Result.(map[string]interface{})
+	peers := resultData["peers"].([]interface{})
+
+	clients, err := ReadClients()
+	withClientDetails := true
+	if err != nil {
+		withClientDetails = false
+	}
+
+	for _, tmpPeer := range peers {
+		peer := tmpPeer.(map[string]interface{})
+		peerHandshake, _ := time.Parse(time.RFC3339Nano, peer["last_handshake"].(string))
+		peerIPs := peer["allowed_ips"].([]interface{})
+		peerAddresses := make([]string, len(peerIPs))
+		for i, peerIP := range peerIPs {
+			peerAddresses[i] = peerIP.(string)
+		}
+		peerHandshakeRelative := time.Since(peerHandshake)
+		peerActive := peerHandshakeRelative.Minutes() < 3 // TODO: we need a better detection... ping for example?
+
+		newClientStatus := &model.ClientStatus{
+			PublicKey:             peer["public_key"].(string),
+			HasPresharedKey:       peer["has_preshared_key"].(bool),
+			ProtocolVersion:       int(peer["protocol_version"].(float64)),
+			Name:                  "UNKNOWN",
+			Email:                 "UNKNOWN",
+			Connected:             peerActive,
+			AllowedIPs:            peerAddresses,
+			Endpoint:              peer["endpoint"].(string),
+			LastHandshake:         peerHandshake,
+			LastHandshakeRelative: peerHandshakeRelative,
+			ReceivedBytes:         int(peer["receive_bytes"].(float64)),
+			TransmittedBytes:      int(peer["transmit_bytes"].(float64)),
+		}
+
+		if withClientDetails {
+			for _, client := range clients {
+				if client.PublicKey != newClientStatus.PublicKey {
+					continue
+				}
+
+				newClientStatus.Name = client.Name
+				newClientStatus.Email = client.Email
+				break
+			}
+		}
+
+		clientStatus = append(clientStatus, newClientStatus)
+	}
+
+	sort.Slice(clientStatus, func(i, j int) bool {
+		return clientStatus[i].LastHandshakeRelative < clientStatus[j].LastHandshakeRelative
+	})
+
+	return clientStatus, nil
+}
diff --git a/model/status.go b/model/status.go
new file mode 100644
index 0000000000000000000000000000000000000000..1ac07dd223e426a5cc7d12503668dbba715e2522
--- /dev/null
+++ b/model/status.go
@@ -0,0 +1,67 @@
+package model
+
+import (
+	"encoding/json"
+	"fmt"
+	"time"
+)
+
+// ClientStatus structure
+type ClientStatus struct {
+	PublicKey             string        `json:"publicKey"`
+	HasPresharedKey       bool          `json:"hasPresharedKey"`
+	ProtocolVersion       int           `json:"protocolVersion"`
+	Name                  string        `json:"name"`
+	Email                 string        `json:"email"`
+	Connected             bool          `json:"connected"`
+	AllowedIPs            []string      `json:"allowedIPs"`
+	Endpoint              string        `json:"endpoint"`
+	LastHandshake         time.Time     `json:"lastHandshake"`
+	LastHandshakeRelative time.Duration `json:"lastHandshakeRelative"`
+	ReceivedBytes         int           `json:"receivedBytes"`
+	TransmittedBytes      int           `json:"transmittedBytes"`
+}
+
+func (c *ClientStatus) MarshalJSON() ([]byte, error) {
+
+	duration := fmt.Sprintf("%v ago", c.LastHandshakeRelative)
+	if c.LastHandshakeRelative.Hours() > 5208 { // 24*7*31 = approx one month
+		duration = "more than a month ago"
+	}
+	return json.Marshal(&struct {
+		PublicKey             string    `json:"publicKey"`
+		HasPresharedKey       bool      `json:"hasPresharedKey"`
+		ProtocolVersion       int       `json:"protocolVersion"`
+		Name                  string    `json:"name"`
+		Email                 string    `json:"email"`
+		Connected             bool      `json:"connected"`
+		AllowedIPs            []string  `json:"allowedIPs"`
+		Endpoint              string    `json:"endpoint"`
+		LastHandshake         time.Time `json:"lastHandshake"`
+		LastHandshakeRelative string    `json:"lastHandshakeRelative"`
+		ReceivedBytes         int       `json:"receivedBytes"`
+		TransmittedBytes      int       `json:"transmittedBytes"`
+	}{
+		PublicKey:             c.PublicKey,
+		HasPresharedKey:       c.HasPresharedKey,
+		ProtocolVersion:       c.ProtocolVersion,
+		Name:                  c.Name,
+		Email:                 c.Email,
+		Connected:             c.Connected,
+		AllowedIPs:            c.AllowedIPs,
+		Endpoint:              c.Endpoint,
+		LastHandshake:         c.LastHandshake,
+		LastHandshakeRelative: duration,
+		ReceivedBytes:         c.ReceivedBytes,
+		TransmittedBytes:      c.TransmittedBytes,
+	})
+}
+
+// InterfaceStatus structure
+type InterfaceStatus struct {
+	Name          string `json:"name"`
+	DeviceType    string `json:"type"`
+	ListenPort    int    `json:"listenPort"`
+	NumberOfPeers int    `json:"numPeers"`
+	PublicKey     string `json:"publicKey"`
+}
diff --git a/ui/src/components/Header.vue b/ui/src/components/Header.vue
index 58ca18fa712add7492071ab0d89928f1f6a2cf1a..e3645449bf38c0fb1b2b3a0ea3e7cce38145794d 100644
--- a/ui/src/components/Header.vue
+++ b/ui/src/components/Header.vue
@@ -15,6 +15,10 @@
                     Server
                     <v-icon right dark>mdi-vpn</v-icon>
                 </v-btn>
+                <v-btn to="/status">
+                    Status
+                    <v-icon right dark>mdi-chart-bar</v-icon>
+                </v-btn>
             </v-toolbar-items>
 
             <v-menu
diff --git a/ui/src/components/Status.vue b/ui/src/components/Status.vue
new file mode 100644
index 0000000000000000000000000000000000000000..739e8c728c444e0c4f9a3bb62a22aaaffe13a7ac
--- /dev/null
+++ b/ui/src/components/Status.vue
@@ -0,0 +1,170 @@
+<template>
+    <v-container>
+      <v-row v-if="dataLoaded">
+        <v-col cols="12">
+          <v-card>
+            <v-card-title>
+              WireGuard Interface Status: {{ interface.name }}
+            </v-card-title>
+            <v-list-item>
+              <v-list-item-content>
+                <v-list-item-subtitle>Public Key: {{ interface.publicKey }}</v-list-item-subtitle>
+                <v-list-item-subtitle>Listening Port: {{ interface.listenPort }}</v-list-item-subtitle>
+                <v-list-item-subtitle>Device Type: {{ interface.type }}</v-list-item-subtitle>
+                <v-list-item-subtitle>Number of Peers: {{ interface.numPeers }}</v-list-item-subtitle>
+              </v-list-item-content>
+            </v-list-item>
+          </v-card>
+        </v-col>
+      </v-row>
+      <v-row v-if="dataLoaded">
+        <v-col cols="12">
+          <v-card>
+            <v-card-title>
+              WireGuard Client Status
+              <v-spacer></v-spacer>
+              <v-text-field
+                  v-model="search"
+                  append-icon="mdi-magnify"
+                  label="Search"
+                  single-line
+                  hide-details
+              ></v-text-field>
+              <v-spacer></v-spacer>
+              <v-btn
+                  color="success"
+                  @click="reload"
+              >
+                Reload
+                <v-icon right dark>mdi-reload</v-icon>
+              </v-btn>
+            </v-card-title>
+            <v-data-table
+              :headers="headers"
+              :items="clients"
+              :search="search"
+          >
+            <template v-slot:item.connected="{ item }">
+              <v-icon left v-if="item.connected" color="success">mdi-lan-connect</v-icon>
+              <v-icon left v-else>mdi-lan-disconnect</v-icon>
+            </template>
+            <template v-slot:item.receivedBytes="{ item }">
+              {{ humanFileSize(item.receivedBytes) }}
+            </template>
+            <template v-slot:item.transmittedBytes="{ item }">
+              {{ humanFileSize(item.transmittedBytes) }}
+            </template>
+            <template v-slot:item.allowedIPs="{ item }">
+              <v-chip
+                  v-for="(ip, i) in item.allowedIPs"
+                  :key="i"
+                  color="indigo"
+                  text-color="white"
+              >
+                <v-icon left>mdi-ip-network</v-icon>
+                {{ ip }}
+              </v-chip>
+            </template>
+            <template v-slot:item.lastHandshake="{ item }">
+              <v-row>
+                <p>{{ item.lastHandshake | formatDate }} ({{ item.lastHandshakeRelative }})</p>
+              </v-row>
+            </template>
+          </v-data-table>
+          </v-card>
+        </v-col>
+      </v-row>
+      <v-row v-else>
+        <v-col cols="12">
+          <v-card>
+            <v-card-title>
+              No stats available...
+            </v-card-title>
+            <v-card-text v-if="enabled">{{ error }}</v-card-text>
+            <v-card-text v-else>Status API integration not configured.</v-card-text>
+          </v-card>
+        </v-col>
+      </v-row>
+    </v-container>
+</template>
+<script>
+  import { mapActions, mapGetters } from 'vuex'
+
+  export default {
+    name: 'Status',
+
+    data: () => ({
+      search: '',
+      headers: [
+        { text: 'Connected', value: 'connected', },
+        { text: 'Name', value: 'name', },
+        { text: 'Endpoint', value: 'endpoint', },
+        { text: 'IP addresses', value: 'allowedIPs', sortable: false, },
+        { text: 'Received Bytes', value: 'receivedBytes', },
+        { text: 'Transmitted Bytes', value: 'transmittedBytes', },
+        { text: 'Last Handshake', value: 'lastHandshake',} ,
+      ],
+    }),
+
+    computed:{
+      ...mapGetters({
+        interface: 'status/interfaceStatus',
+        clients: 'status/clientStatus',
+        enabled: 'status/enabled',
+        error: 'status/error',
+      }),
+      dataLoaded: function () {
+        return this.enabled && this.interface != null && this.interface.name !== "";
+      }
+    },
+
+    mounted () {
+      this.readEnabled()
+      if(this.enabled) {
+        this.readStatus()
+      }
+    },
+
+    watch: {
+      enabled(newValue, oldValue) {
+        if (this.enabled) {
+          this.readStatus()
+        }
+      },
+    },
+
+    methods: {
+      ...mapActions('status', {
+        readStatus: 'read',
+        readEnabled: 'isEnabled',
+      }),
+
+      reload() {
+        this.readStatus()
+      },
+
+      // https://stackoverflow.com/questions/10420352/converting-file-size-in-bytes-to-human-readable-string
+      humanFileSize(bytes, si=false, dp=1) {
+        const thresh = si ? 1000 : 1024;
+
+        if (Math.abs(bytes) < thresh) {
+          return bytes + ' B';
+        }
+
+        const units = si
+            ? ['kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
+            : ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
+        let u = -1;
+        const r = 10**dp;
+
+        do {
+          bytes /= thresh;
+          ++u;
+        } while (Math.round(Math.abs(bytes) * r) / r >= thresh && u < units.length - 1);
+
+
+        return bytes.toFixed(dp) + ' ' + units[u];
+      }
+    }
+  };
+</script>
diff --git a/ui/src/router/index.js b/ui/src/router/index.js
index ee29359639b949ce6a018767c37c9931482b6c85..c4c1d414feb012ec6042a63cad13858515aacb0c 100644
--- a/ui/src/router/index.js
+++ b/ui/src/router/index.js
@@ -24,7 +24,17 @@ const routes = [
     meta: {
       requiresAuth: true
     }
-  }
+  },
+  {
+    path: '/status',
+    name: 'status',
+    component: function () {
+      return import(/* webpackChunkName: "Status" */ '../views/Status.vue')
+    },
+    meta: {
+      requiresAuth: true
+    }
+  },
 ];
 
 const router = new VueRouter({
diff --git a/ui/src/services/api.service.js b/ui/src/services/api.service.js
index 9a5e6d2679135820e18b26977fe43f1f17bdac0e..237c308155fcb9e93500da17d687e2bb32f3bdd9 100644
--- a/ui/src/services/api.service.js
+++ b/ui/src/services/api.service.js
@@ -10,9 +10,13 @@ const ApiService = {
   get(resource) {
     return Vue.axios.get(resource)
       .then(response => response.data)
-      .catch(error => {
-        throw new Error(`ApiService: ${error}`)
-      });
+        .catch(error => {
+          if(typeof error.response !== 'undefined') {
+            throw new Error(`${error.response.status} - ${error.response.statusText}: ${error.response.data}`)
+          } else {
+            throw new Error(`ApiService: ${error}`)
+          }
+        });
   },
 
   post(resource, params) {
diff --git a/ui/src/store/index.js b/ui/src/store/index.js
index 97b5b767ebbfaf23cac1b4503bc1589ca0c627dc..ea685b8d27c2d173824de7826dd65ea63e4fcbea 100644
--- a/ui/src/store/index.js
+++ b/ui/src/store/index.js
@@ -3,6 +3,7 @@ import Vuex from 'vuex'
 import auth from "./modules/auth";
 import client from "./modules/client";
 import server from "./modules/server";
+import status from "./modules/status";
 
 Vue.use(Vuex)
 
@@ -14,6 +15,7 @@ export default new Vuex.Store({
   modules: {
     auth,
     client,
-    server
+    server,
+    status,
   }
 })
diff --git a/ui/src/store/modules/status.js b/ui/src/store/modules/status.js
new file mode 100644
index 0000000000000000000000000000000000000000..b1db23e6c8afe1d600d39805c3d542aec3bdde61
--- /dev/null
+++ b/ui/src/store/modules/status.js
@@ -0,0 +1,97 @@
+import ApiService from "../../services/api.service";
+
+const state = {
+  error: null,
+  enabled: false,
+  interfaceStatus: null,
+  clientStatus: [],
+  version: '_ci_build_not_run_properly_',
+}
+
+const getters = {
+  error(state) {
+    return state.error;
+  },
+
+  enabled(state) {
+    return state.enabled;
+  },
+
+  interfaceStatus(state) {
+    return state.interfaceStatus;
+  },
+
+  clientStatus(state) {
+    return state.clientStatus;
+  },
+
+  version(state) {
+    return state.version;
+  },
+}
+
+const actions = {
+  error({ commit }, error){
+    commit('error', error)
+  },
+
+  read({ commit }){
+    ApiService.get("/status/interface")
+      .then(resp => {
+        commit('interfaceStatus', resp)
+      })
+      .catch(err => {
+        commit('interfaceStatus', null);
+        commit('error', err)
+      });
+    ApiService.get("/status/clients")
+      .then(resp => {
+        commit('clientStatus', resp)
+      })
+      .catch(err => {
+        commit('clientStatus', []);
+        commit('error', err)
+      });
+  },
+
+  isEnabled({ commit }){
+    ApiService.get("/status/enabled")
+      .then(resp => {
+        commit('enabled', resp)
+      })
+      .catch(err => {
+        commit('enabled', false);
+        commit('error', err.response.data)
+      });
+  },
+}
+
+const mutations = {
+  error(state, error) {
+    state.error = error;
+  },
+
+  enabled(state, enabled) {
+    state.enabled = enabled;
+  },
+
+  interfaceStatus(state, interfaceStatus){
+    state.interfaceStatus = interfaceStatus
+  },
+
+  clientStatus(state, clientStatus){
+    state.clientStatus = clientStatus
+  },
+
+  version(state, version){
+    state.version = version
+  },
+}
+
+export default {
+  namespaced: true,
+  state,
+  getters,
+  actions,
+  mutations
+}
diff --git a/ui/src/views/Status.vue b/ui/src/views/Status.vue
new file mode 100644
index 0000000000000000000000000000000000000000..7888cc61ce6b6352e3bb6084a0d4c2d9c6d3b6df
--- /dev/null
+++ b/ui/src/views/Status.vue
@@ -0,0 +1,16 @@
+<template>
+  <v-content>
+    <Status/>
+  </v-content>
+</template>
+
+<script>
+  import Status from '../components/Status'
+
+  export default {
+    name: 'status',
+    components: {
+      Status
+    }
+  }
+</script>