diff --git a/src/briar/api/api.py b/src/briar/api/api.py
index 44ad5d96c3dda43bc060a309627ea5ce18bf12cf..1a8a99aca6bbff92b136fe2005a6966c0a70c8e8 100644
--- a/src/briar/api/api.py
+++ b/src/briar/api/api.py
@@ -2,8 +2,10 @@
 # SPDX-License-Identifier: AGPL-3.0-only
 # License-Filename: LICENSE.md
 
-from briar.api.constants import Constants
+from briar.api.constants import BASE_HTTP_URL, BRIAR_AUTH_TOKEN, BRIAR_DB
+from briar.api.models.socket_listener import SocketListener
 
+from os.path import isfile
 from subprocess import Popen, PIPE, STDOUT
 from threading import Thread
 from time import sleep
@@ -14,18 +16,17 @@ from urllib.request import urlopen
 class Api:
 
     auth_token = None
+    socket_listener = None
+
     _process = None
 
     def __init__(self, headless_jar):
-        self._command = ['java', '-jar', headless_jar]
-        self.constants = Constants()
-        self._load_auth_token()
+        self._command = ["java", "-jar", headless_jar]
+
+        self.socket_listener = SocketListener(self)
 
     def has_account(self):
-        from pathlib import Path
-        home = str(Path.home())
-        from os.path import isdir, join
-        return isdir(join(home, ".briar", "db"))
+        return isfile(BRIAR_DB)
 
     def is_running(self):
         return (self._process is not None) and (self._process.poll() is None)
@@ -61,22 +62,22 @@ class Api:
     def _watch_thread(self, callback):
         while self.is_running():
             try:
+                urlopen(BASE_HTTP_URL)
                 sleep(0.1)
-                print(urlopen(self.constants.get_base_url()).getcode())
-            except HTTPError as e:
-                if(e.code == 404):
+            except HTTPError as http_error:
+                if(http_error.code == 404):
                     self._load_auth_token()
                     callback(True)
                     return
-            except URLError as e:
-                if not isinstance(e.reason, ConnectionRefusedError):
-                    raise e
+            except URLError as url_error:
+                if not isinstance(url_error.reason, ConnectionRefusedError):
+                    raise url_error
         callback(False)
 
     def _login(self, password):
         if not self.is_running():
             raise Exception("Can't login; API not running")
-        self._process.communicate((password + '\n').encode("utf-8"))
+        self._process.communicate(("%s\n" % password).encode("utf-8"))
 
     def _register(self, credentials):
         if not self.is_running():
@@ -87,7 +88,7 @@ class Api:
 
     def _load_auth_token(self):
         if not self.has_account():
-            return
-        with open(self.constants.get_auth_token(), 'r') as file:
+            raise Exception("Can't load authentication token")
+        with open(BRIAR_AUTH_TOKEN, 'r') as file:
             self.auth_token = file.read()
 
diff --git a/src/briar/api/constants.py b/src/briar/api/constants.py
index 10c7d9701977bce227edafb31cb7e82405f60b92..94794a1ab75650b52e0a913f695160df0529d7ce 100644
--- a/src/briar/api/constants.py
+++ b/src/briar/api/constants.py
@@ -6,17 +6,13 @@ from os.path import join
 from pathlib import Path
 from urllib.parse import urljoin
 
+_BRIAR_DIR = ".briar"
 
-class Constants:
+_HOST = "%s://localhost:7000"
+_VERSION_SUFFIX = "v1/"
 
-    _BRIAR_AUTH_TOKEN = 'auth_token'
-    _BRIAR_DIR = '.briar'
+BRIAR_AUTH_TOKEN = join(Path.home(), _BRIAR_DIR, "auth_token")
+BRIAR_DB = join(Path.home(), _BRIAR_DIR, "db", "db.mv.db")
 
-    _HOST = 'http://localhost:7000'
-    _VERSION_SUFFIX = 'v1/'
-
-    def get_auth_token(self):
-        return join(Path.home(), self._BRIAR_DIR, self._BRIAR_AUTH_TOKEN)
-
-    def get_base_url(self):
-        return urljoin(self._HOST, self._VERSION_SUFFIX)
+BASE_HTTP_URL = urljoin(_HOST % "http", _VERSION_SUFFIX)
+WEBSOCKET_URL = urljoin(_HOST % "ws", "%s/ws" % _VERSION_SUFFIX)
diff --git a/src/briar/api/models/contacts.py b/src/briar/api/models/contacts.py
index b80d38059c7c45236f62a8775d93b16c7d15838b..69e5524d560a15d6bf8c80606a36b3d00c8b0c5f 100644
--- a/src/briar/api/models/contacts.py
+++ b/src/briar/api/models/contacts.py
@@ -2,6 +2,7 @@
 # SPDX-License-Identifier: AGPL-3.0-only
 # License-Filename: LICENSE.md
 
+from briar.api.constants import BASE_HTTP_URL
 from briar.api.models.model import Model
 
 from requests import get as _get
@@ -11,7 +12,6 @@ from urllib.parse import urljoin
 class Contacts(Model):
 
     def get(self):
-        headers = {'Authorization': 'Bearer ' + self._api.auth_token}
-        url = urljoin(self._constants.get_base_url(), 'contacts')
-        r = _get(url, headers=headers)
+        url = urljoin(BASE_HTTP_URL, 'contacts')
+        r = _get(url, headers=self._headers)
         return r.json()
diff --git a/src/briar/api/models/model.py b/src/briar/api/models/model.py
index 8c1c89c31978479242cf65a3d20b1a59a6b23f38..e28cb2d5a470519d8af852ea6f5731f9327dd827 100644
--- a/src/briar/api/models/model.py
+++ b/src/briar/api/models/model.py
@@ -5,6 +5,11 @@
 
 class Model:
 
+    _headers = {}
+
     def __init__(self, api):
         self._api = api
-        self._constants = api.constants
+        self._initialize_headers()
+
+    def _initialize_headers(self):
+        self._headers['Authorization'] = 'Bearer %s' % self._api.auth_token
diff --git a/src/briar/api/models/private_chat.py b/src/briar/api/models/private_chat.py
index c11fadbd72e8ee0ec9b0fd7a5419819193667d90..db5a33dbf442f46bd3d8ee643603a1300e2d94ad 100644
--- a/src/briar/api/models/private_chat.py
+++ b/src/briar/api/models/private_chat.py
@@ -2,8 +2,8 @@
 # SPDX-License-Identifier: AGPL-3.0-only
 # License-Filename: LICENSE.md
 
+from briar.api.constants import BASE_HTTP_URL
 from briar.api.models.model import Model
-from briar.api.models.socket_listener import SocketListener
 
 from requests import get as _get
 from requests import post as _post
@@ -13,17 +13,15 @@ from urllib.parse import urljoin
 class PrivateChat(Model):
 
     def get(self, contact_id):
-        headers = {'Authorization': 'Bearer ' + self._api.auth_token}
-        url = urljoin(self._constants.get_base_url(), 'messages/%i' % contact_id)
-        r = _get(url, headers=headers)
-        return r.json()
+        url = urljoin(BASE_HTTP_URL, 'messages/%i' % contact_id)
+        request = _get(url, headers=self._headers)
+        return request.json()
 
     def watch_messages(self, contact_id, callback):
-        socket_listener = SocketListener(self._api)
-        socket_listener.watch(callback, "ConversationMessageReceivedEvent",
-                              contact_id=contact_id)
+        self._api.socket_listener.watch(callback,
+                                        "ConversationMessageReceivedEvent",
+                                        contact_id=contact_id)
 
     def send(self, contact_id, message):
-        headers = {'Authorization': 'Bearer ' + self._api.auth_token}
-        url = urljoin(self._constants.get_base_url(), 'messages/%s' % contact_id)
-        _post(url, headers=headers, json={'text': message})
+        url = urljoin(BASE_HTTP_URL, 'messages/%s' % contact_id)
+        _post(url, headers=self._headers, json={'text': message})
diff --git a/src/briar/api/models/socket_listener.py b/src/briar/api/models/socket_listener.py
index 93646f4a75b0de4cc2fef4c5d13c853799c89a28..444ca3800ae078bc9082521108d91ab1eb6cc2a6 100644
--- a/src/briar/api/models/socket_listener.py
+++ b/src/briar/api/models/socket_listener.py
@@ -2,6 +2,7 @@
 # SPDX-License-Identifier: AGPL-3.0-only
 # License-Filename: LICENSE.md
 
+from briar.api.constants import WEBSOCKET_URL
 from briar.api.models.model import Model
 
 import asyncio
@@ -10,6 +11,7 @@ from threading import Thread
 import websockets
 
 
+# TODO: Make more general; currently very specific to private messages
 class SocketListener(Model):
 
     def watch(self, callback, event, contact_id="0"):
@@ -26,16 +28,17 @@ class SocketListener(Model):
         loop.close()
 
     async def _start_websocket(self, callback, event, contact_id="0"):
-        async with websockets.connect('ws://localhost:7000/v1/ws') as websocket:
+        async with websockets.connect(WEBSOCKET_URL) as websocket:
             await websocket.send(self._api.auth_token)
-            await self._watch_messages(websocket, callback)
+            await self._watch_messages(websocket, event, callback)
 
-    async def _watch_messages(self, websocket, callback):
-        while not websocket.closed and not asyncio.get_event_loop().is_closed():
+    async def _watch_messages(self, websocket, event, callback):
+        while not websocket.closed and not\
+                         asyncio.get_event_loop().is_closed():
             message = await websocket.recv()
-            m = json.loads(message)
-            if m['name'] == 'ConversationMessageReceivedEvent':
-                callback(m['data'])
+            message = json.loads(message)
+            if message['name'] == event:
+                callback(message['data'])
         if not asyncio.get_event_loop().is_closed():
             asyncio.get_event_loop().create_task(
                 self._watch_messages(websocket, callback))