diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json
index 8965f90b..c24a6832 100644
--- a/npm-shrinkwrap.json
+++ b/npm-shrinkwrap.json
@@ -171,7 +171,7 @@
     "asn1.js": {
       "version": "4.9.2",
       "from": "asn1.js@>=4.0.0 <5.0.0",
-      "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.9.2.tgz",
+      "resolved": "https://npm-registry.sipwise.com/asn1.js/-/asn1.js-4.9.2.tgz",
       "dev": true
     },
     "assert": {
@@ -1187,7 +1187,7 @@
     "crypto-browserify": {
       "version": "3.12.0",
       "from": "crypto-browserify@latest",
-      "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz",
+      "resolved": "https://npm-registry.sipwise.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz",
       "dev": true
     },
     "css": {
@@ -2122,170 +2122,170 @@
         "abbrev": {
           "version": "1.1.0",
           "from": "abbrev@1.1.0",
-          "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.0.tgz",
+          "resolved": "https://npm-registry.sipwise.com/abbrev/-/abbrev-1.1.0.tgz",
           "dev": true,
           "optional": true
         },
         "ajv": {
           "version": "4.11.8",
           "from": "ajv@4.11.8",
-          "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz",
+          "resolved": "https://npm-registry.sipwise.com/ajv/-/ajv-4.11.8.tgz",
           "dev": true,
           "optional": true
         },
         "ansi-regex": {
           "version": "2.1.1",
           "from": "ansi-regex@2.1.1",
-          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+          "resolved": "https://npm-registry.sipwise.com/ansi-regex/-/ansi-regex-2.1.1.tgz",
           "dev": true
         },
         "aproba": {
           "version": "1.1.1",
           "from": "aproba@1.1.1",
-          "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.1.1.tgz",
+          "resolved": "https://npm-registry.sipwise.com/aproba/-/aproba-1.1.1.tgz",
           "dev": true,
           "optional": true
         },
         "are-we-there-yet": {
           "version": "1.1.4",
           "from": "are-we-there-yet@1.1.4",
-          "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz",
+          "resolved": "https://npm-registry.sipwise.com/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz",
           "dev": true,
           "optional": true
         },
         "asn1": {
           "version": "0.2.3",
           "from": "asn1@0.2.3",
-          "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz",
+          "resolved": "https://npm-registry.sipwise.com/asn1/-/asn1-0.2.3.tgz",
           "dev": true,
           "optional": true
         },
         "assert-plus": {
           "version": "0.2.0",
           "from": "assert-plus@0.2.0",
-          "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz",
+          "resolved": "https://npm-registry.sipwise.com/assert-plus/-/assert-plus-0.2.0.tgz",
           "dev": true,
           "optional": true
         },
         "asynckit": {
           "version": "0.4.0",
           "from": "asynckit@0.4.0",
-          "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+          "resolved": "https://npm-registry.sipwise.com/asynckit/-/asynckit-0.4.0.tgz",
           "dev": true,
           "optional": true
         },
         "aws-sign2": {
           "version": "0.6.0",
           "from": "aws-sign2@0.6.0",
-          "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz",
+          "resolved": "https://npm-registry.sipwise.com/aws-sign2/-/aws-sign2-0.6.0.tgz",
           "dev": true,
           "optional": true
         },
         "aws4": {
           "version": "1.6.0",
           "from": "aws4@1.6.0",
-          "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz",
+          "resolved": "https://npm-registry.sipwise.com/aws4/-/aws4-1.6.0.tgz",
           "dev": true,
           "optional": true
         },
         "balanced-match": {
           "version": "0.4.2",
           "from": "balanced-match@0.4.2",
-          "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz",
+          "resolved": "https://npm-registry.sipwise.com/balanced-match/-/balanced-match-0.4.2.tgz",
           "dev": true
         },
         "bcrypt-pbkdf": {
           "version": "1.0.1",
           "from": "bcrypt-pbkdf@1.0.1",
-          "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz",
+          "resolved": "https://npm-registry.sipwise.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz",
           "dev": true,
           "optional": true
         },
         "block-stream": {
           "version": "0.0.9",
           "from": "block-stream@0.0.9",
-          "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
+          "resolved": "https://npm-registry.sipwise.com/block-stream/-/block-stream-0.0.9.tgz",
           "dev": true
         },
         "boom": {
           "version": "2.10.1",
           "from": "boom@2.10.1",
-          "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz",
+          "resolved": "https://npm-registry.sipwise.com/boom/-/boom-2.10.1.tgz",
           "dev": true
         },
         "brace-expansion": {
           "version": "1.1.7",
           "from": "brace-expansion@1.1.7",
-          "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.7.tgz",
+          "resolved": "https://npm-registry.sipwise.com/brace-expansion/-/brace-expansion-1.1.7.tgz",
           "dev": true
         },
         "buffer-shims": {
           "version": "1.0.0",
           "from": "buffer-shims@1.0.0",
-          "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz",
+          "resolved": "https://npm-registry.sipwise.com/buffer-shims/-/buffer-shims-1.0.0.tgz",
           "dev": true
         },
         "caseless": {
           "version": "0.12.0",
           "from": "caseless@0.12.0",
-          "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
+          "resolved": "https://npm-registry.sipwise.com/caseless/-/caseless-0.12.0.tgz",
           "dev": true,
           "optional": true
         },
         "co": {
           "version": "4.6.0",
           "from": "co@4.6.0",
-          "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
+          "resolved": "https://npm-registry.sipwise.com/co/-/co-4.6.0.tgz",
           "dev": true,
           "optional": true
         },
         "code-point-at": {
           "version": "1.1.0",
           "from": "code-point-at@1.1.0",
-          "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
+          "resolved": "https://npm-registry.sipwise.com/code-point-at/-/code-point-at-1.1.0.tgz",
           "dev": true
         },
         "combined-stream": {
           "version": "1.0.5",
           "from": "combined-stream@1.0.5",
-          "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz",
+          "resolved": "https://npm-registry.sipwise.com/combined-stream/-/combined-stream-1.0.5.tgz",
           "dev": true
         },
         "concat-map": {
           "version": "0.0.1",
           "from": "concat-map@0.0.1",
-          "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+          "resolved": "https://npm-registry.sipwise.com/concat-map/-/concat-map-0.0.1.tgz",
           "dev": true
         },
         "console-control-strings": {
           "version": "1.1.0",
           "from": "console-control-strings@1.1.0",
-          "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
+          "resolved": "https://npm-registry.sipwise.com/console-control-strings/-/console-control-strings-1.1.0.tgz",
           "dev": true
         },
         "core-util-is": {
           "version": "1.0.2",
           "from": "core-util-is@1.0.2",
-          "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+          "resolved": "https://npm-registry.sipwise.com/core-util-is/-/core-util-is-1.0.2.tgz",
           "dev": true
         },
         "cryptiles": {
           "version": "2.0.5",
           "from": "cryptiles@2.0.5",
-          "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz",
+          "resolved": "https://npm-registry.sipwise.com/cryptiles/-/cryptiles-2.0.5.tgz",
           "dev": true
         },
         "dashdash": {
           "version": "1.14.1",
           "from": "dashdash@1.14.1",
-          "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
+          "resolved": "https://npm-registry.sipwise.com/dashdash/-/dashdash-1.14.1.tgz",
           "dev": true,
           "optional": true,
           "dependencies": {
             "assert-plus": {
               "version": "1.0.0",
               "from": "assert-plus@1.0.0",
-              "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+              "resolved": "https://npm-registry.sipwise.com/assert-plus/-/assert-plus-1.0.0.tgz",
               "dev": true,
               "optional": true
             }
@@ -2294,108 +2294,108 @@
         "debug": {
           "version": "2.6.8",
           "from": "debug@2.6.8",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz",
+          "resolved": "https://npm-registry.sipwise.com/debug/-/debug-2.6.8.tgz",
           "dev": true,
           "optional": true
         },
         "deep-extend": {
           "version": "0.4.2",
           "from": "deep-extend@0.4.2",
-          "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz",
+          "resolved": "https://npm-registry.sipwise.com/deep-extend/-/deep-extend-0.4.2.tgz",
           "dev": true,
           "optional": true
         },
         "delayed-stream": {
           "version": "1.0.0",
           "from": "delayed-stream@1.0.0",
-          "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+          "resolved": "https://npm-registry.sipwise.com/delayed-stream/-/delayed-stream-1.0.0.tgz",
           "dev": true
         },
         "delegates": {
           "version": "1.0.0",
           "from": "delegates@1.0.0",
-          "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
+          "resolved": "https://npm-registry.sipwise.com/delegates/-/delegates-1.0.0.tgz",
           "dev": true,
           "optional": true
         },
         "detect-libc": {
           "version": "1.0.2",
           "from": "detect-libc@^1.0.2",
-          "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.2.tgz",
+          "resolved": "https://npm-registry.sipwise.com/detect-libc/-/detect-libc-1.0.2.tgz",
           "dev": true,
           "optional": true
         },
         "ecc-jsbn": {
           "version": "0.1.1",
           "from": "ecc-jsbn@0.1.1",
-          "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz",
+          "resolved": "https://npm-registry.sipwise.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz",
           "dev": true,
           "optional": true
         },
         "extend": {
           "version": "3.0.1",
           "from": "extend@3.0.1",
-          "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz",
+          "resolved": "https://npm-registry.sipwise.com/extend/-/extend-3.0.1.tgz",
           "dev": true,
           "optional": true
         },
         "extsprintf": {
           "version": "1.0.2",
           "from": "extsprintf@1.0.2",
-          "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz",
+          "resolved": "https://npm-registry.sipwise.com/extsprintf/-/extsprintf-1.0.2.tgz",
           "dev": true
         },
         "forever-agent": {
           "version": "0.6.1",
           "from": "forever-agent@0.6.1",
-          "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
+          "resolved": "https://npm-registry.sipwise.com/forever-agent/-/forever-agent-0.6.1.tgz",
           "dev": true,
           "optional": true
         },
         "form-data": {
           "version": "2.1.4",
           "from": "form-data@2.1.4",
-          "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz",
+          "resolved": "https://npm-registry.sipwise.com/form-data/-/form-data-2.1.4.tgz",
           "dev": true,
           "optional": true
         },
         "fs.realpath": {
           "version": "1.0.0",
           "from": "fs.realpath@1.0.0",
-          "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+          "resolved": "https://npm-registry.sipwise.com/fs.realpath/-/fs.realpath-1.0.0.tgz",
           "dev": true
         },
         "fstream": {
           "version": "1.0.11",
           "from": "fstream@1.0.11",
-          "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz",
+          "resolved": "https://npm-registry.sipwise.com/fstream/-/fstream-1.0.11.tgz",
           "dev": true
         },
         "fstream-ignore": {
           "version": "1.0.5",
           "from": "fstream-ignore@1.0.5",
-          "resolved": "https://registry.npmjs.org/fstream-ignore/-/fstream-ignore-1.0.5.tgz",
+          "resolved": "https://npm-registry.sipwise.com/fstream-ignore/-/fstream-ignore-1.0.5.tgz",
           "dev": true,
           "optional": true
         },
         "gauge": {
           "version": "2.7.4",
           "from": "gauge@2.7.4",
-          "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
+          "resolved": "https://npm-registry.sipwise.com/gauge/-/gauge-2.7.4.tgz",
           "dev": true,
           "optional": true
         },
         "getpass": {
           "version": "0.1.7",
           "from": "getpass@0.1.7",
-          "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
+          "resolved": "https://npm-registry.sipwise.com/getpass/-/getpass-0.1.7.tgz",
           "dev": true,
           "optional": true,
           "dependencies": {
             "assert-plus": {
               "version": "1.0.0",
               "from": "assert-plus@1.0.0",
-              "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+              "resolved": "https://npm-registry.sipwise.com/assert-plus/-/assert-plus-1.0.0.tgz",
               "dev": true,
               "optional": true
             }
@@ -2404,153 +2404,153 @@
         "glob": {
           "version": "7.1.2",
           "from": "glob@7.1.2",
-          "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
+          "resolved": "https://npm-registry.sipwise.com/glob/-/glob-7.1.2.tgz",
           "dev": true
         },
         "graceful-fs": {
           "version": "4.1.11",
           "from": "graceful-fs@4.1.11",
-          "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
+          "resolved": "https://npm-registry.sipwise.com/graceful-fs/-/graceful-fs-4.1.11.tgz",
           "dev": true
         },
         "har-schema": {
           "version": "1.0.5",
           "from": "har-schema@1.0.5",
-          "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz",
+          "resolved": "https://npm-registry.sipwise.com/har-schema/-/har-schema-1.0.5.tgz",
           "dev": true,
           "optional": true
         },
         "har-validator": {
           "version": "4.2.1",
           "from": "har-validator@4.2.1",
-          "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz",
+          "resolved": "https://npm-registry.sipwise.com/har-validator/-/har-validator-4.2.1.tgz",
           "dev": true,
           "optional": true
         },
         "has-unicode": {
           "version": "2.0.1",
           "from": "has-unicode@2.0.1",
-          "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
+          "resolved": "https://npm-registry.sipwise.com/has-unicode/-/has-unicode-2.0.1.tgz",
           "dev": true,
           "optional": true
         },
         "hawk": {
           "version": "3.1.3",
           "from": "hawk@3.1.3",
-          "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz",
+          "resolved": "https://npm-registry.sipwise.com/hawk/-/hawk-3.1.3.tgz",
           "dev": true
         },
         "hoek": {
           "version": "2.16.3",
           "from": "hoek@2.16.3",
-          "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz",
+          "resolved": "https://npm-registry.sipwise.com/hoek/-/hoek-2.16.3.tgz",
           "dev": true
         },
         "http-signature": {
           "version": "1.1.1",
           "from": "http-signature@1.1.1",
-          "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz",
+          "resolved": "https://npm-registry.sipwise.com/http-signature/-/http-signature-1.1.1.tgz",
           "dev": true,
           "optional": true
         },
         "inflight": {
           "version": "1.0.6",
           "from": "inflight@1.0.6",
-          "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+          "resolved": "https://npm-registry.sipwise.com/inflight/-/inflight-1.0.6.tgz",
           "dev": true
         },
         "inherits": {
           "version": "2.0.3",
           "from": "inherits@2.0.3",
-          "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+          "resolved": "https://npm-registry.sipwise.com/inherits/-/inherits-2.0.3.tgz",
           "dev": true
         },
         "ini": {
           "version": "1.3.4",
           "from": "ini@1.3.4",
-          "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz",
+          "resolved": "https://npm-registry.sipwise.com/ini/-/ini-1.3.4.tgz",
           "dev": true,
           "optional": true
         },
         "is-fullwidth-code-point": {
           "version": "1.0.0",
           "from": "is-fullwidth-code-point@1.0.0",
-          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
+          "resolved": "https://npm-registry.sipwise.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
           "dev": true
         },
         "is-typedarray": {
           "version": "1.0.0",
           "from": "is-typedarray@1.0.0",
-          "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+          "resolved": "https://npm-registry.sipwise.com/is-typedarray/-/is-typedarray-1.0.0.tgz",
           "dev": true,
           "optional": true
         },
         "isarray": {
           "version": "1.0.0",
           "from": "isarray@1.0.0",
-          "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+          "resolved": "https://npm-registry.sipwise.com/isarray/-/isarray-1.0.0.tgz",
           "dev": true
         },
         "isstream": {
           "version": "0.1.2",
           "from": "isstream@0.1.2",
-          "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
+          "resolved": "https://npm-registry.sipwise.com/isstream/-/isstream-0.1.2.tgz",
           "dev": true,
           "optional": true
         },
         "jodid25519": {
           "version": "1.0.2",
           "from": "jodid25519@1.0.2",
-          "resolved": "https://registry.npmjs.org/jodid25519/-/jodid25519-1.0.2.tgz",
+          "resolved": "https://npm-registry.sipwise.com/jodid25519/-/jodid25519-1.0.2.tgz",
           "dev": true,
           "optional": true
         },
         "jsbn": {
           "version": "0.1.1",
           "from": "jsbn@0.1.1",
-          "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
+          "resolved": "https://npm-registry.sipwise.com/jsbn/-/jsbn-0.1.1.tgz",
           "dev": true,
           "optional": true
         },
         "json-schema": {
           "version": "0.2.3",
           "from": "json-schema@0.2.3",
-          "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
+          "resolved": "https://npm-registry.sipwise.com/json-schema/-/json-schema-0.2.3.tgz",
           "dev": true,
           "optional": true
         },
         "json-stable-stringify": {
           "version": "1.0.1",
           "from": "json-stable-stringify@1.0.1",
-          "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz",
+          "resolved": "https://npm-registry.sipwise.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz",
           "dev": true,
           "optional": true
         },
         "json-stringify-safe": {
           "version": "5.0.1",
           "from": "json-stringify-safe@5.0.1",
-          "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
+          "resolved": "https://npm-registry.sipwise.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
           "dev": true,
           "optional": true
         },
         "jsonify": {
           "version": "0.0.0",
           "from": "jsonify@0.0.0",
-          "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
+          "resolved": "https://npm-registry.sipwise.com/jsonify/-/jsonify-0.0.0.tgz",
           "dev": true,
           "optional": true
         },
         "jsprim": {
           "version": "1.4.0",
           "from": "jsprim@1.4.0",
-          "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.0.tgz",
+          "resolved": "https://npm-registry.sipwise.com/jsprim/-/jsprim-1.4.0.tgz",
           "dev": true,
           "optional": true,
           "dependencies": {
             "assert-plus": {
               "version": "1.0.0",
               "from": "assert-plus@1.0.0",
-              "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+              "resolved": "https://npm-registry.sipwise.com/assert-plus/-/assert-plus-1.0.0.tgz",
               "dev": true,
               "optional": true
             }
@@ -2559,152 +2559,152 @@
         "mime-db": {
           "version": "1.27.0",
           "from": "mime-db@1.27.0",
-          "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.27.0.tgz",
+          "resolved": "https://npm-registry.sipwise.com/mime-db/-/mime-db-1.27.0.tgz",
           "dev": true
         },
         "mime-types": {
           "version": "2.1.15",
           "from": "mime-types@2.1.15",
-          "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.15.tgz",
+          "resolved": "https://npm-registry.sipwise.com/mime-types/-/mime-types-2.1.15.tgz",
           "dev": true
         },
         "minimatch": {
           "version": "3.0.4",
           "from": "minimatch@3.0.4",
-          "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+          "resolved": "https://npm-registry.sipwise.com/minimatch/-/minimatch-3.0.4.tgz",
           "dev": true
         },
         "minimist": {
           "version": "0.0.8",
           "from": "minimist@0.0.8",
-          "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+          "resolved": "https://npm-registry.sipwise.com/minimist/-/minimist-0.0.8.tgz",
           "dev": true
         },
         "mkdirp": {
           "version": "0.5.1",
           "from": "mkdirp@0.5.1",
-          "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+          "resolved": "https://npm-registry.sipwise.com/mkdirp/-/mkdirp-0.5.1.tgz",
           "dev": true
         },
         "ms": {
           "version": "2.0.0",
           "from": "ms@2.0.0",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+          "resolved": "https://npm-registry.sipwise.com/ms/-/ms-2.0.0.tgz",
           "dev": true,
           "optional": true
         },
         "node-pre-gyp": {
           "version": "0.6.39",
           "from": "node-pre-gyp@^0.6.39",
-          "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.6.39.tgz",
+          "resolved": "https://npm-registry.sipwise.com/node-pre-gyp/-/node-pre-gyp-0.6.39.tgz",
           "dev": true,
           "optional": true
         },
         "nopt": {
           "version": "4.0.1",
           "from": "nopt@4.0.1",
-          "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz",
+          "resolved": "https://npm-registry.sipwise.com/nopt/-/nopt-4.0.1.tgz",
           "dev": true,
           "optional": true
         },
         "npmlog": {
           "version": "4.1.0",
           "from": "npmlog@4.1.0",
-          "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.0.tgz",
+          "resolved": "https://npm-registry.sipwise.com/npmlog/-/npmlog-4.1.0.tgz",
           "dev": true,
           "optional": true
         },
         "number-is-nan": {
           "version": "1.0.1",
           "from": "number-is-nan@1.0.1",
-          "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
+          "resolved": "https://npm-registry.sipwise.com/number-is-nan/-/number-is-nan-1.0.1.tgz",
           "dev": true
         },
         "oauth-sign": {
           "version": "0.8.2",
           "from": "oauth-sign@0.8.2",
-          "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz",
+          "resolved": "https://npm-registry.sipwise.com/oauth-sign/-/oauth-sign-0.8.2.tgz",
           "dev": true,
           "optional": true
         },
         "object-assign": {
           "version": "4.1.1",
           "from": "object-assign@4.1.1",
-          "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+          "resolved": "https://npm-registry.sipwise.com/object-assign/-/object-assign-4.1.1.tgz",
           "dev": true,
           "optional": true
         },
         "once": {
           "version": "1.4.0",
           "from": "once@1.4.0",
-          "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+          "resolved": "https://npm-registry.sipwise.com/once/-/once-1.4.0.tgz",
           "dev": true
         },
         "os-homedir": {
           "version": "1.0.2",
           "from": "os-homedir@1.0.2",
-          "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
+          "resolved": "https://npm-registry.sipwise.com/os-homedir/-/os-homedir-1.0.2.tgz",
           "dev": true,
           "optional": true
         },
         "os-tmpdir": {
           "version": "1.0.2",
           "from": "os-tmpdir@1.0.2",
-          "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+          "resolved": "https://npm-registry.sipwise.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
           "dev": true,
           "optional": true
         },
         "osenv": {
           "version": "0.1.4",
           "from": "osenv@0.1.4",
-          "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz",
+          "resolved": "https://npm-registry.sipwise.com/osenv/-/osenv-0.1.4.tgz",
           "dev": true,
           "optional": true
         },
         "path-is-absolute": {
           "version": "1.0.1",
           "from": "path-is-absolute@1.0.1",
-          "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+          "resolved": "https://npm-registry.sipwise.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
           "dev": true
         },
         "performance-now": {
           "version": "0.2.0",
           "from": "performance-now@0.2.0",
-          "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz",
+          "resolved": "https://npm-registry.sipwise.com/performance-now/-/performance-now-0.2.0.tgz",
           "dev": true,
           "optional": true
         },
         "process-nextick-args": {
           "version": "1.0.7",
           "from": "process-nextick-args@1.0.7",
-          "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
+          "resolved": "https://npm-registry.sipwise.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
           "dev": true
         },
         "punycode": {
           "version": "1.4.1",
           "from": "punycode@1.4.1",
-          "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
+          "resolved": "https://npm-registry.sipwise.com/punycode/-/punycode-1.4.1.tgz",
           "dev": true,
           "optional": true
         },
         "qs": {
           "version": "6.4.0",
           "from": "qs@6.4.0",
-          "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz",
+          "resolved": "https://npm-registry.sipwise.com/qs/-/qs-6.4.0.tgz",
           "dev": true,
           "optional": true
         },
         "rc": {
           "version": "1.2.1",
           "from": "rc@1.2.1",
-          "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.1.tgz",
+          "resolved": "https://npm-registry.sipwise.com/rc/-/rc-1.2.1.tgz",
           "dev": true,
           "optional": true,
           "dependencies": {
             "minimist": {
               "version": "1.2.0",
               "from": "minimist@1.2.0",
-              "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+              "resolved": "https://npm-registry.sipwise.com/minimist/-/minimist-1.2.0.tgz",
               "dev": true,
               "optional": true
             }
@@ -2713,66 +2713,66 @@
         "readable-stream": {
           "version": "2.2.9",
           "from": "readable-stream@2.2.9",
-          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.9.tgz",
+          "resolved": "https://npm-registry.sipwise.com/readable-stream/-/readable-stream-2.2.9.tgz",
           "dev": true
         },
         "request": {
           "version": "2.81.0",
           "from": "request@2.81.0",
-          "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz",
+          "resolved": "https://npm-registry.sipwise.com/request/-/request-2.81.0.tgz",
           "dev": true,
           "optional": true
         },
         "rimraf": {
           "version": "2.6.1",
           "from": "rimraf@2.6.1",
-          "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz",
+          "resolved": "https://npm-registry.sipwise.com/rimraf/-/rimraf-2.6.1.tgz",
           "dev": true
         },
         "safe-buffer": {
           "version": "5.0.1",
           "from": "safe-buffer@5.0.1",
-          "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.0.1.tgz",
+          "resolved": "https://npm-registry.sipwise.com/safe-buffer/-/safe-buffer-5.0.1.tgz",
           "dev": true
         },
         "semver": {
           "version": "5.3.0",
           "from": "semver@5.3.0",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
+          "resolved": "https://npm-registry.sipwise.com/semver/-/semver-5.3.0.tgz",
           "dev": true,
           "optional": true
         },
         "set-blocking": {
           "version": "2.0.0",
           "from": "set-blocking@2.0.0",
-          "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+          "resolved": "https://npm-registry.sipwise.com/set-blocking/-/set-blocking-2.0.0.tgz",
           "dev": true,
           "optional": true
         },
         "signal-exit": {
           "version": "3.0.2",
           "from": "signal-exit@3.0.2",
-          "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
+          "resolved": "https://npm-registry.sipwise.com/signal-exit/-/signal-exit-3.0.2.tgz",
           "dev": true,
           "optional": true
         },
         "sntp": {
           "version": "1.0.9",
           "from": "sntp@1.0.9",
-          "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz",
+          "resolved": "https://npm-registry.sipwise.com/sntp/-/sntp-1.0.9.tgz",
           "dev": true
         },
         "sshpk": {
           "version": "1.13.0",
           "from": "sshpk@1.13.0",
-          "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.0.tgz",
+          "resolved": "https://npm-registry.sipwise.com/sshpk/-/sshpk-1.13.0.tgz",
           "dev": true,
           "optional": true,
           "dependencies": {
             "assert-plus": {
               "version": "1.0.0",
               "from": "assert-plus@1.0.0",
-              "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+              "resolved": "https://npm-registry.sipwise.com/assert-plus/-/assert-plus-1.0.0.tgz",
               "dev": true,
               "optional": true
             }
@@ -2781,107 +2781,107 @@
         "string_decoder": {
           "version": "1.0.1",
           "from": "string_decoder@1.0.1",
-          "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.1.tgz",
+          "resolved": "https://npm-registry.sipwise.com/string_decoder/-/string_decoder-1.0.1.tgz",
           "dev": true
         },
         "string-width": {
           "version": "1.0.2",
           "from": "string-width@1.0.2",
-          "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+          "resolved": "https://npm-registry.sipwise.com/string-width/-/string-width-1.0.2.tgz",
           "dev": true
         },
         "stringstream": {
           "version": "0.0.5",
           "from": "stringstream@0.0.5",
-          "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz",
+          "resolved": "https://npm-registry.sipwise.com/stringstream/-/stringstream-0.0.5.tgz",
           "dev": true,
           "optional": true
         },
         "strip-ansi": {
           "version": "3.0.1",
           "from": "strip-ansi@3.0.1",
-          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+          "resolved": "https://npm-registry.sipwise.com/strip-ansi/-/strip-ansi-3.0.1.tgz",
           "dev": true
         },
         "strip-json-comments": {
           "version": "2.0.1",
           "from": "strip-json-comments@2.0.1",
-          "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
+          "resolved": "https://npm-registry.sipwise.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
           "dev": true,
           "optional": true
         },
         "tar": {
           "version": "2.2.1",
           "from": "tar@2.2.1",
-          "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz",
+          "resolved": "https://npm-registry.sipwise.com/tar/-/tar-2.2.1.tgz",
           "dev": true
         },
         "tar-pack": {
           "version": "3.4.0",
           "from": "tar-pack@3.4.0",
-          "resolved": "https://registry.npmjs.org/tar-pack/-/tar-pack-3.4.0.tgz",
+          "resolved": "https://npm-registry.sipwise.com/tar-pack/-/tar-pack-3.4.0.tgz",
           "dev": true,
           "optional": true
         },
         "tough-cookie": {
           "version": "2.3.2",
           "from": "tough-cookie@2.3.2",
-          "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.2.tgz",
+          "resolved": "https://npm-registry.sipwise.com/tough-cookie/-/tough-cookie-2.3.2.tgz",
           "dev": true,
           "optional": true
         },
         "tunnel-agent": {
           "version": "0.6.0",
           "from": "tunnel-agent@0.6.0",
-          "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+          "resolved": "https://npm-registry.sipwise.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
           "dev": true,
           "optional": true
         },
         "tweetnacl": {
           "version": "0.14.5",
           "from": "tweetnacl@0.14.5",
-          "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
+          "resolved": "https://npm-registry.sipwise.com/tweetnacl/-/tweetnacl-0.14.5.tgz",
           "dev": true,
           "optional": true
         },
         "uid-number": {
           "version": "0.0.6",
           "from": "uid-number@0.0.6",
-          "resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.6.tgz",
+          "resolved": "https://npm-registry.sipwise.com/uid-number/-/uid-number-0.0.6.tgz",
           "dev": true,
           "optional": true
         },
         "util-deprecate": {
           "version": "1.0.2",
           "from": "util-deprecate@1.0.2",
-          "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+          "resolved": "https://npm-registry.sipwise.com/util-deprecate/-/util-deprecate-1.0.2.tgz",
           "dev": true
         },
         "uuid": {
           "version": "3.0.1",
           "from": "uuid@3.0.1",
-          "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.0.1.tgz",
+          "resolved": "https://npm-registry.sipwise.com/uuid/-/uuid-3.0.1.tgz",
           "dev": true,
           "optional": true
         },
         "verror": {
           "version": "1.3.6",
           "from": "verror@1.3.6",
-          "resolved": "https://registry.npmjs.org/verror/-/verror-1.3.6.tgz",
+          "resolved": "https://npm-registry.sipwise.com/verror/-/verror-1.3.6.tgz",
           "dev": true,
           "optional": true
         },
         "wide-align": {
           "version": "1.1.2",
           "from": "wide-align@1.1.2",
-          "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz",
+          "resolved": "https://npm-registry.sipwise.com/wide-align/-/wide-align-1.1.2.tgz",
           "dev": true,
           "optional": true
         },
         "wrappy": {
           "version": "1.0.2",
           "from": "wrappy@1.0.2",
-          "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+          "resolved": "https://npm-registry.sipwise.com/wrappy/-/wrappy-1.0.2.tgz",
           "dev": true
         }
       }
@@ -3001,7 +3001,7 @@
     "growl": {
       "version": "1.10.3",
       "from": "growl@1.10.3",
-      "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.3.tgz",
+      "resolved": "https://npm-registry.sipwise.com/growl/-/growl-1.10.3.tgz",
       "dev": true
     },
     "has": {
@@ -4014,7 +4014,7 @@
     "mocha": {
       "version": "4.0.1",
       "from": "mocha@>=4.0.0 <5.0.0",
-      "resolved": "https://registry.npmjs.org/mocha/-/mocha-4.0.1.tgz",
+      "resolved": "https://npm-registry.sipwise.com/mocha/-/mocha-4.0.1.tgz",
       "dev": true,
       "dependencies": {
         "debug": {
@@ -5017,7 +5017,7 @@
     "randomfill": {
       "version": "1.0.3",
       "from": "randomfill@>=1.0.3 <2.0.0",
-      "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.3.tgz",
+      "resolved": "https://npm-registry.sipwise.com/randomfill/-/randomfill-1.0.3.tgz",
       "dev": true
     },
     "range-parser": {
@@ -6036,6 +6036,11 @@
       "resolved": "https://npm-registry.sipwise.com/utils-merge/-/utils-merge-1.0.1.tgz",
       "dev": true
     },
+    "uuid": {
+      "version": "3.2.1",
+      "from": "uuid@latest",
+      "resolved": "https://npm-registry.sipwise.com/uuid/-/uuid-3.2.1.tgz"
+    },
     "validate-npm-package-license": {
       "version": "3.0.1",
       "from": "validate-npm-package-license@>=3.0.1 <4.0.0",
@@ -6069,7 +6074,7 @@
     "vue": {
       "version": "2.5.2",
       "from": "vue@>=2.5.0 <3.0.0",
-      "resolved": "https://registry.npmjs.org/vue/-/vue-2.5.2.tgz"
+      "resolved": "https://npm-registry.sipwise.com/vue/-/vue-2.5.2.tgz"
     },
     "vue-hot-reload-api": {
       "version": "2.2.0",
@@ -6145,7 +6150,7 @@
     "vue-template-compiler": {
       "version": "2.5.2",
       "from": "vue-template-compiler@>=2.5.0 <3.0.0",
-      "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.5.2.tgz",
+      "resolved": "https://npm-registry.sipwise.com/vue-template-compiler/-/vue-template-compiler-2.5.2.tgz",
       "dev": true
     },
     "vue-template-es2015-compiler": {
diff --git a/package.json b/package.json
index fb6a45dc..365cb1bf 100644
--- a/package.json
+++ b/package.json
@@ -15,6 +15,7 @@
     "babel-runtime": "^6.25.0",
     "quasar-extras": "0.x",
     "quasar-framework": "^0.14.4",
+    "uuid": "3.2.1",
     "vue": "^2.5.0",
     "vue-i18n": "7.3.2",
     "vue-resource": "1.3.4",
diff --git a/src/api/pbx-config.js b/src/api/pbx-config.js
index bb5f35b8..7b3a1b8b 100644
--- a/src/api/pbx-config.js
+++ b/src/api/pbx-config.js
@@ -3,7 +3,9 @@ import Vue from 'vue';
 import { getJsonBody } from './utils';
 import { getNumbers, assignNumber, assignNumbers } from './user';
 import { createSubscriber, deleteSubscriber } from './subscriber';
+import uuid from 'uuid';
 
+var createId = uuid.v4;
 var assumedRows = 1000;
 
 export function getAllPbxSubscribers() {
@@ -73,13 +75,12 @@ export function getPbxConfiguration() {
 
 export function addGroup(group) {
     return new Promise((resolve, reject)=>{
-        let randomToken = ()=>{ return 'd' + Date.now() + "r" + (Math.round(Math.random() * 1000000) + 1000000); };
         Promise.resolve().then(()=>{
             return createSubscriber({
                 customer_id: group.customerId,
                 domain_id: group.domainId,
-                username: randomToken(),
-                password: randomToken(),
+                username: createId(),
+                password: createId(),
                 display_name: group.name,
                 is_pbx_group: true,
                 pbx_extension: group.extension,
@@ -100,3 +101,30 @@ export function addGroup(group) {
 export function removeGroup(id) {
     return deleteSubscriber(id);
 }
+
+export function addSeat(seat) {
+    return new Promise((resolve, reject)=>{
+        Promise.resolve().then(()=>{
+            return createSubscriber({
+                customer_id: seat.customerId,
+                domain_id: seat.domainId,
+                username: createId(),
+                password: createId(),
+                display_name: seat.name,
+                is_pbx_group: false,
+                pbx_extension: seat.extension,
+                pbx_group_ids: seat.groups
+            });
+        }).then((subscriberId)=>{
+            assignNumbers(seat.aliasNumbers, subscriberId);
+        }).then(()=>{
+            resolve();
+        }).catch((err)=>{
+            reject(err);
+        });
+    });
+}
+
+export function removeSeat(id) {
+    return deleteSubscriber(id);
+}
diff --git a/src/api/subscriber.js b/src/api/subscriber.js
index 54e311d2..98fee1ed 100644
--- a/src/api/subscriber.js
+++ b/src/api/subscriber.js
@@ -189,7 +189,7 @@ export function createSubscriber(subscriber) {
         }).then((res)=>{
             resolve(_.last(_.split(res.headers.get('Location'), '/')));
         }).catch((err)=>{
-            if(err.status === 422) {
+            if(err.status >= 400) {
                 reject(new Error(err.body.message));
             } else {
                 reject(err);
@@ -203,7 +203,7 @@ export function deleteSubscriber(id) {
         Vue.http.delete('/api/subscribers/' + id).then((res)=>{
             resolve();
         }).catch((err)=>{
-            if(err.status === 422) {
+            if(err.status >= 400) {
                 reject(new Error(err.body.message));
             } else {
                 reject(err);
diff --git a/src/components/layouts/Default.vue b/src/components/layouts/Default.vue
index 4b55f29c..eb4f6e37 100644
--- a/src/components/layouts/Default.vue
+++ b/src/components/layouts/Default.vue
@@ -127,7 +127,8 @@
         QSideLink,
         QTransition,
         QCollapsible,
-        Platform
+        Platform,
+        QWindowResizeObservable
     } from 'quasar-framework'
     export default {
         name: 'default',
@@ -170,7 +171,8 @@
             QSideLink,
             QTransition,
             QCollapsible,
-            CscCall
+            CscCall,
+            QWindowResizeObservable
         },
         computed: {
             ...mapGetters('layout', [
@@ -229,7 +231,6 @@
         },
         methods: {
             onWindowResize() {
-                this.applyLayout();
             },
             toggleFullscreen() {
                 this.$store.commit('layout/toggleFullscreen');
diff --git a/src/components/pages/PbxConfiguration/CscPbxGroup.vue b/src/components/pages/PbxConfiguration/CscPbxGroup.vue
index bde8c202..6fc32b87 100644
--- a/src/components/pages/PbxConfiguration/CscPbxGroup.vue
+++ b/src/components/pages/PbxConfiguration/CscPbxGroup.vue
@@ -1,13 +1,14 @@
 <template>
     <q-card class="csc-pbx-group">
-        <q-card-title>
-            <q-icon name="group" color="primary" size="22px"/>
-            <span class="csc-pbx-group-title">{{ group.display_name }}</span>
-            <q-chip pointing="left" color="primary">
+        <q-card-title class="cursor-pointer" @click="toggleMain()">
+            <q-icon name="group" color="primary" size="24px"/>
+            <span v-if="!expanded" class="csc-pbx-group-title">{{ group.display_name }}</span>
+            <q-chip v-if="!expanded" pointing="left" color="primary">
                 {{ $t('pbxConfig.extension') }}: <span class="csc-important">{{ group.pbx_extension }}</span>
             </q-chip>
+            <q-icon :name="titleIcon" color="primary" size="22px" slot="right"/>
         </q-card-title>
-        <q-card-main>
+        <q-card-main v-if="expanded" class="transition-generic">
             <q-field :label="$t('pbxConfig.groupName')">
                 <q-input v-model="name" readonly />
             </q-field>
@@ -31,7 +32,7 @@
             </q-field>
         </q-card-main>
         <q-card-actions align="center">
-            <q-btn :loader="isLoading" v-model="isLoading" flat round
+            <q-btn :loader="isLoading" v-model="isLoading" flat :small="isMobile" :round="isMobile"
                    color="negative" icon="delete" @click="remove()">Delete</q-btn>
         </q-card-actions>
         <q-inner-loading :visible="isLoading">
@@ -55,18 +56,23 @@
         QChip,
         QBtn,
         QInnerLoading,
-        QSpinnerMat
+        QSpinnerMat,
+        QTransition,
+        Platform
     } from 'quasar-framework'
     export default {
         name: 'csc-pbx-group',
-        props: ['group',
+        props: [
+            'group',
             'huntPolicyOptions',
             'aliasNumberOptions',
             'seatOptions',
             'loading'
         ],
         data () {
-            return {}
+            return {
+                expanded: false
+            }
         },
         components: {
             QCard,
@@ -80,7 +86,8 @@
             QChip,
             QBtn,
             QInnerLoading,
-            QSpinnerMat
+            QSpinnerMat,
+            QTransition
         },
         computed: {
             id() {
@@ -140,9 +147,26 @@
                     cardClasses.push('light-dimmed');
                 }
                 return cardClasses;
+            },
+            titleIcon() {
+                if(this.expanded) {
+                    return 'keyboard arrow down';
+                } else {
+                    return 'keyboard arrow up';
+                }
+            },
+            isMobile() {
+                return Platform.is.mobile;
             }
         },
         methods: {
+            toggleMain() {
+                if(this.expanded) {
+                    this.expanded = false;
+                } else {
+                    this.expanded = true;
+                }
+            },
             remove() {
                 this.$emit('remove', this.groupModel);
             }
diff --git a/src/components/pages/PbxConfiguration/CscPbxSeat.vue b/src/components/pages/PbxConfiguration/CscPbxSeat.vue
new file mode 100644
index 00000000..4563717a
--- /dev/null
+++ b/src/components/pages/PbxConfiguration/CscPbxSeat.vue
@@ -0,0 +1,186 @@
+<template>
+    <q-card class="csc-pbx-seat">
+        <q-card-title class="cursor-pointer" @click="toggleMain()">
+            <q-icon name="person" color="primary" size="24px"/>
+            <span v-if="!expanded" class="csc-pbx-seat-title">{{ name }}</span>
+            <q-chip v-if="!expanded" pointing="left" color="primary">
+                {{ $t('pbxConfig.extension') }}: <span class="csc-important">{{ extension }}</span>
+            </q-chip>
+            <q-icon :name="titleIcon" color="primary" size="22px" slot="right"/>
+        </q-card-title>
+        <q-card-main v-if="expanded">
+            <q-field :label="$t('pbxConfig.seatName')">
+                <q-input v-model="name" readonly />
+            </q-field>
+            <q-field :label="$t('pbxConfig.extension')">
+                <q-input v-model="extension" readonly />
+            </q-field>
+            <q-field :label="$t('pbxConfig.primaryNumber')">
+                <q-input v-model="primaryNumber" readonly disabled />
+            </q-field>
+            <q-field :label="$t('pbxConfig.aliasNumbers')">
+                <q-select v-model="aliasNumbers" :options="aliasNumberOptions" multiple chips readonly clearable />
+            </q-field>
+            <q-field :label="$t('pbxConfig.groups')">
+                <q-select v-model="groups" :options="groupOptions" multiple chips readonly clearable />
+            </q-field>
+        </q-card-main>
+        <q-card-actions align="center">
+            <q-btn flat :small="isMobile" :round="isMobile" color="negative"
+                   icon="delete" @click="remove()">Delete</q-btn>
+        </q-card-actions>
+        <q-inner-loading :visible="isLoading">
+            <q-spinner-mat size="60px" color="primary"></q-spinner-mat>
+        </q-inner-loading>
+    </q-card>
+</template>
+
+<script>
+    import _ from 'lodash';
+    import numberFilter from '../../../filters/number'
+    import {
+        QCard,
+        QCardTitle,
+        QCardMain,
+        QCardActions,
+        QField,
+        QInput,
+        QIcon,
+        QSelect,
+        QChip,
+        QBtn,
+        QInnerLoading,
+        QSpinnerMat,
+        QTransition,
+        Platform,
+        Dialog
+    } from 'quasar-framework'
+    export default {
+        name: 'csc-pbx-seat',
+        props: [
+            'seat',
+            'aliasNumberOptions',
+            'groupOptions',
+            'deleting'
+        ],
+        data () {
+            return {
+                expanded: false
+            }
+        },
+        components: {
+            QCard,
+            QCardTitle,
+            QCardMain,
+            QCardActions,
+            QField,
+            QInput,
+            QIcon,
+            QSelect,
+            QChip,
+            QBtn,
+            QInnerLoading,
+            QSpinnerMat,
+            QTransition
+        },
+        computed: {
+            id() {
+                return this.seat.id;
+            },
+            name() {
+                return this.seat.display_name;
+            },
+            extension() {
+                return this.seat.pbx_extension;
+            },
+            primaryNumber() {
+                return numberFilter(this.seat.primary_number);
+            },
+            aliasNumbers() {
+                let numbers = [];
+                if(_.isArray(this.seat.alias_numbers)) {
+                    this.seat.alias_numbers.forEach((number)=>{
+                        numbers.push(number.number_id);
+                    });
+                }
+                return numbers;
+            },
+            groups() {
+                let groups = [];
+                if(_.isArray(this.seat.groups)) {
+                    this.seat.groups.forEach((group)=>{
+                        groups.push(group.id);
+                    });
+                }
+                return groups;
+            },
+            seatModel() {
+                return {
+                    id: this.id,
+                    name: this.name,
+                    extension: this.extension,
+                    primaryNumber: this.primaryNumber,
+                    aliasNumbers: this.aliasNumbers,
+                    groups: this.groups
+                }
+            },
+            isLoading() {
+                return this.deleting;
+            },
+            cardClasses() {
+                var cardClasses = ['csc-pbx-seat'];
+                if(this.isLoading) {
+                    cardClasses.push('light-dimmed');
+                }
+                return cardClasses;
+            },
+            titleIcon() {
+                if(this.expanded) {
+                    return 'keyboard arrow down';
+                } else {
+                    return 'keyboard arrow up';
+                }
+            },
+            isMobile() {
+                return Platform.is.mobile;
+            }
+        },
+        methods: {
+            toggleMain() {
+                this.expanded = !this.expanded
+            },
+            remove() {
+                var store = this.$store;
+                var state = this;
+                var i18n = this.$i18n;
+                Dialog.create({
+                    title: i18n.t('pbxConfig.removeSeatTitle'),
+                    message: i18n.t('pbxConfig.removeSeatText', { seat: this.name }),
+                    buttons: [
+                        'Cancel',
+                        {
+                            label: i18n.t('pbxConfig.removeSeat'),
+                            color: 'negative',
+                            handler () {
+                                state.loading = true;
+                                state.$emit('remove', state.seatModel);
+                            }
+                        }
+                    ]
+                });
+            }
+        }
+    }
+</script>
+
+<style>
+    .csc-pbx-seat {
+        position: relative;
+    }
+    .csc-pbx-seat .csc-pbx-seat-title {
+        padding-left: 8px;
+    }
+    .csc-important {
+        font-weight: bold;
+    }
+</style>
diff --git a/src/components/pages/PbxConfiguration/CscPbxSeatAddForm.vue b/src/components/pages/PbxConfiguration/CscPbxSeatAddForm.vue
new file mode 100644
index 00000000..cd2174ed
--- /dev/null
+++ b/src/components/pages/PbxConfiguration/CscPbxSeatAddForm.vue
@@ -0,0 +1,152 @@
+<template>
+    <div class="csc-add-form csc-pbx-seat-add-form">
+        <q-card v-if="enabled">
+            <q-card-title>
+                <q-icon name="add" color="primary" size="24px"/>
+                <span>{{ $t('pbxConfig.addSeat') }}</span>
+            </q-card-title>
+            <q-card-main>
+                <q-field>
+                    <q-input :disabled="isRequesting" ref="name" v-model="form.name" autofocus
+                             :float-label="$t('pbxConfig.seatName')" clearable />
+                </q-field>
+                <q-field>
+                    <q-input :disabled="isRequesting" type="number" v-model="form.extension" clearable
+                             min="1" max="1000000" :float-label="$t('pbxConfig.extension')"  />
+                </q-field>
+                <q-field>
+                    <q-select :disabled="isRequesting" v-model="form.aliasNumbers" multiple chips readonly clearable
+                              :float-label="$t('pbxConfig.aliasNumbers')" :options="aliasNumberOptions" />
+                </q-field>
+                <q-field>
+                    <q-select :disabled="isRequesting" v-model="form.groups" multiple chips readonly clearable
+                              :float-label="$t('pbxConfig.groups')" :options="groupOptions" />
+                </q-field>
+            </q-card-main>
+            <q-card-separator/>
+            <q-card-actions align="center">
+                <q-btn v-if="!isRequesting" flat color="secondary" icon="clear"
+                       @click="cancel()">{{ $t('buttons.cancel') }}</q-btn>
+                <q-btn loader v-model="isRequesting" flat color="primary" icon="done"
+                       @click="save()">{{ $t('buttons.save') }}</q-btn>
+            </q-card-actions>
+            <q-inner-loading :visible="isRequesting">
+                <q-spinner-mat size="60px" color="primary"></q-spinner-mat>
+            </q-inner-loading>
+        </q-card>
+        <q-card v-else flat>
+            <q-card-actions align="center">
+                <q-btn color="primary" icon="add" flat @click="add()">{{ $t('pbxConfig.addSeat') }}</q-btn>
+            </q-card-actions>
+        </q-card>
+    </div>
+</template>
+
+<script>
+    import {
+        QChip,
+        QCard,
+        QCardSeparator,
+        QCardTitle,
+        QCardMain,
+        QCardActions,
+        QIcon,
+        QPopover,
+        QList,
+        QItem,
+        QItemMain,
+        QField,
+        QInput,
+        QBtn,
+        QSelect,
+        QInnerLoading,
+        QSpinnerDots,
+        QSpinnerMat,
+        Dialog
+    } from 'quasar-framework'
+
+    export default {
+        name: 'csc-pbx-seat-add-form',
+        props: [
+            'aliasNumberOptions',
+            'groupOptions'
+        ],
+        components: {
+            QChip,
+            QCard,
+            QCardSeparator,
+            QCardTitle,
+            QCardMain,
+            QCardActions,
+            QIcon,
+            QPopover,
+            QList,
+            QItem,
+            QItemMain,
+            QField,
+            QInput,
+            QBtn,
+            QSelect,
+            QInnerLoading,
+            QSpinnerDots,
+            QSpinnerMat,
+            Dialog
+        },
+        data () {
+            return {
+                form: this.getDefaultData(),
+                enabled: false,
+                loading: false
+            }
+        },
+        computed: {
+            isRequesting() {
+                return this.loading;
+            }
+        },
+        methods: {
+            getDefaultData() {
+                return {
+                    name: '',
+                    extension: '',
+                    aliasNumbers: [],
+                    groups: []
+                }
+            },
+            cancel() {
+                this.enabled = false;
+            },
+            add() {
+                this.enabled = true;
+                this.form =  this.getDefaultData();
+            },
+            save() {
+                this.loading = true;
+                this.$emit('save', {
+                    name: this.form.name,
+                    extension: this.form.extension,
+                    aliasNumbers: this.form.aliasNumbers,
+                    groups: this.form.groups
+                });
+            },
+            succeeded() {
+                this.loading = false;
+                this.enabled = false;
+            },
+            failed() {
+                this.loading = false;
+                this.enabled = true;
+            }
+        }
+    }
+</script>
+
+<style lang="stylus">
+    @import '../../../../src/themes/app.variables.styl';
+    .csc-pbx-seat-add-form .q-card {
+        position: relative;
+    }
+    .csc-pbx-seat-add-form .q-card .q-field:last-child {
+        margin-bottom: 36px;
+    }
+</style>
diff --git a/src/components/pages/PbxConfiguration/CscPbxSeatList.vue b/src/components/pages/PbxConfiguration/CscPbxSeatList.vue
new file mode 100644
index 00000000..2f1c9960
--- /dev/null
+++ b/src/components/pages/PbxConfiguration/CscPbxSeatList.vue
@@ -0,0 +1,53 @@
+<template>
+    <div class="csc-pbx-seat-list">
+        <q-card v-if="loading" flat>
+            <q-card-actions align="center">
+                <q-spinner-dots  color="primary" :size="40"/>
+            </q-card-actions>
+        </q-card>
+        <csc-pbx-seat v-for="seat in seats" :seat="seat" @remove="remove" :deleting="isDeleting(seat)"
+                      :alias-number-options="aliasNumberOptions" :group-options="groupOptions" />
+    </div>
+</template>
+
+<script>
+    import {
+        QCard,
+        QCardActions,
+        QSpinnerDots
+    } from 'quasar-framework'
+    import CscPbxSeat from './CscPbxSeat'
+
+    export default {
+        name: 'csc-pbx-seat-list',
+        components: {
+            QCard,
+            QCardActions,
+            QSpinnerDots,
+            CscPbxSeat
+        },
+        props: [
+            'seats',
+            'loading',
+            'aliasNumberOptions',
+            'groupOptions',
+            'deletingSeat'
+        ],
+        data () {
+            return {
+
+            }
+        },
+        methods: {
+            remove(seat) {
+                this.$emit('remove', seat);
+            },
+            isDeleting(seat) {
+                return this.deletingSeat !== null && seat.id === this.deletingSeat.id;
+            }
+        }
+    }
+</script>
+
+<style>
+</style>
diff --git a/src/components/pages/PbxConfiguration/Seats.vue b/src/components/pages/PbxConfiguration/Seats.vue
index 14aad75b..ca6a6ce8 100644
--- a/src/components/pages/PbxConfiguration/Seats.vue
+++ b/src/components/pages/PbxConfiguration/Seats.vue
@@ -1,22 +1,23 @@
 <template>
     <csc-page title="Seats">
-        <q-card v-for="seat in seats" class="pbx-seat">
-            <q-card-title>
-                <q-icon name="person" color="primary" size="22px"/>
-                <span class="pbx-seat-title">{{ seat.display_name }}</span>
-                <csc-number-chip :item="seat" />
-            </q-card-title>
-        </q-card>
+        <csc-pbx-seat-add-form ref="addForm" :alias-number-options="aliasNumberOptions"
+                               :group-options="groupOptions" @save="save" />
+        <csc-pbx-seat-list :alias-number-options="aliasNumberOptions" :group-options="groupOptions"
+                           :seats="seats" :loading="isListLoading" @remove="remove" :deleting-seat="deletingSeat" />
     </csc-page>
 </template>
 
 <script>
     import CscPage  from '../../CscPage'
-    import CscNumberChip  from '../../card/CscNumberChip'
+    import CscPbxSeatAddForm  from './CscPbxSeatAddForm'
+    import CscPbxSeatList  from './CscPbxSeatList'
     import { QChip, QCard, QCardSeparator, QCardTitle, QCardMain,
         QIcon, QPopover, QList, QItem, QItemMain } from 'quasar-framework'
+    import aliasNumberOptions from '../../../mixins/alias-number-options'
+    import { startLoading, stopLoading, showGlobalError, showToast } from '../../../helpers/ui'
 
     export default {
+        mixins: [aliasNumberOptions],
         mounted() {
             this.$store.dispatch('pbxConfig/listSeats');
         },
@@ -25,7 +26,6 @@
         },
         components: {
             CscPage,
-            CscNumberChip,
             QChip,
             QCard,
             QCardSeparator,
@@ -35,11 +35,69 @@
             QPopover,
             QList,
             QItem,
-            QItemMain
+            QItemMain,
+            CscPbxSeatAddForm,
+            CscPbxSeatList
         },
         computed: {
+            addFormSucceeded() {
+                return this.$store.state.pbxConfig.addSeatState === 'succeeded';
+            },
+            addFormFailed() {
+                return this.$store.state.pbxConfig.addSeatState === 'failed';
+            },
+            addFormError() {
+                return this.$store.state.pbxConfig.addSeatError;
+            },
+            isListLoading() {
+                return this.$store.state.pbxConfig.listAllState === 'requesting';
+            },
+            removeError() {
+                return this.$store.state.pbxConfig.removeSeatError;
+            },
+            groupOptions() {
+                let groups = [];
+                this.groups.forEach((group)=>{
+                    groups.push({
+                        label: group.display_name,
+                        sublabel: this.$t('pbxConfig.extension') + ': ' + group.pbx_extension,
+                        value: group.id
+                    });
+                });
+                return groups;
+            },
             seats() {
                 return this.$store.getters['pbxConfig/seats'];
+            },
+            groups() {
+                return this.$store.getters['pbxConfig/groups'];
+            },
+            deletingSeat() {
+                return this.$store.state.pbxConfig.removeSeatItem;
+            }
+        },
+        methods: {
+            save(seat) {
+                this.$store.dispatch('pbxConfig/addSeat', seat);
+            },
+            remove(seat) {
+                this.$store.dispatch('pbxConfig/removeSeat', seat);
+            }
+        },
+        watch: {
+            addFormSucceeded() {
+                this.$refs.addForm.succeeded();
+            },
+            addFormFailed() {
+                if(this.addFormError !== null) {
+                    this.$refs.addForm.failed();
+                    showGlobalError(this.addFormError);
+                }
+            },
+            removeError() {
+                if(this.removeError !== null) {
+                    showGlobalError(this.removeError);
+                }
             }
         }
     }
diff --git a/src/helpers/ui.js b/src/helpers/ui.js
index 97ebaa82..8170a2cd 100644
--- a/src/helpers/ui.js
+++ b/src/helpers/ui.js
@@ -26,3 +26,7 @@ export function showToast(message) {
         bgColor: '#68A44E'
     });
 }
+
+export function removeDialog(options) {
+
+}
diff --git a/src/locales/en.json b/src/locales/en.json
index bd5da5fb..ef2bba0e 100644
--- a/src/locales/en.json
+++ b/src/locales/en.json
@@ -165,8 +165,9 @@
         "seat": "Seat",
         "seats": "Seats",
         "group": "Group",
+        "groups": "Groups",
         "extension": "Extension",
-        "groupName": "Name",
+        "groupName": "Group Name",
         "huntPolicy": "Hunt Policy",
         "huntTimeout": "Hunt Timeout",
         "primaryNumber": "Primary Number",
@@ -178,8 +179,13 @@
         "allocatedByNobody": "Free",
         "allocatedBy": "Allocated by {type} {name}",
         "addGroup": "Add Group",
-        "removeGroup": "Remove",
+        "removeGroup": "Remove group",
         "removeGroupTitle": "Remove group",
-        "removeGroupText": "You are about to remove group \"{group}\""
+        "removeGroupText": "You are about to remove group \"{group}\"",
+        "seatName": "Seat Name",
+        "addSeat": "Add Seat",
+        "removeSeat": "Remove seat",
+        "removeSeatTitle": "Remove seat",
+        "removeSeatText": "You are about to remove seat \"{seat}\""
     }
 }
diff --git a/src/mixins/alias-number-options.js b/src/mixins/alias-number-options.js
new file mode 100644
index 00000000..59976b21
--- /dev/null
+++ b/src/mixins/alias-number-options.js
@@ -0,0 +1,35 @@
+'use strict';
+
+import numberFilter from '../filters/number';
+
+export default {
+    computed: {
+        aliasNumbers() {
+            return this.$store.getters['pbxConfig/aliasNumbers'];
+        },
+        aliasNumberOptions() {
+            let aliasNumber = [];
+            this.aliasNumbers.forEach((number)=>{
+                let owner = this.$t('pbxConfig.allocatedByNobody');
+                if(number.subscriber !== null && number.subscriber.display_name !== null &&
+                    number.subscriber.is_pbx_group) {
+                    owner = this.$t('pbxConfig.allocatedBy', {
+                        type: this.$t('pbxConfig.group'),
+                        name:  number.subscriber.display_name
+                    });
+                } else if (number.subscriber !== null && number.subscriber.display_name !== null) {
+                    owner = this.$t('pbxConfig.allocatedBy', {
+                        type: this.$t('pbxConfig.seat'),
+                        name:  number.subscriber.display_name
+                    });
+                }
+                aliasNumber.push({
+                    label: numberFilter(number),
+                    sublabel: owner,
+                    value: number.id
+                });
+            });
+            return aliasNumber;
+        }
+    }
+};
diff --git a/src/store/pbx-config.js b/src/store/pbx-config.js
index 5bdcdf05..8099eff0 100644
--- a/src/store/pbx-config.js
+++ b/src/store/pbx-config.js
@@ -1,6 +1,6 @@
 
 import _ from 'lodash';
-import { getPbxConfiguration, addGroup, removeGroup } from '../api/pbx-config'
+import { getPbxConfiguration, addGroup, removeGroup, addSeat, removeSeat } from '../api/pbx-config'
 
 const ListState = {
     initiated: 'initiated',
@@ -9,7 +9,7 @@ const ListState = {
     failed: 'failed'
 };
 
-const AddGroupState = {
+const AddState = {
     button: 'button',
     input: 'input',
     requesting: 'requesting',
@@ -17,7 +17,7 @@ const AddGroupState = {
     failed: 'failed'
 };
 
-const RemoveGroupState = {
+const RemoveState = {
     initiated: 'initiated',
     requesting: 'requesting',
     succeeded: 'succeeded',
@@ -36,11 +36,16 @@ export default {
         numbersMap : {},
         listAllState: ListState.initiated,
         listAllError: null,
-        addGroupState: AddGroupState.button,
+        addGroupState: AddState.button,
         addGroupError: null,
-        removeGroupState: RemoveGroupState.initiated,
+        removeGroupState: RemoveState.initiated,
         removeGroupError: null,
-        removeGroupItem: null
+        removeGroupItem: null,
+        addSeatState: AddState.button,
+        addSeatError: null,
+        removeSeatState: RemoveState.initiated,
+        removeSeatError: null,
+        removeSeatItem: null
     },
     getters: {
         groups(state, getters) {
@@ -82,7 +87,7 @@ export default {
             state.listAllState = ListState.requesting;
         },
         listAllSucceeded(state, all) {
-            state.removeGroupState = RemoveGroupState.initiated;
+            state.RemoveState = RemoveState.initiated;
             state.listAllState = ListState.succeeded;
             state.listAllError = null;
             state.pilot = all.pilot;
@@ -131,30 +136,56 @@ export default {
             state.listAllError = error;
         },
         addGroupRequesting(state){
-            state.addGroupState = AddGroupState.requesting;
+            state.addGroupState = AddState.requesting;
             state.addGroupError = null;
         },
         addGroupSucceeded(state){
-            state.addGroupState = AddGroupState.succeeded;
+            state.addGroupState = AddState.succeeded;
             state.addGroupError = null;
         },
         addGroupFailed(state, error) {
-            state.addGroupState = AddGroupState.failed;
+            state.addGroupState = AddState.failed;
             state.addGroupError = error;
         },
         removeGroupRequesting(state, group) {
-            state.removeGroupState = RemoveGroupState.requesting;
+            state.removeGroupState = RemoveState.requesting;
             state.removeGroupError = null;
             state.removeGroupItem = group;
         },
         removeGroupSucceeded(state) {
-            state.removeGroupState = RemoveGroupState.succeeded;
+            state.removeGroupState = RemoveState.succeeded;
             state.removeGroupError = null;
         },
         removeGroupFailed(state, message) {
-            state.removeGroupState = RemoveGroupState.failed;
+            state.removeGroupState = RemoveState.failed;
             state.removeGroupError = message;
-        }
+        },
+        addSeatRequesting(state){
+            state.addSeatState = AddState.requesting;
+            state.addSeatError = null;
+        },
+        addSeatSucceeded(state){
+            state.addSeatState = AddState.succeeded;
+            state.addSeatError = null;
+        },
+        addSeatFailed(state, error) {
+            state.addSeatState = AddState.failed;
+            state.addSeatError = error;
+        },
+        removeSeatRequesting(state, seat) {
+            state.removeSeatState = RemoveState.requesting;
+            state.removeSeatError = null;
+            state.removeSeatItem = seat;
+        },
+        removeSeatSucceeded(state) {
+            state.removeSeatState = RemoveState.succeeded;
+            state.removeSeatError = null;
+        },
+        removeSeatFailed(state, message) {
+            state.removeSeatState = RemoveState.failed;
+            state.removeSeatError = message;
+            state.removeSeatItem = null;
+        },
     },
     actions: {
         listSeats(context) {
@@ -187,6 +218,26 @@ export default {
             }).catch((err)=>{
                 context.commit('removeGroupFailed', err.message);
             });
+        },
+        addSeat(context, seat) {
+            seat.customerId = context.state.pilot.customer_id;
+            seat.domainId = context.state.pilot.domain_id;
+            context.commit('addSeatRequesting', seat);
+            addSeat(seat).then(()=>{
+                context.commit('addSeatSucceeded', seat);
+                context.dispatch('listGroups');
+            }).catch((err)=>{
+                context.commit('addSeatFailed', err.message);
+            });
+        },
+        removeSeat(context, seat) {
+            context.commit('removeSeatRequesting', seat);
+            removeSeat(seat.id).then(()=>{
+                context.commit('removeSeatSucceeded');
+                context.dispatch('listGroups');
+            }).catch((err)=>{
+                context.commit('removeSeatFailed', err.message);
+            });
         }
     }
 };