diff --git a/briar-android/src/org/briarproject/android/BriarService.java b/briar-android/src/org/briarproject/android/BriarService.java
index d93e7bcd375c461d6354a7053bfa419a8470f3ab..a34e5a105fbb348d93be4d483231c86b9173aa78 100644
--- a/briar-android/src/org/briarproject/android/BriarService.java
+++ b/briar-android/src/org/briarproject/android/BriarService.java
@@ -170,7 +170,7 @@ public class BriarService extends RoboService implements EventListener {
 	public void eventOccurred(Event e) {
 		if (e instanceof MessageAddedEvent) {
 			MessageAddedEvent m = (MessageAddedEvent) e;
-			GroupId g = m.getGroup().getId();
+			GroupId g = m.getGroupId();
 			ContactId c = m.getContactId();
 			if (c != null) showMessageNotification(g, c);
 		}
diff --git a/briar-android/src/org/briarproject/android/contact/ConversationActivity.java b/briar-android/src/org/briarproject/android/contact/ConversationActivity.java
index fe60f8c423c7d89518f8a8c38c7b1caef2ae1823..662ada73878ce6573e471424a182a8ca1e31c011 100644
--- a/briar-android/src/org/briarproject/android/contact/ConversationActivity.java
+++ b/briar-android/src/org/briarproject/android/contact/ConversationActivity.java
@@ -347,7 +347,7 @@ implements EventListener, OnClickListener, OnItemClickListener {
 				finishOnUiThread();
 			}
 		} else if (e instanceof MessageAddedEvent) {
-			GroupId g = ((MessageAddedEvent) e).getGroup().getId();
+			GroupId g = ((MessageAddedEvent) e).getGroupId();
 			if (g.equals(groupId)) {
 				LOG.info("Message added, reloading");
 				loadHeaders();
diff --git a/briar-android/src/org/briarproject/android/forum/AvailableForumsActivity.java b/briar-android/src/org/briarproject/android/forum/AvailableForumsActivity.java
index 816ed7b90534a308f9687d8eb45c797ab52b4b12..a14704d30991db1c05e9ff6704e62a6aa35eda9f 100644
--- a/briar-android/src/org/briarproject/android/forum/AvailableForumsActivity.java
+++ b/briar-android/src/org/briarproject/android/forum/AvailableForumsActivity.java
@@ -20,8 +20,8 @@ import org.briarproject.api.event.EventListener;
 import org.briarproject.api.event.RemoteSubscriptionsUpdatedEvent;
 import org.briarproject.api.event.SubscriptionAddedEvent;
 import org.briarproject.api.event.SubscriptionRemovedEvent;
+import org.briarproject.api.forum.Forum;
 import org.briarproject.api.forum.ForumManager;
-import org.briarproject.api.sync.Group;
 import org.briarproject.api.sync.GroupId;
 
 import java.util.ArrayList;
@@ -43,7 +43,6 @@ implements EventListener, OnItemClickListener {
 
 	private AvailableForumsAdapter adapter = null;
 	private ListView list = null;
-	private ListLoadingProgressBar loading = null;
 
 	// Fields that are accessed from background threads must be volatile
 	@Inject private volatile ForumManager forumManager;
@@ -60,7 +59,7 @@ implements EventListener, OnItemClickListener {
 		list.setOnItemClickListener(this);
 
 		// Show a progress bar while the list is loading
-		loading = new ListLoadingProgressBar(this);
+		ListLoadingProgressBar loading = new ListLoadingProgressBar(this);
 		setContentView(loading);
 	}
 
@@ -78,12 +77,12 @@ implements EventListener, OnItemClickListener {
 					Collection<ForumContacts> available =
 							new ArrayList<ForumContacts>();
 					long now = System.currentTimeMillis();
-					for (Group g : forumManager.getAvailableGroups()) {
+					for (Forum f : forumManager.getAvailableForums()) {
 						try {
-							GroupId id = g.getId();
+							GroupId id = f.getId();
 							Collection<Contact> c =
 									forumManager.getSubscribers(id);
-							available.add(new ForumContacts(g, c));
+							available.add(new ForumContacts(f, c));
 						} catch (NoSuchSubscriptionException e) {
 							// Continue
 						}
@@ -142,18 +141,18 @@ implements EventListener, OnItemClickListener {
 		AvailableForumsItem item = adapter.getItem(position);
 		Collection<ContactId> visible = new ArrayList<ContactId>();
 		for (Contact c : item.getContacts()) visible.add(c.getId());
-		addSubscription(item.getGroup(), visible);
+		addSubscription(item.getForum(), visible);
 		String subscribed = getString(R.string.subscribed_toast);
 		Toast.makeText(this, subscribed, LENGTH_SHORT).show();
 	}
 
-	private void addSubscription(final Group g,
+	private void addSubscription(final Forum f,
 			final Collection<ContactId> visible) {
 		runOnDbThread(new Runnable() {
 			public void run() {
 				try {
-					forumManager.addGroup(g);
-					forumManager.setVisibility(g.getId(), visible);
+					forumManager.addForum(f);
+					forumManager.setVisibility(f.getId(), visible);
 				} catch (DbException e) {
 					if (LOG.isLoggable(WARNING))
 						LOG.log(WARNING, e.toString(), e);
diff --git a/briar-android/src/org/briarproject/android/forum/AvailableForumsAdapter.java b/briar-android/src/org/briarproject/android/forum/AvailableForumsAdapter.java
index 918cfe15de41cc4c7ad5e46368c5920ef34f18ec..e5969e3bea3b795970c4fc82daef77734ed2de17 100644
--- a/briar-android/src/org/briarproject/android/forum/AvailableForumsAdapter.java
+++ b/briar-android/src/org/briarproject/android/forum/AvailableForumsAdapter.java
@@ -41,7 +41,7 @@ class AvailableForumsAdapter extends ArrayAdapter<AvailableForumsItem> {
 		name.setSingleLine();
 		name.setEllipsize(END);
 		name.setPadding(pad, pad, pad, pad);
-		name.setText(item.getGroup().getName());
+		name.setText(item.getForum().getName());
 		layout.addView(name);
 
 		TextView status = new TextView(ctx);
diff --git a/briar-android/src/org/briarproject/android/forum/AvailableForumsItem.java b/briar-android/src/org/briarproject/android/forum/AvailableForumsItem.java
index f9b9c3a64dc835341105ad4f25affbd8123f7e60..7d8a91feb8b4fea845dde718d0594fae89b1d366 100644
--- a/briar-android/src/org/briarproject/android/forum/AvailableForumsItem.java
+++ b/briar-android/src/org/briarproject/android/forum/AvailableForumsItem.java
@@ -1,7 +1,7 @@
 package org.briarproject.android.forum;
 
 import org.briarproject.api.contact.Contact;
-import org.briarproject.api.sync.Group;
+import org.briarproject.api.forum.Forum;
 
 import java.util.Collection;
 
@@ -13,8 +13,8 @@ class AvailableForumsItem {
 		this.forumContacts = forumContacts;
 	}
 
-	Group getGroup() {
-		return forumContacts.getGroup();
+	Forum getForum() {
+		return forumContacts.getForum();
 	}
 
 	Collection<Contact> getContacts() {
diff --git a/briar-android/src/org/briarproject/android/forum/AvailableForumsItemComparator.java b/briar-android/src/org/briarproject/android/forum/AvailableForumsItemComparator.java
index 82a8b9a928a29ff575979b9a285dce695f1d7320..c9098edb00538c785a876f99238690c7165b33e0 100644
--- a/briar-android/src/org/briarproject/android/forum/AvailableForumsItemComparator.java
+++ b/briar-android/src/org/briarproject/android/forum/AvailableForumsItemComparator.java
@@ -9,8 +9,8 @@ class AvailableForumsItemComparator implements Comparator<AvailableForumsItem> {
 
 	public int compare(AvailableForumsItem a, AvailableForumsItem b) {
 		if (a == b) return 0;
-		String aName = a.getGroup().getName();
-		String bName = b.getGroup().getName();
+		String aName = a.getForum().getName();
+		String bName = b.getForum().getName();
 		return String.CASE_INSENSITIVE_ORDER.compare(aName, bName);
 	}
 }
diff --git a/briar-android/src/org/briarproject/android/forum/CreateForumActivity.java b/briar-android/src/org/briarproject/android/forum/CreateForumActivity.java
index 76dc444147a632a845903a091a04ca6f34c0404a..89c230e189ba0d74c7ea281e3dd4a065abb24dba 100644
--- a/briar-android/src/org/briarproject/android/forum/CreateForumActivity.java
+++ b/briar-android/src/org/briarproject/android/forum/CreateForumActivity.java
@@ -17,9 +17,9 @@ import org.briarproject.R;
 import org.briarproject.android.BriarActivity;
 import org.briarproject.android.util.LayoutUtils;
 import org.briarproject.api.db.DbException;
+import org.briarproject.api.forum.Forum;
+import org.briarproject.api.forum.ForumFactory;
 import org.briarproject.api.forum.ForumManager;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.GroupFactory;
 import org.briarproject.util.StringUtils;
 
 import java.util.logging.Logger;
@@ -52,7 +52,7 @@ implements OnEditorActionListener, OnClickListener {
 	private TextView feedback = null;
 
 	// Fields that are accessed from background threads must be volatile
-	@Inject private volatile GroupFactory groupFactory;
+	@Inject private volatile ForumFactory forumFactory;
 	@Inject private volatile ForumManager forumManager;
 
 	@Override
@@ -138,13 +138,13 @@ implements OnEditorActionListener, OnClickListener {
 		runOnDbThread(new Runnable() {
 			public void run() {
 				try {
-					Group g = groupFactory.createGroup(name);
+					Forum f = forumFactory.createForum(name);
 					long now = System.currentTimeMillis();
-					forumManager.addGroup(g);
+					forumManager.addForum(f);
 					long duration = System.currentTimeMillis() - now;
 					if (LOG.isLoggable(INFO))
 						LOG.info("Storing forum took " + duration + " ms");
-					displayForum(g);
+					displayForum(f);
 				} catch (DbException e) {
 					if (LOG.isLoggable(WARNING))
 						LOG.log(WARNING, e.toString(), e);
@@ -154,13 +154,13 @@ implements OnEditorActionListener, OnClickListener {
 		});
 	}
 
-	private void displayForum(final Group g) {
+	private void displayForum(final Forum f) {
 		runOnUiThread(new Runnable() {
 			public void run() {
 				Intent i = new Intent(CreateForumActivity.this,
 						ForumActivity.class);
-				i.putExtra("briar.GROUP_ID", g.getId().getBytes());
-				i.putExtra("briar.FORUM_NAME", g.getName());
+				i.putExtra("briar.GROUP_ID", f.getId().getBytes());
+				i.putExtra("briar.FORUM_NAME", f.getName());
 				startActivity(i);
 				Toast.makeText(CreateForumActivity.this,
 						R.string.forum_created_toast, LENGTH_LONG).show();
diff --git a/briar-android/src/org/briarproject/android/forum/ForumActivity.java b/briar-android/src/org/briarproject/android/forum/ForumActivity.java
index ee14bad2912b68bbaa3d48c016e99e04be9be476..99df221fc035f0f05955574e542fc0394529a374 100644
--- a/briar-android/src/org/briarproject/android/forum/ForumActivity.java
+++ b/briar-android/src/org/briarproject/android/forum/ForumActivity.java
@@ -26,9 +26,9 @@ import org.briarproject.api.event.EventBus;
 import org.briarproject.api.event.EventListener;
 import org.briarproject.api.event.MessageAddedEvent;
 import org.briarproject.api.event.SubscriptionRemovedEvent;
+import org.briarproject.api.forum.Forum;
 import org.briarproject.api.forum.ForumManager;
 import org.briarproject.api.identity.Author;
-import org.briarproject.api.sync.Group;
 import org.briarproject.api.sync.GroupId;
 import org.briarproject.api.sync.MessageHeader;
 import org.briarproject.api.sync.MessageId;
@@ -74,7 +74,7 @@ OnClickListener, OnItemClickListener {
 	@Inject private volatile ForumManager forumManager;
 	@Inject private volatile EventBus eventBus;
 	private volatile GroupId groupId = null;
-	private volatile Group group = null;
+	private volatile Forum forum = null;
 
 	@Override
 	public void onCreate(Bundle state) {
@@ -152,10 +152,10 @@ OnClickListener, OnItemClickListener {
 			public void run() {
 				try {
 					long now = System.currentTimeMillis();
-					group = forumManager.getGroup(groupId);
+					forum = forumManager.getForum(groupId);
 					long duration = System.currentTimeMillis() - now;
 					if (LOG.isLoggable(INFO))
-						LOG.info("Loading group " + duration + " ms");
+						LOG.info("Loading forum " + duration + " ms");
 					displayForumName();
 				} catch (NoSuchSubscriptionException e) {
 					finishOnUiThread();
@@ -170,7 +170,7 @@ OnClickListener, OnItemClickListener {
 	private void displayForumName() {
 		runOnUiThread(new Runnable() {
 			public void run() {
-				setTitle(group.getName());
+				setTitle(forum.getName());
 			}
 		});
 	}
@@ -313,7 +313,7 @@ OnClickListener, OnItemClickListener {
 
 	public void eventOccurred(Event e) {
 		if (e instanceof MessageAddedEvent) {
-			if (((MessageAddedEvent) e).getGroup().getId().equals(groupId)) {
+			if (((MessageAddedEvent) e).getGroupId().equals(groupId)) {
 				LOG.info("Message added, reloading");
 				loadHeaders();
 			}
@@ -330,13 +330,13 @@ OnClickListener, OnItemClickListener {
 		if (view == composeButton) {
 			Intent i = new Intent(this, WriteForumPostActivity.class);
 			i.putExtra("briar.GROUP_ID", groupId.getBytes());
-			i.putExtra("briar.FORUM_NAME", group.getName());
+			i.putExtra("briar.FORUM_NAME", forum.getName());
 			i.putExtra("briar.MIN_TIMESTAMP", getMinTimestampForNewMessage());
 			startActivity(i);
 		} else if (view == shareButton) {
 			Intent i = new Intent(this, ShareForumActivity.class);
 			i.putExtra("briar.GROUP_ID", groupId.getBytes());
-			i.putExtra("briar.FORUM_NAME", group.getName());
+			i.putExtra("briar.FORUM_NAME", forum.getName());
 			startActivity(i);
 		}
 	}
@@ -361,7 +361,7 @@ OnClickListener, OnItemClickListener {
 		MessageHeader item = adapter.getItem(position).getHeader();
 		Intent i = new Intent(this, ReadForumPostActivity.class);
 		i.putExtra("briar.GROUP_ID", groupId.getBytes());
-		i.putExtra("briar.FORUM_NAME", group.getName());
+		i.putExtra("briar.FORUM_NAME", forum.getName());
 		i.putExtra("briar.MESSAGE_ID", item.getId().getBytes());
 		Author author = item.getAuthor();
 		if (author != null) i.putExtra("briar.AUTHOR_NAME", author.getName());
diff --git a/briar-android/src/org/briarproject/android/forum/ForumContacts.java b/briar-android/src/org/briarproject/android/forum/ForumContacts.java
index aa3b0c75c47e26da64c400e336550dde322d26e3..ce24fc86053d44987cc5fb710f37a90c65b2ad27 100644
--- a/briar-android/src/org/briarproject/android/forum/ForumContacts.java
+++ b/briar-android/src/org/briarproject/android/forum/ForumContacts.java
@@ -1,22 +1,22 @@
 package org.briarproject.android.forum;
 
 import org.briarproject.api.contact.Contact;
-import org.briarproject.api.sync.Group;
+import org.briarproject.api.forum.Forum;
 
 import java.util.Collection;
 
 class ForumContacts {
 
-	private final Group group;
+	private final Forum forum;
 	private final Collection<Contact> contacts;
 
-	ForumContacts(Group group, Collection<Contact> contacts) {
-		this.group = group;
+	ForumContacts(Forum forum, Collection<Contact> contacts) {
+		this.forum = forum;
 		this.contacts = contacts;
 	}
 
-	Group getGroup() {
-		return group;
+	Forum getForum() {
+		return forum;
 	}
 
 	Collection<Contact> getContacts() {
diff --git a/briar-android/src/org/briarproject/android/forum/ForumListActivity.java b/briar-android/src/org/briarproject/android/forum/ForumListActivity.java
index c602aefc06b1ee5d2922b5066e3edd3f7af7ef6e..e57ddfee3f04f49cc5a49cdc5c5e0a585293ad30 100644
--- a/briar-android/src/org/briarproject/android/forum/ForumListActivity.java
+++ b/briar-android/src/org/briarproject/android/forum/ForumListActivity.java
@@ -32,6 +32,7 @@ import org.briarproject.api.event.MessageAddedEvent;
 import org.briarproject.api.event.RemoteSubscriptionsUpdatedEvent;
 import org.briarproject.api.event.SubscriptionAddedEvent;
 import org.briarproject.api.event.SubscriptionRemovedEvent;
+import org.briarproject.api.forum.Forum;
 import org.briarproject.api.forum.ForumManager;
 import org.briarproject.api.sync.Group;
 import org.briarproject.api.sync.GroupId;
@@ -153,16 +154,16 @@ OnCreateContextMenuListener {
 			public void run() {
 				try {
 					long now = System.currentTimeMillis();
-					for (Group g : forumManager.getGroups()) {
+					for (Forum f : forumManager.getForums()) {
 						try {
 							Collection<MessageHeader> headers =
-									forumManager.getMessageHeaders(g.getId());
-							displayHeaders(g, headers);
+									forumManager.getMessageHeaders(f.getId());
+							displayHeaders(f, headers);
 						} catch (NoSuchSubscriptionException e) {
 							// Continue
 						}
 					}
-					int available = forumManager.getAvailableGroups().size();
+					int available = forumManager.getAvailableForums().size();
 					long duration = System.currentTimeMillis() - now;
 					if (LOG.isLoggable(INFO))
 						LOG.info("Full load took " + duration + " ms");
@@ -189,11 +190,11 @@ OnCreateContextMenuListener {
 		});
 	}
 
-	private void displayHeaders(final Group g,
+	private void displayHeaders(final Forum f,
 			final Collection<MessageHeader> headers) {
 		runOnUiThread(new Runnable() {
 			public void run() {
-				GroupId id = g.getId();
+				GroupId id = f.getId();
 				groupIds.put(id, id);
 				list.setVisibility(VISIBLE);
 				loading.setVisibility(GONE);
@@ -201,7 +202,7 @@ OnCreateContextMenuListener {
 				ForumListItem item = findForum(id);
 				if (item != null) adapter.remove(item);
 				// Add a new item
-				adapter.add(new ForumListItem(g, headers));
+				adapter.add(new ForumListItem(f, headers));
 				adapter.sort(ForumListItemComparator.INSTANCE);
 				adapter.notifyDataSetChanged();
 				selectFirstUnread();
@@ -230,7 +231,7 @@ OnCreateContextMenuListener {
 		int count = adapter.getCount();
 		for (int i = 0; i < count; i++) {
 			ForumListItem item = adapter.getItem(i);
-			if (item.getGroup().getId().equals(g)) return item;
+			if (item.getForum().getId().equals(g)) return item;
 		}
 		return null; // Not found
 	}
@@ -255,8 +256,8 @@ OnCreateContextMenuListener {
 
 	public void eventOccurred(Event e) {
 		if (e instanceof MessageAddedEvent) {
-			Group g = ((MessageAddedEvent) e).getGroup();
-			if (groupIds.containsKey(g.getId())) {
+			GroupId g = ((MessageAddedEvent) e).getGroupId();
+			if (groupIds.containsKey(g)) {
 				LOG.info("Message added, reloading");
 				loadHeaders(g);
 			}
@@ -275,19 +276,20 @@ OnCreateContextMenuListener {
 		}
 	}
 
-	private void loadHeaders(final Group g) {
+	private void loadHeaders(final GroupId g) {
 		runOnDbThread(new Runnable() {
 			public void run() {
 				try {
 					long now = System.currentTimeMillis();
+					Forum f = forumManager.getForum(g);
 					Collection<MessageHeader> headers =
-							forumManager.getMessageHeaders(g.getId());
+							forumManager.getMessageHeaders(g);
 					long duration = System.currentTimeMillis() - now;
 					if (LOG.isLoggable(INFO))
 						LOG.info("Partial load took " + duration + " ms");
-					displayHeaders(g, headers);
+					displayHeaders(f, headers);
 				} catch (NoSuchSubscriptionException e) {
-					removeForum(g.getId());
+					removeForum(g);
 				} catch (DbException e) {
 					if (LOG.isLoggable(WARNING))
 						LOG.log(WARNING, e.toString(), e);
@@ -320,7 +322,7 @@ OnCreateContextMenuListener {
 			public void run() {
 				try {
 					long now = System.currentTimeMillis();
-					int available = forumManager.getAvailableGroups().size();
+					int available = forumManager.getAvailableForums().size();
 					long duration = System.currentTimeMillis() - now;
 					if (LOG.isLoggable(INFO))
 						LOG.info("Loading available took " + duration + " ms");
@@ -344,9 +346,9 @@ OnCreateContextMenuListener {
 	public void onItemClick(AdapterView<?> parent, View view, int position,
 			long id) {
 		Intent i = new Intent(this, ForumActivity.class);
-		Group g = adapter.getItem(position).getGroup();
-		i.putExtra("briar.GROUP_ID", g.getId().getBytes());
-		i.putExtra("briar.FORUM_NAME", g.getName());
+		Forum f = adapter.getItem(position).getForum();
+		i.putExtra("briar.GROUP_ID", f.getId().getBytes());
+		i.putExtra("briar.FORUM_NAME", f.getName());
 		startActivity(i);
 	}
 
@@ -363,19 +365,19 @@ OnCreateContextMenuListener {
 			ContextMenuInfo info = menuItem.getMenuInfo();
 			int position = ((AdapterContextMenuInfo) info).position;
 			ForumListItem item = adapter.getItem(position);
-			removeSubscription(item.getGroup());
+			removeSubscription(item.getForum());
 			String unsubscribed = getString(R.string.unsubscribed_toast);
 			Toast.makeText(this, unsubscribed, LENGTH_SHORT).show();
 		}
 		return true;
 	}
 
-	private void removeSubscription(final Group g) {
+	private void removeSubscription(final Forum f) {
 		runOnDbThread(new Runnable() {
 			public void run() {
 				try {
 					long now = System.currentTimeMillis();
-					forumManager.removeGroup(g);
+					forumManager.removeForum(f);
 					long duration = System.currentTimeMillis() - now;
 					if (LOG.isLoggable(INFO))
 						LOG.info("Removing group took " + duration + " ms");
diff --git a/briar-android/src/org/briarproject/android/forum/ForumListAdapter.java b/briar-android/src/org/briarproject/android/forum/ForumListAdapter.java
index e61cf9d249c3b275b16b4b40cf8c0c21a83724e1..17a7e2f2a4f847574c19e2dcb97c9582498f5477 100644
--- a/briar-android/src/org/briarproject/android/forum/ForumListAdapter.java
+++ b/briar-android/src/org/briarproject/android/forum/ForumListAdapter.java
@@ -46,7 +46,7 @@ class ForumListAdapter extends ArrayAdapter<ForumListItem> {
 		name.setSingleLine();
 		name.setEllipsize(END);
 		name.setPadding(pad, pad, pad, pad);
-		String forumName = item.getGroup().getName();
+		String forumName = item.getForum().getName();
 		if (unread > 0) name.setText(forumName + " (" + unread + ")");
 		else name.setText(forumName);
 		layout.addView(name);
diff --git a/briar-android/src/org/briarproject/android/forum/ForumListItem.java b/briar-android/src/org/briarproject/android/forum/ForumListItem.java
index 3eef6c43618ac539375465903d101f0ee4c39154..f3d665b47bd6357c39becc591e0337f5854ac29e 100644
--- a/briar-android/src/org/briarproject/android/forum/ForumListItem.java
+++ b/briar-android/src/org/briarproject/android/forum/ForumListItem.java
@@ -1,19 +1,19 @@
 package org.briarproject.android.forum;
 
-import org.briarproject.api.sync.Group;
+import org.briarproject.api.forum.Forum;
 import org.briarproject.api.sync.MessageHeader;
 
 import java.util.Collection;
 
 class ForumListItem {
 
-	private final Group group;
+	private final Forum forum;
 	private final boolean empty;
 	private final long timestamp;
 	private final int unread;
 
-	ForumListItem(Group group, Collection<MessageHeader> headers) {
-		this.group = group;
+	ForumListItem(Forum forum, Collection<MessageHeader> headers) {
+		this.forum = forum;
 		empty = headers.isEmpty();
 		if (empty) {
 			timestamp = 0;
@@ -34,8 +34,8 @@ class ForumListItem {
 		}
 	}
 
-	Group getGroup() {
-		return group;
+	Forum getForum() {
+		return forum;
 	}
 
 	boolean isEmpty() {
diff --git a/briar-android/src/org/briarproject/android/forum/ForumListItemComparator.java b/briar-android/src/org/briarproject/android/forum/ForumListItemComparator.java
index 46bc0d613a78c015ab40ae1f4150f4e21cb0bd1c..2c7ac144933d001922b2809dd7bc7875752cdb3a 100644
--- a/briar-android/src/org/briarproject/android/forum/ForumListItemComparator.java
+++ b/briar-android/src/org/briarproject/android/forum/ForumListItemComparator.java
@@ -9,13 +9,13 @@ class ForumListItemComparator implements Comparator<ForumListItem> {
 
 	public int compare(ForumListItem a, ForumListItem b) {
 		if (a == b) return 0;
-		// The item with the newest message comes first
+		// The forum with the newest message comes first
 		long aTime = a.getTimestamp(), bTime = b.getTimestamp();
 		if (aTime > bTime) return -1;
 		if (aTime < bTime) return 1;
-		// Break ties by group name
-		String aName = a.getGroup().getName();
-		String bName = b.getGroup().getName();
+		// Break ties by forum name
+		String aName = a.getForum().getName();
+		String bName = b.getForum().getName();
 		return String.CASE_INSENSITIVE_ORDER.compare(aName, bName);
 	}
 }
diff --git a/briar-android/src/org/briarproject/android/forum/WriteForumPostActivity.java b/briar-android/src/org/briarproject/android/forum/WriteForumPostActivity.java
index 16d2e41ca93c019021a98461a4795b3d9f50ed69..62a56a9a986f1249c1a3375048433983c42e52a2 100644
--- a/briar-android/src/org/briarproject/android/forum/WriteForumPostActivity.java
+++ b/briar-android/src/org/briarproject/android/forum/WriteForumPostActivity.java
@@ -28,14 +28,14 @@ import org.briarproject.api.crypto.CryptoExecutor;
 import org.briarproject.api.crypto.KeyParser;
 import org.briarproject.api.crypto.PrivateKey;
 import org.briarproject.api.db.DbException;
+import org.briarproject.api.forum.Forum;
 import org.briarproject.api.forum.ForumManager;
+import org.briarproject.api.forum.ForumPostFactory;
 import org.briarproject.api.identity.AuthorId;
 import org.briarproject.api.identity.IdentityManager;
 import org.briarproject.api.identity.LocalAuthor;
-import org.briarproject.api.sync.Group;
 import org.briarproject.api.sync.GroupId;
 import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageFactory;
 import org.briarproject.api.sync.MessageId;
 import org.briarproject.util.StringUtils;
 
@@ -79,11 +79,11 @@ implements OnItemSelectedListener, OnClickListener {
 	@Inject private volatile IdentityManager identityManager;
 	@Inject private volatile ForumManager forumManager;
 	@Inject private volatile CryptoComponent crypto;
-	@Inject private volatile MessageFactory messageFactory;
+	@Inject private volatile ForumPostFactory forumPostFactory;
 	private volatile MessageId parentId = null;
 	private volatile long minTimestamp = -1;
 	private volatile LocalAuthor localAuthor = null;
-	private volatile Group group = null;
+	private volatile Forum forum = null;
 
 	@Override
 	public void onCreate(Bundle state) {
@@ -138,7 +138,7 @@ implements OnItemSelectedListener, OnClickListener {
 		sendButton.setId(3);
 		sendButton.setBackgroundResource(0);
 		sendButton.setImageResource(R.drawable.social_send_now);
-		sendButton.setEnabled(false); // Enabled after loading the group
+		sendButton.setEnabled(false); // Enabled after loading the forum
 		sendButton.setOnClickListener(this);
 		RelativeLayout.LayoutParams right = CommonLayoutParams.relative();
 		right.addRule(ALIGN_PARENT_RIGHT);
@@ -170,7 +170,7 @@ implements OnItemSelectedListener, OnClickListener {
 					long now = System.currentTimeMillis();
 					Collection<LocalAuthor> localAuthors =
 							identityManager.getLocalAuthors();
-					group = forumManager.getGroup(groupId);
+					forum = forumManager.getForum(groupId);
 					long duration = System.currentTimeMillis() - now;
 					if (LOG.isLoggable(INFO))
 						LOG.info("Load took " + duration + " ms");
@@ -204,7 +204,7 @@ implements OnItemSelectedListener, OnClickListener {
 						break;
 					}
 				}
-				setTitle(group.getName());
+				setTitle(forum.getName());
 				sendButton.setEnabled(true);
 			}
 		});
@@ -253,7 +253,7 @@ implements OnItemSelectedListener, OnClickListener {
 	}
 
 	public void onClick(View view) {
-		if (group == null) throw new IllegalStateException();
+		if (forum == null) throw new IllegalStateException();
 		String message = content.getText().toString();
 		if (message.equals("")) return;
 		createMessage(StringUtils.toUtf8(message));
@@ -270,14 +270,14 @@ implements OnItemSelectedListener, OnClickListener {
 				Message m;
 				try {
 					if (localAuthor == null) {
-						m = messageFactory.createAnonymousMessage(parentId,
-								group, "text/plain", timestamp, body);
+						m = forumPostFactory.createAnonymousPost(parentId,
+								forum, "text/plain", timestamp, body);
 					} else {
 						KeyParser keyParser = crypto.getSignatureKeyParser();
 						byte[] b = localAuthor.getPrivateKey();
 						PrivateKey authorKey = keyParser.parsePrivateKey(b);
-						m = messageFactory.createPseudonymousMessage(parentId,
-								group, localAuthor, authorKey, "text/plain",
+						m = forumPostFactory.createPseudonymousPost(parentId,
+								forum, localAuthor, authorKey, "text/plain",
 								timestamp, body);
 					}
 				} catch (GeneralSecurityException e) {
diff --git a/briar-api/src/org/briarproject/api/event/MessageAddedEvent.java b/briar-api/src/org/briarproject/api/event/MessageAddedEvent.java
index 73f4175fb412348262e82a5a481f607f49bd678d..a557d008570563ba25d8ea228ce107e391eb12d0 100644
--- a/briar-api/src/org/briarproject/api/event/MessageAddedEvent.java
+++ b/briar-api/src/org/briarproject/api/event/MessageAddedEvent.java
@@ -1,22 +1,22 @@
 package org.briarproject.api.event;
 
 import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.sync.Group;
+import org.briarproject.api.sync.GroupId;
 
 /** An event that is broadcast when a message is added to the database. */
 public class MessageAddedEvent extends Event {
 
-	private final Group group;
+	private final GroupId groupId;
 	private final ContactId contactId;
 
-	public MessageAddedEvent(Group group, ContactId contactId) {
-		this.group = group;
+	public MessageAddedEvent(GroupId groupId, ContactId contactId) {
+		this.groupId = groupId;
 		this.contactId = contactId;
 	}
 
-	/** Returns the group to which the message belongs. */
-	public Group getGroup() {
-		return group;
+	/** Returns the ID of the group to which the message belongs. */
+	public GroupId getGroupId() {
+		return groupId;
 	}
 
 	/**
diff --git a/briar-api/src/org/briarproject/api/forum/Forum.java b/briar-api/src/org/briarproject/api/forum/Forum.java
new file mode 100644
index 0000000000000000000000000000000000000000..bad5f6ebf004767962a9dd6be700837bbd4fb236
--- /dev/null
+++ b/briar-api/src/org/briarproject/api/forum/Forum.java
@@ -0,0 +1,10 @@
+package org.briarproject.api.forum;
+
+import org.briarproject.api.sync.GroupId;
+
+public interface Forum {
+
+	GroupId getId();
+
+	String getName();
+}
diff --git a/briar-api/src/org/briarproject/api/forum/ForumFactory.java b/briar-api/src/org/briarproject/api/forum/ForumFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..d069c63d7a554893f5429b26ef7c71ab0f10f215
--- /dev/null
+++ b/briar-api/src/org/briarproject/api/forum/ForumFactory.java
@@ -0,0 +1,7 @@
+package org.briarproject.api.forum;
+
+public interface ForumFactory {
+
+	/** Creates a forum with the given name and a random salt. */
+	Forum createForum(String name);
+}
diff --git a/briar-api/src/org/briarproject/api/forum/ForumManager.java b/briar-api/src/org/briarproject/api/forum/ForumManager.java
index eec231dd996099d2c35443516f6168044caf070d..b2b70b70f3879e43126662016df4928d3d6a2d5f 100644
--- a/briar-api/src/org/briarproject/api/forum/ForumManager.java
+++ b/briar-api/src/org/briarproject/api/forum/ForumManager.java
@@ -3,7 +3,6 @@ package org.briarproject.api.forum;
 import org.briarproject.api.contact.Contact;
 import org.briarproject.api.contact.ContactId;
 import org.briarproject.api.db.DbException;
-import org.briarproject.api.sync.Group;
 import org.briarproject.api.sync.GroupId;
 import org.briarproject.api.sync.Message;
 import org.briarproject.api.sync.MessageHeader;
@@ -14,56 +13,54 @@ import java.util.Collection;
 public interface ForumManager {
 
 	/**
-	 * Subscribes to a group, or returns false if the user already has the
-	 * maximum number of public subscriptions.
+	 * Subscribes to a forum, or returns false if the user already has the
+	 * maximum number of forum subscriptions.
 	 */
-	boolean addGroup(Group g) throws DbException;
+	boolean addForum(Forum f) throws DbException;
 
 	/** Stores a local message. */
 	void addLocalMessage(Message m) throws DbException;
 
-	/** Returns all groups to which the user could subscribe. */
-	Collection<Group> getAvailableGroups() throws DbException;
+	/** Returns all forums to which the user could subscribe. */
+	Collection<Forum> getAvailableForums() throws DbException;
 
-	/** Returns the group with the given ID, if the user subscribes to it. */
-	Group getGroup(GroupId g) throws DbException;
+	/** Returns the forum with the given ID, if the user subscribes to it. */
+	Forum getForum(GroupId g) throws DbException;
 
-	/** Returns all groups to which the user subscribes, excluding inboxes. */
-	Collection<Group> getGroups() throws DbException;
+	/** Returns all forums to which the user subscribes. */
+	Collection<Forum> getForums() throws DbException;
 
 	/** Returns the body of the message with the given ID. */
 	byte[] getMessageBody(MessageId m) throws DbException;
 
-	/** Returns the headers of all messages in the given group. */
+	/** Returns the headers of all messages in the given forum. */
 	Collection<MessageHeader> getMessageHeaders(GroupId g)
 			throws DbException;
 
-	/** Returns all contacts who subscribe to the given group. */
+	/** Returns all contacts who subscribe to the given forum. */
 	Collection<Contact> getSubscribers(GroupId g) throws DbException;
 
-	/** Returns the IDs of all contacts to which the given group is visible. */
+	/** Returns the IDs of all contacts to which the given forum is visible. */
 	Collection<ContactId> getVisibility(GroupId g) throws DbException;
 
 	/**
-	 * Unsubscribes from a group. Any messages belonging to the group
-	 * are deleted.
+	 * Unsubscribes from a forum. Any messages belonging to the forum are
+	 * deleted.
 	 */
-	void removeGroup(Group g) throws DbException;
+	void removeForum(Forum f) throws DbException;
 
-	/**
-	 * Marks a message as read or unread.
-	 */
+	/** Marks a message as read or unread. */
 	void setReadFlag(MessageId m, boolean read) throws DbException;
 
 	/**
-	 * Makes a group visible to the given set of contacts and invisible to any
+	 * Makes a forum visible to the given set of contacts and invisible to any
 	 * other current or future contacts.
 	 */
 	void setVisibility(GroupId g, Collection<ContactId> visible)
 			throws DbException;
 
 	/**
-	 * Makes a group visible to all current and future contacts, or invisible
+	 * Makes a forum visible to all current and future contacts, or invisible
 	 * to future contacts.
 	 */
 	void setVisibleToAll(GroupId g, boolean all) throws DbException;
diff --git a/briar-api/src/org/briarproject/api/forum/ForumPostFactory.java b/briar-api/src/org/briarproject/api/forum/ForumPostFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..185eb16b003880caf569d2043eb66aece0973822
--- /dev/null
+++ b/briar-api/src/org/briarproject/api/forum/ForumPostFactory.java
@@ -0,0 +1,21 @@
+package org.briarproject.api.forum;
+
+import org.briarproject.api.crypto.PrivateKey;
+import org.briarproject.api.identity.Author;
+import org.briarproject.api.sync.Message;
+import org.briarproject.api.sync.MessageId;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+
+public interface ForumPostFactory {
+
+	Message createAnonymousPost(MessageId parent, Forum forum,
+			String contentType, long timestamp, byte[] body) throws IOException,
+			GeneralSecurityException;
+
+	Message createPseudonymousPost(MessageId parent, Forum forum,
+			Author author, PrivateKey privateKey, String contentType,
+			long timestamp, byte[] body) throws IOException,
+			GeneralSecurityException;
+}
diff --git a/briar-core/src/org/briarproject/db/DatabaseComponentImpl.java b/briar-core/src/org/briarproject/db/DatabaseComponentImpl.java
index 87f8aa49b4533135e08aeaff7115d7f27aaad7c2..2447b3844c43e80db1e592724a312e90852aae66 100644
--- a/briar-core/src/org/briarproject/db/DatabaseComponentImpl.java
+++ b/briar-core/src/org/briarproject/db/DatabaseComponentImpl.java
@@ -222,8 +222,10 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
 		} finally {
 			lock.writeLock().unlock();
 		}
-		if (!duplicate && subscribed)
-			eventBus.broadcast(new MessageAddedEvent(m.getGroup(), null));
+		if (!duplicate && subscribed) {
+			GroupId g = m.getGroup().getId();
+			eventBus.broadcast(new MessageAddedEvent(g, null));
+		}
 	}
 
 	/**
@@ -1050,8 +1052,10 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
 			lock.writeLock().unlock();
 		}
 		if (visible) {
-			if (!duplicate)
-				eventBus.broadcast(new MessageAddedEvent(m.getGroup(), c));
+			if (!duplicate) {
+				GroupId g = m.getGroup().getId();
+				eventBus.broadcast(new MessageAddedEvent(g, c));
+			}
 			eventBus.broadcast(new MessageToAckEvent(c));
 		}
 	}
diff --git a/briar-core/src/org/briarproject/forum/ForumFactoryImpl.java b/briar-core/src/org/briarproject/forum/ForumFactoryImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..3dcb401aa0cf1bec953f7b7e550a93ecdcf32577
--- /dev/null
+++ b/briar-core/src/org/briarproject/forum/ForumFactoryImpl.java
@@ -0,0 +1,22 @@
+package org.briarproject.forum;
+
+import com.google.inject.Inject;
+
+import org.briarproject.api.forum.Forum;
+import org.briarproject.api.forum.ForumFactory;
+import org.briarproject.api.sync.GroupFactory;
+
+// Temporary facade during sync protocol refactoring
+class ForumFactoryImpl implements ForumFactory {
+
+	private final GroupFactory groupFactory;
+
+	@Inject
+	ForumFactoryImpl(GroupFactory groupFactory) {
+		this.groupFactory = groupFactory;
+	}
+
+	public Forum createForum(String name) {
+		return new ForumImpl(groupFactory.createGroup(name));
+	}
+}
diff --git a/briar-core/src/org/briarproject/forum/ForumImpl.java b/briar-core/src/org/briarproject/forum/ForumImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..90a6b85abfbc6d53609935fde2c8a51ba2c8f214
--- /dev/null
+++ b/briar-core/src/org/briarproject/forum/ForumImpl.java
@@ -0,0 +1,37 @@
+package org.briarproject.forum;
+
+import org.briarproject.api.forum.Forum;
+import org.briarproject.api.sync.Group;
+import org.briarproject.api.sync.GroupId;
+
+// Temporary facade during sync protocol refactoring
+class ForumImpl implements Forum {
+
+	private final Group group;
+
+	ForumImpl(Group group) {
+		this.group = group;
+	}
+
+	public GroupId getId() {
+		return group.getId();
+	}
+
+	public String getName() {
+		return group.getName();
+	}
+
+	Group getGroup() {
+		return group;
+	}
+
+	@Override
+	public int hashCode() {
+		return group.hashCode();
+	}
+
+	@Override
+	public boolean equals(Object o) {
+		return o instanceof ForumImpl && group.equals(((ForumImpl) o).group);
+	}
+}
diff --git a/briar-core/src/org/briarproject/forum/ForumManagerImpl.java b/briar-core/src/org/briarproject/forum/ForumManagerImpl.java
index 06c902c98a13d49935dec12bcd7658faf2946f36..caa1e56c4802f21d52302ef25ded7f1c303e0a8b 100644
--- a/briar-core/src/org/briarproject/forum/ForumManagerImpl.java
+++ b/briar-core/src/org/briarproject/forum/ForumManagerImpl.java
@@ -6,6 +6,7 @@ import org.briarproject.api.contact.Contact;
 import org.briarproject.api.contact.ContactId;
 import org.briarproject.api.db.DatabaseComponent;
 import org.briarproject.api.db.DbException;
+import org.briarproject.api.forum.Forum;
 import org.briarproject.api.forum.ForumManager;
 import org.briarproject.api.sync.Group;
 import org.briarproject.api.sync.GroupId;
@@ -13,8 +14,12 @@ 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 ForumManagerImpl implements ForumManager {
 
 	private final DatabaseComponent db;
@@ -25,8 +30,8 @@ class ForumManagerImpl implements ForumManager {
 	}
 
 	@Override
-	public boolean addGroup(Group g) throws DbException {
-		return db.addGroup(g);
+	public boolean addForum(Forum f) throws DbException {
+		return db.addGroup(((ForumImpl) f).getGroup());
 	}
 
 	@Override
@@ -35,18 +40,24 @@ class ForumManagerImpl implements ForumManager {
 	}
 
 	@Override
-	public Collection<Group> getAvailableGroups() throws DbException {
-		return db.getAvailableGroups();
+	public Collection<Forum> getAvailableForums() throws DbException {
+		Collection<Group> groups = db.getAvailableGroups();
+		List<Forum> forums = new ArrayList<Forum>(groups.size());
+		for (Group g : groups) forums.add(new ForumImpl(g));
+		return Collections.unmodifiableList(forums);
 	}
 
 	@Override
-	public Group getGroup(GroupId g) throws DbException {
-		return db.getGroup(g);
+	public Forum getForum(GroupId g) throws DbException {
+		return new ForumImpl(db.getGroup(g));
 	}
 
 	@Override
-	public Collection<Group> getGroups() throws DbException {
-		return db.getGroups();
+	public Collection<Forum> getForums() throws DbException {
+		Collection<Group> groups = db.getGroups();
+		List<Forum> forums = new ArrayList<Forum>(groups.size());
+		for (Group g : groups) forums.add(new ForumImpl(g));
+		return Collections.unmodifiableList(forums);
 	}
 
 	@Override
@@ -71,8 +82,8 @@ class ForumManagerImpl implements ForumManager {
 	}
 
 	@Override
-	public void removeGroup(Group g) throws DbException {
-		db.removeGroup(g);
+	public void removeForum(Forum f) throws DbException {
+		db.removeGroup(((ForumImpl) f).getGroup());
 	}
 
 	@Override
diff --git a/briar-core/src/org/briarproject/forum/ForumModule.java b/briar-core/src/org/briarproject/forum/ForumModule.java
index 0015457c1b1ee5320d813b80ea08c43cc4d7b940..6e63a34e88bb8cee12f5261b86e2f5c3a28b6645 100644
--- a/briar-core/src/org/briarproject/forum/ForumModule.java
+++ b/briar-core/src/org/briarproject/forum/ForumModule.java
@@ -2,12 +2,16 @@ package org.briarproject.forum;
 
 import com.google.inject.AbstractModule;
 
+import org.briarproject.api.forum.ForumFactory;
 import org.briarproject.api.forum.ForumManager;
+import org.briarproject.api.forum.ForumPostFactory;
 
 public class ForumModule extends AbstractModule {
 
 	@Override
 	protected void configure() {
+		bind(ForumFactory.class).to(ForumFactoryImpl.class);
 		bind(ForumManager.class).to(ForumManagerImpl.class);
+		bind(ForumPostFactory.class).to(ForumPostFactoryImpl.class);
 	}
 }
diff --git a/briar-core/src/org/briarproject/forum/ForumPostFactoryImpl.java b/briar-core/src/org/briarproject/forum/ForumPostFactoryImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..b4f09ce0f25719fd44180d704562a21cb13816f4
--- /dev/null
+++ b/briar-core/src/org/briarproject/forum/ForumPostFactoryImpl.java
@@ -0,0 +1,43 @@
+package org.briarproject.forum;
+
+import com.google.inject.Inject;
+
+import org.briarproject.api.crypto.PrivateKey;
+import org.briarproject.api.forum.Forum;
+import org.briarproject.api.forum.ForumPostFactory;
+import org.briarproject.api.identity.Author;
+import org.briarproject.api.sync.Message;
+import org.briarproject.api.sync.MessageFactory;
+import org.briarproject.api.sync.MessageId;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+
+// Temporary facade during sync protocol refactoring
+class ForumPostFactoryImpl implements ForumPostFactory {
+
+	private final MessageFactory messageFactory;
+
+	@Inject
+	ForumPostFactoryImpl(MessageFactory messageFactory) {
+		this.messageFactory = messageFactory;
+	}
+
+	@Override
+	public Message createAnonymousPost(MessageId parent, Forum forum,
+			String contentType, long timestamp, byte[] body)
+			throws IOException, GeneralSecurityException {
+		return messageFactory.createAnonymousMessage(parent,
+				((ForumImpl) forum).getGroup(), contentType, timestamp, body);
+	}
+
+	@Override
+	public Message createPseudonymousPost(MessageId parent, Forum forum,
+			Author author, PrivateKey privateKey, String contentType,
+			long timestamp, byte[] body)
+			throws IOException, GeneralSecurityException {
+		return messageFactory.createPseudonymousMessage(parent,
+				((ForumImpl) forum).getGroup(), author, privateKey, contentType,
+				timestamp, body);
+	}
+}