diff --git a/briar-headless/README.md b/briar-headless/README.md
index ca704a1a7bd7bd76a96fb0146b6eb83443043acf..5b4b9feee38253e75d6408f7cb62ebf4eec108a7 100644
--- a/briar-headless/README.md
+++ b/briar-headless/README.md
@@ -1,17 +1,17 @@
 # Briar REST API
 
-This is a headless Briar client that exposes a REST API
+This is a headless Briar peer that exposes a REST API
 with an integrated HTTP server instead of a traditional user interface.
-You can use this API to script the client behavior
+You can use this API to script the peer behavior
 or to develop your own user interface for it.
 
 ## How to use
 
-The REST API client comes as a `jar` file
+The REST API peer comes as a `jar` file
 and needs a Java Runtime Environment (JRE) that supports at least Java 8.
 It currently works only on GNU/Linux operating systems.
 
-You can start the client (and its API server) like this:
+You can start the peer (and its API server) like this:
 
     $ java -jar briar-headless/build/libs/briar-headless.jar
 
@@ -69,7 +69,7 @@ Returns a JSON array of contacts:
 *Not yet implemented*
 
 The only workaround is to add a contact to the Briar app running on a rooted Android phone
-and then move its database (and key files) to the headless client.
+and then move its database (and key files) to the headless peer.
 
 ### Listing all private messages
 
@@ -93,7 +93,7 @@ It returns a JSON array of private messages:
 }
 ```
 
-If `local` is `true`, the message was sent by the Briar client instead of its remote contact.
+If `local` is `true`, the message was sent by the Briar peer instead of its remote contact.
 
 Attention: There can messages of other `type`s where the message `body` is `null`.
 
@@ -136,7 +136,7 @@ The text of the blog post should be included in the form parameter `text`.
 
 ## Websocket API
 
-The Briar client uses a websocket to notify a connected API client about new events.
+The Briar peer uses a websocket to notify a connected API client about new events.
 
 `WS /v1/ws`
 
@@ -157,7 +157,7 @@ Your websocket client will most likely add these headers automatically.
 
 ### Receiving new private messages
 
-When the Briar client receives a new private message,
+When the Briar peer receives a new private message,
 it will send a JSON object to connected websocket clients:
 
 ```json
diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/BriarService.kt b/briar-headless/src/main/java/org/briarproject/briar/headless/BriarService.kt
index 40e76af335aaca211f792454cd5d436569a417a4..5f13b739e97c2a33bbbaa16c8dc6e3fc227e2ac6 100644
--- a/briar-headless/src/main/java/org/briarproject/briar/headless/BriarService.kt
+++ b/briar-headless/src/main/java/org/briarproject/briar/headless/BriarService.kt
@@ -16,7 +16,8 @@ import javax.inject.Singleton
 @Immutable
 @Singleton
 internal class BriarService
-@Inject constructor(
+@Inject
+constructor(
     private val accountManager: AccountManager,
     private val lifecycleManager: LifecycleManager,
     private val passwordStrengthEstimator: PasswordStrengthEstimator
diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/Router.kt b/briar-headless/src/main/java/org/briarproject/briar/headless/Router.kt
index 2914be0b7a9e366dd4055eb05a540c2fc6bac3a5..c1d4563cf395416962949199160fc2da56f43a2a 100644
--- a/briar-headless/src/main/java/org/briarproject/briar/headless/Router.kt
+++ b/briar-headless/src/main/java/org/briarproject/briar/headless/Router.kt
@@ -5,7 +5,7 @@ import io.javalin.JavalinEvent.SERVER_START_FAILED
 import io.javalin.JavalinEvent.SERVER_STOPPED
 import io.javalin.apibuilder.ApiBuilder.*
 import io.javalin.core.util.ContextUtil
-import io.javalin.core.util.Header
+import io.javalin.core.util.Header.AUTHORIZATION
 import org.briarproject.briar.headless.blogs.BlogController
 import org.briarproject.briar.headless.contact.ContactController
 import org.briarproject.briar.headless.event.WebSocketController
@@ -21,7 +21,8 @@ import kotlin.system.exitProcess
 
 @Immutable
 @Singleton
-internal class Router @Inject
+internal class Router
+@Inject
 constructor(
     private val briarService: BriarService,
     private val webSocketController: WebSocketController,
@@ -36,7 +37,7 @@ constructor(
 
     fun start(authToken: String, port: Int, debug: Boolean) {
         briarService.start()
-        getRuntime().addShutdownHook(Thread(Runnable { stop() }))
+        getRuntime().addShutdownHook(Thread(this::stop))
 
         val app = Javalin.create()
             .port(port)
@@ -48,7 +49,7 @@ constructor(
         app.start()
 
         app.accessManager { handler, ctx, _ ->
-            if (ctx.header("Authorization") == "Bearer $authToken") {
+            if (ctx.header(AUTHORIZATION) == "Bearer $authToken") {
                 handler.handle(ctx)
             } else {
                 ctx.status(401).result("Unauthorized")
@@ -77,7 +78,7 @@ constructor(
         }
         app.ws("/v1/ws") { ws ->
             ws.onConnect { session ->
-                val authHeader = session.header(Header.AUTHORIZATION)
+                val authHeader = session.header(AUTHORIZATION)
                 val token = ContextUtil.getBasicAuthCredentials(authHeader)?.username
                 if (authToken == token) {
                     logger.info("Adding websocket session with ${session.remoteAddress}")
diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/blogs/BlogControllerImpl.kt b/briar-headless/src/main/java/org/briarproject/briar/headless/blogs/BlogControllerImpl.kt
index 4125dfba1c8c30a530e7bd2decc6c8f590966d3f..d3f179e4855add55780693ed72a19b5608e26374 100644
--- a/briar-headless/src/main/java/org/briarproject/briar/headless/blogs/BlogControllerImpl.kt
+++ b/briar-headless/src/main/java/org/briarproject/briar/headless/blogs/BlogControllerImpl.kt
@@ -15,7 +15,8 @@ import javax.inject.Singleton
 @Immutable
 @Singleton
 internal class BlogControllerImpl
-@Inject constructor(
+@Inject
+constructor(
     private val blogManager: BlogManager,
     private val blogPostFactory: BlogPostFactory,
     private val identityManager: IdentityManager,
diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/contact/ContactControllerImpl.kt b/briar-headless/src/main/java/org/briarproject/briar/headless/contact/ContactControllerImpl.kt
index 7a53476a907becaef21a76fb8b32c58cd8f24f6e..bf94c70a562b3a8a75176ef8660006643fb75cb3 100644
--- a/briar-headless/src/main/java/org/briarproject/briar/headless/contact/ContactControllerImpl.kt
+++ b/briar-headless/src/main/java/org/briarproject/briar/headless/contact/ContactControllerImpl.kt
@@ -9,7 +9,8 @@ import javax.inject.Singleton
 @Immutable
 @Singleton
 internal class ContactControllerImpl
-@Inject constructor(private val contactManager: ContactManager) : ContactController {
+@Inject
+constructor(private val contactManager: ContactManager) : ContactController {
 
     override fun list(ctx: Context): Context {
         val contacts = contactManager.activeContacts.map { contact ->
diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/event/WebSocketController.kt b/briar-headless/src/main/java/org/briarproject/briar/headless/event/WebSocketController.kt
index ed723d55690bee939db20d6b90144e6793696f22..abbbc81e5b8fb3ee72c9a6fd738b4a93c5436e0d 100644
--- a/briar-headless/src/main/java/org/briarproject/briar/headless/event/WebSocketController.kt
+++ b/briar-headless/src/main/java/org/briarproject/briar/headless/event/WebSocketController.kt
@@ -2,6 +2,7 @@ package org.briarproject.briar.headless.event
 
 import io.javalin.websocket.WsSession
 import org.briarproject.bramble.api.lifecycle.IoExecutor
+import org.briarproject.briar.headless.json.JsonDict
 import javax.annotation.concurrent.ThreadSafe
 
 @ThreadSafe
@@ -12,6 +13,6 @@ interface WebSocketController {
     /**
      * Sends an event to all open sessions using the [IoExecutor].
      */
-    fun sendEvent(name: String, obj: Any)
+    fun sendEvent(name: String, obj: JsonDict)
 
 }
diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/event/WebSocketControllerImpl.kt b/briar-headless/src/main/java/org/briarproject/briar/headless/event/WebSocketControllerImpl.kt
index 6ea7bf6e5ee467d48c14ba14c764c3d1d455afe2..c36156ca1410f4ae6e508af45212d6d9ad64f1d9 100644
--- a/briar-headless/src/main/java/org/briarproject/briar/headless/event/WebSocketControllerImpl.kt
+++ b/briar-headless/src/main/java/org/briarproject/briar/headless/event/WebSocketControllerImpl.kt
@@ -4,11 +4,12 @@ import io.javalin.json.JavalinJson.toJson
 import io.javalin.websocket.WsSession
 import org.briarproject.bramble.api.lifecycle.IoExecutor
 import org.briarproject.bramble.util.LogUtils.logException
+import org.briarproject.briar.headless.json.JsonDict
 import org.eclipse.jetty.websocket.api.WebSocketException
 import java.io.IOException
 import java.util.concurrent.ConcurrentHashMap
 import java.util.concurrent.Executor
-import java.util.logging.Level
+import java.util.logging.Level.WARNING
 import java.util.logging.Logger.getLogger
 import javax.annotation.concurrent.Immutable
 import javax.inject.Inject
@@ -17,21 +18,24 @@ import javax.inject.Singleton
 @Immutable
 @Singleton
 internal class WebSocketControllerImpl
-@Inject constructor(@IoExecutor private val ioExecutor: Executor) : WebSocketController {
+@Inject
+constructor(@IoExecutor private val ioExecutor: Executor) : WebSocketController {
 
     private val logger = getLogger(WebSocketControllerImpl::javaClass.name)
 
     override val sessions: MutableSet<WsSession> = ConcurrentHashMap.newKeySet<WsSession>()
 
-    override fun sendEvent(name: String, obj: Any) = ioExecutor.execute {
+    override fun sendEvent(name: String, obj: JsonDict) {
+        val event = toJson(OutputEvent(name, obj))
         sessions.forEach { session ->
-            val event = OutputEvent(name, obj)
-            try {
-                session.send(toJson(event))
-            } catch (e: WebSocketException) {
-                logException(logger, Level.WARNING, e)
-            } catch (e: IOException) {
-                logException(logger, Level.WARNING, e)
+            ioExecutor.execute {
+                try {
+                    session.send(event)
+                } catch (e: WebSocketException) {
+                    logException(logger, WARNING, e)
+                } catch (e: IOException) {
+                    logException(logger, WARNING, e)
+                }
             }
         }
     }
diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/forums/ForumControllerImpl.kt b/briar-headless/src/main/java/org/briarproject/briar/headless/forums/ForumControllerImpl.kt
index 1e0d49d78ab5264838e65aa41eb02e276bc58a03..952f6e8eec12080d15d59d1a2b9fdf972f100ce2 100644
--- a/briar-headless/src/main/java/org/briarproject/briar/headless/forums/ForumControllerImpl.kt
+++ b/briar-headless/src/main/java/org/briarproject/briar/headless/forums/ForumControllerImpl.kt
@@ -12,7 +12,8 @@ import javax.inject.Singleton
 @Immutable
 @Singleton
 internal class ForumControllerImpl
-@Inject constructor(private val forumManager: ForumManager) : ForumController {
+@Inject
+constructor(private val forumManager: ForumManager) : ForumController {
 
     override fun list(ctx: Context): Context {
         return ctx.json(forumManager.forums.output())
diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/MessagingControllerImpl.kt b/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/MessagingControllerImpl.kt
index 0d9c546dfc08ea1782d3964225f811e08176b87a..34fbca73ede760e129072d8b7c196cfb5d54d33d 100644
--- a/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/MessagingControllerImpl.kt
+++ b/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/MessagingControllerImpl.kt
@@ -36,7 +36,8 @@ internal const val EVENT_PRIVATE_MESSAGE = "PrivateMessageReceivedEvent"
 @Immutable
 @Singleton
 internal class MessagingControllerImpl
-@Inject constructor(
+@Inject
+constructor(
     private val messagingManager: MessagingManager,
     private val conversationManager: ConversationManager,
     private val privateMessageFactory: PrivateMessageFactory,
diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/OutputPrivateResponse.kt b/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/OutputPrivateResponse.kt
index ee0f8189317de841f24e87df7b01d9f6eea24d7d..f0b3fbda32e4c3a84b65a3ed011b9194af14d95c 100644
--- a/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/OutputPrivateResponse.kt
+++ b/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/OutputPrivateResponse.kt
@@ -44,7 +44,7 @@ internal fun BlogInvitationResponse.output(contactId: ContactId): JsonDict {
 
 internal fun ForumInvitationResponse.output(contactId: ContactId): JsonDict {
     val dict = (this as InvitationResponse).output(contactId)
-    dict["type"] = "BlogInvitationResponse"
+    dict["type"] = "ForumInvitationResponse"
     return dict
 }
 
diff --git a/briar-headless/src/test/java/org/briarproject/briar/headless/messaging/MessagingControllerImplTest.kt b/briar-headless/src/test/java/org/briarproject/briar/headless/messaging/MessagingControllerImplTest.kt
index 7ead89482c9f1177554b3d925490ee18c52879ac..c567e547c0633e7776d7f84e834b2b5eea871a34 100644
--- a/briar-headless/src/test/java/org/briarproject/briar/headless/messaging/MessagingControllerImplTest.kt
+++ b/briar-headless/src/test/java/org/briarproject/briar/headless/messaging/MessagingControllerImplTest.kt
@@ -44,6 +44,7 @@ internal class MessagingControllerImplTest : ControllerTest() {
     private val header =
         PrivateMessageHeader(message.id, group.id, timestamp, true, true, true, true)
     private val sessionId = SessionId(getRandomId())
+    private val privateMessage = PrivateMessage(message)
 
     @Test
     fun list() {
@@ -91,7 +92,6 @@ internal class MessagingControllerImplTest : ControllerTest() {
 
     @Test
     fun write() {
-        val privateMessage = PrivateMessage(message)
         val slot = CapturingSlot<JsonDict>()
 
         expectGetContact()
@@ -110,12 +110,7 @@ internal class MessagingControllerImplTest : ControllerTest() {
 
         controller.write(ctx)
 
-        val output = slot.captured
-        assertEquals(privateMessage.output(contact.id, body), output)
-        assertEquals(contact.id.int, output["contactId"])
-        assertEquals(body, output["body"])
-        assertEquals(message.id.bytes, output["id"])
-        assertEquals("PrivateMessage", output["type"])
+        assertEquals(privateMessage.output(contact.id, body), slot.captured)
     }
 
     @Test
@@ -181,6 +176,25 @@ internal class MessagingControllerImplTest : ControllerTest() {
         assertJsonEquals(json, header.output(contact.id, body))
     }
 
+    @Test
+    fun testOutputPrivateMessage() {
+        val json = """
+            {
+                "body": "$body",
+                "type": "PrivateMessage",
+                "timestamp": ${message.timestamp},
+                "groupId": ${toJson(message.groupId.bytes)},
+                "contactId": ${contact.id.int},
+                "local": true,
+                "seen": true,
+                "read": true,
+                "sent": true,
+                "id": ${toJson(message.id.bytes)}
+            }
+        """
+        assertJsonEquals(json, privateMessage.output(contact.id, body))
+    }
+
     @Test
     fun testIntroductionRequestWithEmptyBody() {
         val request = IntroductionRequest(