diff --git a/briar-android/src/org/briarproject/android/contact/ContactListActivity.java b/briar-android/src/org/briarproject/android/contact/ContactListActivity.java
index 80e8c28e9322d53c29877532159f1011e7625928..fff550fc46bdb88af5a84902795bfb7be2de9401 100644
--- a/briar-android/src/org/briarproject/android/contact/ContactListActivity.java
+++ b/briar-android/src/org/briarproject/android/contact/ContactListActivity.java
@@ -38,9 +38,9 @@ import org.briarproject.api.event.EventListener;
 import org.briarproject.api.event.MessageAddedEvent;
 import org.briarproject.api.identity.AuthorId;
 import org.briarproject.api.messaging.MessagingManager;
+import org.briarproject.api.messaging.PrivateMessageHeader;
 import org.briarproject.api.plugins.ConnectionRegistry;
 import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageHeader;
 
 import java.util.Collection;
 import java.util.logging.Logger;
@@ -141,11 +141,11 @@ EventListener {
 					for (Contact c : contactManager.getContacts()) {
 						try {
 							ContactId id = c.getId();
-							GroupId inbox =
+							GroupId conversation =
 									messagingManager.getConversationId(id);
-							Collection<MessageHeader> headers =
+							Collection<PrivateMessageHeader> headers =
 									messagingManager.getMessageHeaders(id);
-							displayContact(c, inbox, headers);
+							displayContact(c, conversation, headers);
 						} catch (NoSuchContactException e) {
 							// Continue
 						}
@@ -174,8 +174,8 @@ EventListener {
 		});
 	}
 
-	private void displayContact(final Contact c,
-			final GroupId inbox, final Collection<MessageHeader> headers) {
+	private void displayContact(final Contact c, final GroupId conversation,
+			final Collection<PrivateMessageHeader> headers) {
 		runOnUiThread(new Runnable() {
 			public void run() {
 				list.setVisibility(VISIBLE);
@@ -185,7 +185,8 @@ EventListener {
 				ContactListItem item = findItem(c.getId());
 				if (item != null) adapter.remove(item);
 				// Add a new item
-				adapter.add(new ContactListItem(c, connected, inbox, headers));
+				adapter.add(new ContactListItem(c, connected, conversation,
+						headers));
 				adapter.sort(ContactListItemComparator.INSTANCE);
 				adapter.notifyDataSetChanged();
 			}
@@ -226,12 +227,12 @@ EventListener {
 		ContactListItem item = adapter.getItem(position);
 		ContactId contactId = item.getContact().getId();
 		String contactName = item.getContact().getAuthor().getName();
-		GroupId inbox = item.getInboxGroupId();
+		GroupId groupId = item.getConversationId();
 		AuthorId localAuthorId = item.getContact().getLocalAuthorId();
 		Intent i = new Intent(this, ConversationActivity.class);
 		i.putExtra("briar.CONTACT_ID", contactId.getInt());
 		i.putExtra("briar.CONTACT_NAME", contactName);
-		i.putExtra("briar.GROUP_ID", inbox.getBytes());
+		i.putExtra("briar.GROUP_ID", groupId.getBytes());
 		i.putExtra("briar.LOCAL_AUTHOR_ID", localAuthorId.getBytes());
 		startActivity(i);
 	}
@@ -293,7 +294,7 @@ EventListener {
 			public void run() {
 				try {
 					long now = System.currentTimeMillis();
-					Collection<MessageHeader> headers =
+					Collection<PrivateMessageHeader> headers =
 							messagingManager.getMessageHeaders(c);
 					long duration = System.currentTimeMillis() - now;
 					if (LOG.isLoggable(INFO))
@@ -310,7 +311,7 @@ EventListener {
 	}
 
 	private void updateItem(final ContactId c,
-			final Collection<MessageHeader> headers) {
+			final Collection<PrivateMessageHeader> headers) {
 		runOnUiThread(new Runnable() {
 			public void run() {
 				ContactListItem item = findItem(c);
diff --git a/briar-android/src/org/briarproject/android/contact/ContactListItem.java b/briar-android/src/org/briarproject/android/contact/ContactListItem.java
index 4772f4b9af8d79af636e91ff0b5aaaeb3df3391b..2553c659c02e9c871115bf273a3a2eca3c97168d 100644
--- a/briar-android/src/org/briarproject/android/contact/ContactListItem.java
+++ b/briar-android/src/org/briarproject/android/contact/ContactListItem.java
@@ -1,8 +1,8 @@
 package org.briarproject.android.contact;
 
 import org.briarproject.api.contact.Contact;
+import org.briarproject.api.messaging.PrivateMessageHeader;
 import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageHeader;
 
 import java.util.Collection;
 
@@ -10,25 +10,25 @@ import java.util.Collection;
 class ContactListItem {
 
 	private final Contact contact;
-	private final GroupId inbox;
+	private final GroupId conversation;
 	private boolean connected, empty;
 	private long timestamp;
 	private int unread;
 
-	ContactListItem(Contact contact, boolean connected, GroupId inbox,
-			Collection<MessageHeader> headers) {
+	ContactListItem(Contact contact, boolean connected, GroupId conversation,
+			Collection<PrivateMessageHeader> headers) {
 		this.contact = contact;
-		this.inbox = inbox;
+		this.conversation = conversation;
 		this.connected = connected;
 		setHeaders(headers);
 	}
 
-	void setHeaders(Collection<MessageHeader> headers) {
+	void setHeaders(Collection<PrivateMessageHeader> headers) {
 		empty = headers.isEmpty();
 		timestamp = 0;
 		unread = 0;
 		if (!empty) {
-			for (MessageHeader h : headers) {
+			for (PrivateMessageHeader h : headers) {
 				if (h.getTimestamp() > timestamp) timestamp = h.getTimestamp();
 				if (!h.isRead()) unread++;
 			}
@@ -39,8 +39,8 @@ class ContactListItem {
 		return contact;
 	}
 
-	GroupId getInboxGroupId() {
-		return inbox;
+	GroupId getConversationId() {
+		return conversation;
 	}
 
 	boolean isConnected() {
diff --git a/briar-android/src/org/briarproject/android/contact/ConversationActivity.java b/briar-android/src/org/briarproject/android/contact/ConversationActivity.java
index 804e2ce356331d35b1005a7e8184f0f6f21cfe40..ff90470feaaff73345443e50375886a640272853 100644
--- a/briar-android/src/org/briarproject/android/contact/ConversationActivity.java
+++ b/briar-android/src/org/briarproject/android/contact/ConversationActivity.java
@@ -41,11 +41,11 @@ import org.briarproject.api.identity.AuthorId;
 import org.briarproject.api.messaging.MessagingManager;
 import org.briarproject.api.messaging.PrivateConversation;
 import org.briarproject.api.messaging.PrivateMessageFactory;
+import org.briarproject.api.messaging.PrivateMessageHeader;
+import org.briarproject.api.messaging.PrivateMessageHeader.Status;
 import org.briarproject.api.plugins.ConnectionRegistry;
 import org.briarproject.api.sync.GroupId;
 import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageHeader;
-import org.briarproject.api.sync.MessageHeader.State;
 import org.briarproject.api.sync.MessageId;
 import org.briarproject.util.StringUtils;
 
@@ -70,6 +70,8 @@ import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
 import static org.briarproject.android.contact.ReadPrivateMessageActivity.RESULT_PREV_NEXT;
 import static org.briarproject.android.util.CommonLayoutParams.MATCH_WRAP_1;
+import static org.briarproject.api.messaging.PrivateMessageHeader.Status.DELIVERED;
+import static org.briarproject.api.messaging.PrivateMessageHeader.Status.SENT;
 
 public class ConversationActivity extends BriarActivity
 implements EventListener, OnClickListener, OnItemClickListener {
@@ -209,7 +211,7 @@ implements EventListener, OnClickListener, OnItemClickListener {
 			public void run() {
 				try {
 					long now = System.currentTimeMillis();
-					Collection<MessageHeader> headers =
+					Collection<PrivateMessageHeader> headers =
 							messagingManager.getMessageHeaders(contactId);
 					long duration = System.currentTimeMillis() - now;
 					if (LOG.isLoggable(INFO))
@@ -225,7 +227,8 @@ implements EventListener, OnClickListener, OnItemClickListener {
 		});
 	}
 
-	private void displayHeaders(final Collection<MessageHeader> headers) {
+	private void displayHeaders(
+			final Collection<PrivateMessageHeader> headers) {
 		runOnUiThread(new Runnable() {
 			public void run() {
 				loading.setVisibility(GONE);
@@ -235,7 +238,7 @@ implements EventListener, OnClickListener, OnItemClickListener {
 				sendButton.setEnabled(true);
 				adapter.clear();
 				if (!headers.isEmpty()) {
-					for (MessageHeader h : headers) {
+					for (PrivateMessageHeader h : headers) {
 						ConversationItem item = new ConversationItem(h);
 						byte[] body = bodyCache.get(h.getId());
 						if (body == null) loadMessageBody(h);
@@ -251,7 +254,7 @@ implements EventListener, OnClickListener, OnItemClickListener {
 		});
 	}
 
-	private void loadMessageBody(final MessageHeader h) {
+	private void loadMessageBody(final PrivateMessageHeader h) {
 		runOnDbThread(new Runnable() {
 			public void run() {
 				try {
@@ -312,7 +315,7 @@ implements EventListener, OnClickListener, OnItemClickListener {
 		List<MessageId> unread = new ArrayList<MessageId>();
 		int count = adapter.getCount();
 		for (int i = 0; i < count; i++) {
-			MessageHeader h = adapter.getItem(i).getHeader();
+			PrivateMessageHeader h = adapter.getItem(i).getHeader();
 			if (!h.isRead()) unread.add(h.getId());
 		}
 		if (unread.isEmpty()) return;
@@ -356,13 +359,13 @@ implements EventListener, OnClickListener, OnItemClickListener {
 			MessagesSentEvent m = (MessagesSentEvent) e;
 			if (m.getContactId().equals(contactId)) {
 				LOG.info("Messages sent");
-				markMessages(m.getMessageIds(), State.SENT);
+				markMessages(m.getMessageIds(), SENT);
 			}
 		} else if (e instanceof MessagesAckedEvent) {
 			MessagesAckedEvent m = (MessagesAckedEvent) e;
 			if (m.getContactId().equals(contactId)) {
 				LOG.info("Messages acked");
-				markMessages(m.getMessageIds(), State.DELIVERED);
+				markMessages(m.getMessageIds(), DELIVERED);
 			}
 		} else if (e instanceof ContactConnectedEvent) {
 			ContactConnectedEvent c = (ContactConnectedEvent) e;
@@ -381,7 +384,8 @@ implements EventListener, OnClickListener, OnItemClickListener {
 		}
 	}
 
-	private void markMessages(final Collection<MessageId> messageIds, final State state) {
+	private void markMessages(final Collection<MessageId> messageIds,
+			final Status status) {
 		runOnUiThread(new Runnable() {
 			public void run() {
 				Set<MessageId> messages = new HashSet<MessageId>(messageIds);
@@ -390,7 +394,7 @@ implements EventListener, OnClickListener, OnItemClickListener {
 				for (int i = 0; i < count; i++) {
 					ConversationItem item = adapter.getItem(i);
 					if (messages.contains(item.getHeader().getId())) {
-						item.setStatus(state);
+						item.setStatus(status);
 						changed = true;
 					}
 				}
@@ -460,7 +464,7 @@ implements EventListener, OnClickListener, OnItemClickListener {
 
 	private void displayMessage(int position) {
 		ConversationItem item = adapter.getItem(position);
-		MessageHeader header = item.getHeader();
+		PrivateMessageHeader header = item.getHeader();
 		Intent i = new Intent(this, ReadPrivateMessageActivity.class);
 		i.putExtra("briar.CONTACT_ID", contactId.getInt());
 		i.putExtra("briar.CONTACT_NAME", contactName);
diff --git a/briar-android/src/org/briarproject/android/contact/ConversationAdapter.java b/briar-android/src/org/briarproject/android/contact/ConversationAdapter.java
index 240bdea4dd32bc0b08eb76c847ed9f3b95e25588..a95b00e47574f78f119492ca232e871efdfcd001 100644
--- a/briar-android/src/org/briarproject/android/contact/ConversationAdapter.java
+++ b/briar-android/src/org/briarproject/android/contact/ConversationAdapter.java
@@ -14,8 +14,7 @@ import android.widget.TextView;
 import org.briarproject.R;
 import org.briarproject.android.util.ElasticHorizontalSpace;
 import org.briarproject.android.util.LayoutUtils;
-import org.briarproject.api.sync.MessageHeader;
-import org.briarproject.api.sync.MessageHeader.State;
+import org.briarproject.api.messaging.PrivateMessageHeader;
 import org.briarproject.util.StringUtils;
 
 import java.util.ArrayList;
@@ -25,6 +24,8 @@ import static android.view.Gravity.LEFT;
 import static android.widget.LinearLayout.HORIZONTAL;
 import static android.widget.LinearLayout.VERTICAL;
 import static org.briarproject.android.util.CommonLayoutParams.MATCH_WRAP;
+import static org.briarproject.api.messaging.PrivateMessageHeader.Status.DELIVERED;
+import static org.briarproject.api.messaging.PrivateMessageHeader.Status.SENT;
 
 class ConversationAdapter extends ArrayAdapter<ConversationItem> {
 
@@ -39,7 +40,7 @@ class ConversationAdapter extends ArrayAdapter<ConversationItem> {
 	@Override
 	public View getView(int position, View convertView, ViewGroup parent) {
 		ConversationItem item = getItem(position);
-		MessageHeader header = item.getHeader();
+		PrivateMessageHeader header = item.getHeader();
 		Context ctx = getContext();
 		Resources res = ctx.getResources();
 
@@ -81,9 +82,9 @@ class ConversationAdapter extends ArrayAdapter<ConversationItem> {
 
 			ImageView status = new ImageView(ctx);
 			status.setPadding(0, 0, pad, 0);
-			if (item.getStatus() == State.DELIVERED) {
+			if (item.getStatus() == DELIVERED) {
 				status.setImageResource(R.drawable.message_delivered);
-			} else if (item.getStatus() == State.SENT) {
+			} else if (item.getStatus() == SENT) {
 				status.setImageResource(R.drawable.message_sent);
 			} else {
 				status.setImageResource(R.drawable.message_stored);
diff --git a/briar-android/src/org/briarproject/android/contact/ConversationItem.java b/briar-android/src/org/briarproject/android/contact/ConversationItem.java
index 292bd4a713289d448e61582ef696bff8e10698b6..7ee6c3bd7d2bd61d00291aac18472506a77e6fd6 100644
--- a/briar-android/src/org/briarproject/android/contact/ConversationItem.java
+++ b/briar-android/src/org/briarproject/android/contact/ConversationItem.java
@@ -1,22 +1,22 @@
 package org.briarproject.android.contact;
 
-import org.briarproject.api.sync.MessageHeader;
-import org.briarproject.api.sync.MessageHeader.State;
+import org.briarproject.api.messaging.PrivateMessageHeader;
+import org.briarproject.api.messaging.PrivateMessageHeader.Status;
 
 // This class is not thread-safe
 class ConversationItem {
 
-	private final MessageHeader header;
+	private final PrivateMessageHeader header;
 	private byte[] body;
-	private State status;
+	private Status status;
 
-	ConversationItem(MessageHeader header) {
+	ConversationItem(PrivateMessageHeader header) {
 		this.header = header;
 		body = null;
 		status = header.getStatus();
 	}
 
-	MessageHeader getHeader() {
+	PrivateMessageHeader getHeader() {
 		return header;
 	}
 
@@ -28,11 +28,11 @@ class ConversationItem {
 		this.body = body;
 	}
 
-	State getStatus() {
+	Status getStatus() {
 		return status;
 	}
 
-	void setStatus(State state) {
-		this.status = state;
+	void setStatus(Status status) {
+		this.status = status;
 	}
 }
diff --git a/briar-api/src/org/briarproject/api/messaging/MessagingManager.java b/briar-api/src/org/briarproject/api/messaging/MessagingManager.java
index afdcc1320064f3e980223864ed301f5d523a9c46..960bdd639341cf5b09f7fc9ee695fcf5c218ae93 100644
--- a/briar-api/src/org/briarproject/api/messaging/MessagingManager.java
+++ b/briar-api/src/org/briarproject/api/messaging/MessagingManager.java
@@ -4,7 +4,6 @@ import org.briarproject.api.contact.ContactId;
 import org.briarproject.api.db.DbException;
 import org.briarproject.api.sync.GroupId;
 import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageHeader;
 import org.briarproject.api.sync.MessageId;
 
 import java.util.Collection;
@@ -27,7 +26,7 @@ public interface MessagingManager {
 	 * Returns the headers of all messages in the private conversation with the
 	 * given contact, or null if no private conversation ID has been set.
 	 */
-	Collection<MessageHeader> getMessageHeaders(ContactId c)
+	Collection<PrivateMessageHeader> getMessageHeaders(ContactId c)
 			throws DbException;
 
 	/** Returns the body of the private message with the given ID. */
diff --git a/briar-api/src/org/briarproject/api/messaging/PrivateMessageHeader.java b/briar-api/src/org/briarproject/api/messaging/PrivateMessageHeader.java
new file mode 100644
index 0000000000000000000000000000000000000000..1f81e21d13ef7cc40966d29293ef05614a364cd5
--- /dev/null
+++ b/briar-api/src/org/briarproject/api/messaging/PrivateMessageHeader.java
@@ -0,0 +1,23 @@
+package org.briarproject.api.messaging;
+
+import org.briarproject.api.identity.Author;
+import org.briarproject.api.sync.MessageId;
+
+public interface PrivateMessageHeader {
+
+	enum Status { STORED, SENT, DELIVERED }
+
+	MessageId getId();
+
+	Author getAuthor();
+
+	String getContentType();
+
+	long getTimestamp();
+
+	boolean isLocal();
+
+	boolean isRead();
+
+	Status getStatus();
+}
diff --git a/briar-core/src/org/briarproject/messaging/MessagingManagerImpl.java b/briar-core/src/org/briarproject/messaging/MessagingManagerImpl.java
index e0c1c793b0359843c3f2d592d2fab20c8c1acafc..eca57c25dc514d3729866ebb10970aebbf374b46 100644
--- a/briar-core/src/org/briarproject/messaging/MessagingManagerImpl.java
+++ b/briar-core/src/org/briarproject/messaging/MessagingManagerImpl.java
@@ -7,12 +7,16 @@ import org.briarproject.api.db.DatabaseComponent;
 import org.briarproject.api.db.DbException;
 import org.briarproject.api.messaging.MessagingManager;
 import org.briarproject.api.messaging.PrivateConversation;
+import org.briarproject.api.messaging.PrivateMessageHeader;
 import org.briarproject.api.sync.GroupId;
 import org.briarproject.api.sync.Message;
 import org.briarproject.api.sync.MessageHeader;
 import org.briarproject.api.sync.MessageId;
 
+import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
 
 // Temporary facade during sync protocol refactoring
 class MessagingManagerImpl implements MessagingManager {
@@ -40,9 +44,14 @@ class MessagingManagerImpl implements MessagingManager {
 	}
 
 	@Override
-	public Collection<MessageHeader> getMessageHeaders(ContactId c)
+	public Collection<PrivateMessageHeader> getMessageHeaders(ContactId c)
 			throws DbException {
-		return db.getInboxMessageHeaders(c);
+		Collection<MessageHeader> headers = db.getInboxMessageHeaders(c);
+		List<PrivateMessageHeader> privateHeaders =
+				new ArrayList<PrivateMessageHeader>(headers.size());
+		for (MessageHeader m : headers)
+			privateHeaders.add(new PrivateMessageHeaderImpl(m));
+		return Collections.unmodifiableList(privateHeaders);
 	}
 
 	@Override
diff --git a/briar-core/src/org/briarproject/messaging/PrivateMessageHeaderImpl.java b/briar-core/src/org/briarproject/messaging/PrivateMessageHeaderImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..377447ac81393fee8c112d2563565ec796277832
--- /dev/null
+++ b/briar-core/src/org/briarproject/messaging/PrivateMessageHeaderImpl.java
@@ -0,0 +1,60 @@
+package org.briarproject.messaging;
+
+import org.briarproject.api.identity.Author;
+import org.briarproject.api.messaging.PrivateMessageHeader;
+import org.briarproject.api.sync.MessageHeader;
+import org.briarproject.api.sync.MessageId;
+
+// Temporary facade during sync protocol refactoring
+public class PrivateMessageHeaderImpl implements PrivateMessageHeader {
+
+	private final MessageHeader messageHeader;
+
+	PrivateMessageHeaderImpl(MessageHeader messageHeader) {
+		this.messageHeader = messageHeader;
+	}
+
+	@Override
+	public MessageId getId() {
+		return messageHeader.getId();
+	}
+
+	@Override
+	public Author getAuthor() {
+		return messageHeader.getAuthor();
+	}
+
+	@Override
+	public String getContentType() {
+		return messageHeader.getContentType();
+	}
+
+	@Override
+	public long getTimestamp() {
+		return messageHeader.getTimestamp();
+	}
+
+	@Override
+	public boolean isLocal() {
+		return messageHeader.isLocal();
+	}
+
+	@Override
+	public boolean isRead() {
+		return messageHeader.isRead();
+	}
+
+	@Override
+	public Status getStatus() {
+		switch (messageHeader.getStatus()) {
+			case STORED:
+				return Status.STORED;
+			case SENT:
+				return Status.SENT;
+			case DELIVERED:
+				return Status.DELIVERED;
+			default:
+				throw new IllegalStateException();
+		}
+	}
+}