diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/OutputPrivateMessage.kt b/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/OutputPrivateMessage.kt
index e73b30b1874239a1e2e8a79c76c70963abcdb746..3401afb831e9486315193185511fcc8d1ea7ee3f 100644
--- a/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/OutputPrivateMessage.kt
+++ b/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/OutputPrivateMessage.kt
@@ -5,21 +5,18 @@ import org.briarproject.briar.api.messaging.PrivateMessage
 import org.briarproject.briar.api.messaging.PrivateMessageHeader
 import org.briarproject.briar.headless.json.JsonDict
 
-internal fun PrivateMessageHeader.output(contactId: ContactId, body: String?): JsonDict {
-    val dict = JsonDict(
-        "type" to "org.briarproject.briar.api.messaging.PrivateMessageHeader",
-        "contactId" to contactId.int,
-        "timestamp" to timestamp,
-        "read" to isRead,
-        "seen" to isSeen,
-        "sent" to isSent,
-        "local" to isLocal,
-        "id" to id.bytes,
-        "groupId" to groupId.bytes
-    )
-    if (body != null) dict["body"] = body
-    return dict
-}
+internal fun PrivateMessageHeader.output(contactId: ContactId, body: String?) = JsonDict(
+    "type" to "org.briarproject.briar.api.messaging.PrivateMessageHeader",
+    "contactId" to contactId.int,
+    "timestamp" to timestamp,
+    "read" to isRead,
+    "seen" to isSeen,
+    "sent" to isSent,
+    "local" to isLocal,
+    "id" to id.bytes,
+    "groupId" to groupId.bytes,
+    "body" to body
+)
 
 internal fun PrivateMessage.output(contactId: ContactId, body: String) = JsonDict(
     "type" to "org.briarproject.briar.api.messaging.PrivateMessageHeader",
@@ -32,4 +29,4 @@ internal fun PrivateMessage.output(contactId: ContactId, body: String) = JsonDic
     "id" to message.id.bytes,
     "groupId" to message.groupId.bytes,
     "body" to body
-)
\ No newline at end of file
+)
diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/OutputPrivateRequest.kt b/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/OutputPrivateRequest.kt
index 3ecd902a61b8e3a56d2fcf9c49f513f47c609078..92693a2ca6131f33d413298e5a7d93504bb7d35d 100644
--- a/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/OutputPrivateRequest.kt
+++ b/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/OutputPrivateRequest.kt
@@ -1,5 +1,3 @@
-@file:Suppress("unused")
-
 package org.briarproject.briar.headless.messaging
 
 import org.briarproject.bramble.api.contact.ContactId
@@ -53,4 +51,4 @@ internal fun GroupInvitationRequest.output(contactId: ContactId): JsonDict {
     val dict = (this as InvitationRequest<*>).output(contactId)
     dict["type"] = "org.briarproject.briar.api.privategroup.invitation.GroupInvitationRequest"
     return dict
-}
\ No newline at end of file
+}
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 98c57ade4077ef9ff81257c8aca5e82c71ed1f44..d50413a50e24a7b278115e3d2a64d0394862b262 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
@@ -1,5 +1,3 @@
-@file:Suppress("MemberVisibilityCanBePrivate", "unused")
-
 package org.briarproject.briar.headless.messaging
 
 import org.briarproject.bramble.api.contact.ContactId
@@ -54,4 +52,4 @@ internal fun GroupInvitationResponse.output(contactId: ContactId): JsonDict {
     val dict = (this as InvitationResponse).output(contactId)
     dict["type"] = "org.briarproject.briar.api.privategroup.invitation.GroupInvitationResponse"
     return dict
-}
\ No newline at end of file
+}
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 374a59bee1c32444244c18ecbe44650eacb84044..5f05d9e8219b3b022679e122f1fa1f340cf96cf0 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
@@ -11,7 +11,6 @@ import org.briarproject.bramble.test.ImmediateExecutor
 import org.briarproject.bramble.test.TestUtils.getRandomId
 import org.briarproject.bramble.util.StringUtils.getRandomString
 import org.briarproject.briar.api.client.SessionId
-import org.briarproject.briar.api.introduction.IntroductionConstants.MAX_REQUEST_MESSAGE_LENGTH
 import org.briarproject.briar.api.introduction.IntroductionRequest
 import org.briarproject.briar.api.messaging.*
 import org.briarproject.briar.api.messaging.MessagingConstants.MAX_PRIVATE_MESSAGE_BODY_LENGTH
@@ -44,6 +43,7 @@ internal class MessagingControllerImplTest : ControllerTest() {
 
     private val header =
         PrivateMessageHeader(message.id, group.id, timestamp, true, true, true, true)
+    private val sessionId = SessionId(getRandomId())
 
     @Test
     fun list() {
@@ -57,10 +57,8 @@ internal class MessagingControllerImplTest : ControllerTest() {
 
     @Test
     fun listIntroductionRequest() {
-        val sessionId = SessionId(getRandomId())
-        val text = getRandomString(MAX_REQUEST_MESSAGE_LENGTH)
         val request = IntroductionRequest(
-            message.id, group.id, timestamp, true, true, false, true, sessionId, author, text,
+            message.id, group.id, timestamp, true, true, false, true, sessionId, author, body,
             false, false
         )
 
@@ -113,12 +111,13 @@ internal class MessagingControllerImplTest : ControllerTest() {
         controller.write(ctx)
 
         val output = slot.captured
-        assertEquals(contact.id.int, output.get("contactId"))
-        assertEquals(body, output.get("body"))
-        assertEquals(message.id.bytes, output.get("id"))
+        assertEquals(privateMessage.output(contact.id, body), output)
+        assertEquals(contact.id.int, output["contactId"])
+        assertEquals(body, output["body"])
+        assertEquals(message.id.bytes, output["id"])
         assertEquals(
             "org.briarproject.briar.api.messaging.PrivateMessageHeader",
-            output.get("type")
+            output["type"]
         )
     }
 
@@ -185,6 +184,33 @@ internal class MessagingControllerImplTest : ControllerTest() {
         assertJsonEquals(json, header.output(contact.id, body))
     }
 
+    @Test
+    fun testIntroductionRequestWithEmptyBody() {
+        val request = IntroductionRequest(
+            message.id, group.id, timestamp, true, true, false, true, sessionId, author, null,
+            false, false
+        )
+        val json = """
+            {
+                "body": null,
+                "type": "org.briarproject.briar.api.introduction.IntroductionRequest",
+                "timestamp": $timestamp,
+                "groupId": ${toJson(request.groupId.bytes)},
+                "contactId": ${contact.id.int},
+                "local": ${request.isLocal},
+                "seen": ${request.isSeen},
+                "read": ${request.isRead},
+                "sent": ${request.isSent},
+                "id": ${toJson(request.id.bytes)},
+                "sessionId": ${toJson(request.sessionId.bytes)},
+                "name": ${request.name},
+                "answered": ${request.wasAnswered()},
+                "alreadyContact": ${request.isContact}
+            }
+        """
+        assertJsonEquals(json, request.output(contact.id))
+    }
+
     private fun expectGetContact() {
         every { ctx.pathParam("contactId") } returns contact.id.int.toString()
         every { contactManager.getContact(contact.id) } returns contact