diff --git a/src/briar/api/models/contacts.py b/src/briar/api/models/contacts.py
index 76698cab322aa194723af142ccaa62096b09a773..b80d38059c7c45236f62a8775d93b16c7d15838b 100644
--- a/src/briar/api/models/contacts.py
+++ b/src/briar/api/models/contacts.py
@@ -4,11 +4,14 @@
 
 from briar.api.models.model import Model
 
-import requests
+from requests import get as _get
+from urllib.parse import urljoin
 
 
-class Contacts (Model):
+class Contacts(Model):
 
     def get(self):
-        r = requests.get(self.constants.get_base_url())
-        print(r.status_code)
+        headers = {'Authorization': 'Bearer ' + self._api.auth_token}
+        url = urljoin(self._constants.get_base_url(), 'contacts')
+        r = _get(url, headers=headers)
+        return r.json()
diff --git a/src/briar/api/models/model.py b/src/briar/api/models/model.py
index a883e4d289136759d727fa9d1ccfd6d699582e38..8c1c89c31978479242cf65a3d20b1a59a6b23f38 100644
--- a/src/briar/api/models/model.py
+++ b/src/briar/api/models/model.py
@@ -7,4 +7,4 @@ class Model:
 
     def __init__(self, api):
         self._api = api
-        self.constants = api.constants
+        self._constants = api.constants
diff --git a/src/briar/api/models/private_chat.py b/src/briar/api/models/private_chat.py
new file mode 100644
index 0000000000000000000000000000000000000000..07bc9ddefdcf9e3dfda25ed2aa89df0feaeb9932
--- /dev/null
+++ b/src/briar/api/models/private_chat.py
@@ -0,0 +1,17 @@
+# Copyright (c) 2019 Nico Alt
+# SPDX-License-Identifier: AGPL-3.0-only
+# License-Filename: LICENSE.md
+
+from briar.api.models.model import Model
+
+from requests import get as _get
+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/' + contact_id)
+        r = _get(url, headers=headers)
+        return r.json()
diff --git a/src/briar/gtk/containers/chat.py b/src/briar/gtk/containers/chat.py
new file mode 100644
index 0000000000000000000000000000000000000000..21d8d121e647355aa7a86e0c6136a97e7e5e9d13
--- /dev/null
+++ b/src/briar/gtk/containers/chat.py
@@ -0,0 +1,34 @@
+# Copyright (c) 2019 Nico Alt
+# SPDX-License-Identifier: AGPL-3.0-only
+# License-Filename: LICENSE.md
+
+from briar.api.models.private_chat import PrivateChat
+from briar.gtk.container import Container
+from briar.gtk.define import App
+
+import gi
+gi.require_version('Gtk', '3.0')
+from gi.repository import Gtk
+
+
+class ChatContainer(Container):
+
+    def __init__(self, contact_id):
+        super().__init__()
+        self._api = App().api
+        self._setup_view()
+        self._load_content(contact_id)
+
+    def _setup_view(self):
+        self.builder.add_from_resource("/app/briar/gtk/ui/main.ui")
+        self.add(self.builder.get_object("main"))
+        self.builder.connect_signals(self)
+
+    def _load_content(self, contact_id):
+        private_chat = PrivateChat(self._api)
+        messages_list = private_chat.get(contact_id)
+        messages_list_box = self.builder.get_object("contacts_list")
+        for message in messages_list:
+            message_label = Gtk.Label(message["text"])
+            message_label.show()
+            messages_list_box.add(message_label)
diff --git a/src/briar/gtk/containers/main.py b/src/briar/gtk/containers/main.py
index b2a91150b0ee1886f635f9bf0176fcbe2c1ef6a1..dc63cb4afbed821918b2f318f72fe4f8698b3590 100644
--- a/src/briar/gtk/containers/main.py
+++ b/src/briar/gtk/containers/main.py
@@ -6,20 +6,39 @@ from briar.api.models.contacts import Contacts
 from briar.gtk.container import Container
 from briar.gtk.define import App
 
+import gi
+gi.require_version('Gtk', '3.0')
+from gi.repository import GLib, GObject, Gtk
+
 
 class MainContainer(Container):
 
     def __init__(self):
         super().__init__()
         self._api = App().api
-        self.__setup_view()
+        self._register_signals()
+        self._setup_view()
         self._load_content()
 
-    def __setup_view(self):
+    def _register_signals(self):
+        GObject.signal_new("briar_open_private_chat", Gtk.Overlay,
+                           GObject.SignalFlags.RUN_LAST, GObject.TYPE_BOOLEAN,
+                           (GObject.TYPE_STRING,))
+
+    def _setup_view(self):
         self.builder.add_from_resource("/app/briar/gtk/ui/main.ui")
         self.add(self.builder.get_object("main"))
         self.builder.connect_signals(self)
 
     def _load_content(self):
         contacts = Contacts(self._api)
-        contacts.get()
+        contacts_list = contacts.get()
+        contacts_list_box = self.builder.get_object("contacts_list")
+        for contact in contacts_list:
+            contact_label = Gtk.Button(contact["author"]["name"])
+            contact_label.connect("clicked", self._contact_clicked)
+            contact_label.show()
+            contacts_list_box.add(contact_label)
+
+    def _contact_clicked(self, contact):
+        GLib.idle_add(self.emit, "briar_open_private_chat", (contact,))
diff --git a/src/briar/gtk/containers/startup.py b/src/briar/gtk/containers/startup.py
index 67b267f030238cede00a12c9aa6c4512a3bba3c7..66930c962acda711b89ecabca441d125b3b3ea55 100644
--- a/src/briar/gtk/containers/startup.py
+++ b/src/briar/gtk/containers/startup.py
@@ -14,9 +14,9 @@ class StartupContainer(Container):
 
     def __init__(self):
         super().__init__()
-        self._setup_view()
-        self._register_signals()
         self._api = App().api
+        self._register_signals()
+        self._setup_view()
 
     def on_username_button_clicked(self, button):
         self.builder.get_object("username_grid").set_visible(False)
@@ -34,6 +34,11 @@ class StartupContainer(Container):
         password = self.builder.get_object("password_entry").get_text()
         self._api.login(password, self._startup_finished)
 
+    def _register_signals(self):
+        GObject.signal_new("briar_startup_completed", Gtk.Overlay,
+                           GObject.SignalFlags.RUN_LAST, GObject.TYPE_BOOLEAN,
+                           (GObject.TYPE_STRING,))
+
     def _setup_view(self):
         self.set_hexpand(True)
         self.set_vexpand(True)
@@ -45,11 +50,6 @@ class StartupContainer(Container):
             self.add(self.builder.get_object("login"))
         self.builder.connect_signals(self)
 
-    def _register_signals(self):
-        GObject.signal_new("briar_startup_completed", Gtk.Overlay,
-                           GObject.SignalFlags.RUN_LAST, GObject.TYPE_BOOLEAN,
-                           (GObject.TYPE_STRING,))
-
     def _startup_finished(self, succeeded):
         if succeeded:
             GLib.idle_add(self.emit, "briar_startup_completed", (succeeded,))
diff --git a/src/briar/gtk/window.py b/src/briar/gtk/window.py
index e11cb78121a3d72b42b34ffc6cb3145ee267361b..35eedca02ddd884e2a543b2529fad6307a450ebb 100644
--- a/src/briar/gtk/window.py
+++ b/src/briar/gtk/window.py
@@ -2,6 +2,7 @@
 # SPDX-License-Identifier: AGPL-3.0-only
 # License-Filename: LICENSE.md
 
+from briar.gtk.containers.chat import ChatContainer
 from briar.gtk.containers.main import MainContainer
 from briar.gtk.containers.startup import StartupContainer
 from briar.gtk.define import App
@@ -42,7 +43,6 @@ class Window(Gtk.ApplicationWindow):
     def __setup_startup_container(self):
         self.__container = StartupContainer()
         self.__container.show()
-
         self.__container.connect("briar_startup_completed",
                                  self.__on_startup_completed)
         self.__grid.add(self.__container)
@@ -55,5 +55,17 @@ class Window(Gtk.ApplicationWindow):
     def __setup_main_container(self):
         self.__container = MainContainer()
         self.__container.show()
+        self.__container.connect("briar_open_private_chat",
+                                 self.__open_private_chat)
+        self.__grid.add(self.__container)
+
+    def __open_private_chat(self, inst, obj):
+        self.__grid.destroy()
+        self.__setup_grid()
+        self.__setup_private_chat("1")
+
+    def __setup_private_chat(self, contact_id):
+        self.__container = ChatContainer(contact_id)
+        self.__container.show()
         self.__grid.add(self.__container)