diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/sync/ClientVersioningManager.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/ClientVersioningManager.java
index 8a374b288c3d73e43f2a8fda1ee245de183d1f78..781ce4b4e41e42cdc75951c6cd0224db8f4c1034 100644
--- a/bramble-api/src/main/java/org/briarproject/bramble/api/sync/ClientVersioningManager.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/ClientVersioningManager.java
@@ -1,6 +1,7 @@
 package org.briarproject.bramble.api.sync;
 
 import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.contact.ContactId;
 import org.briarproject.bramble.api.db.DbException;
 import org.briarproject.bramble.api.db.Transaction;
 import org.briarproject.bramble.api.lifecycle.LifecycleManager;
@@ -34,6 +35,13 @@ public interface ClientVersioningManager {
 	void registerClientVersioningHook(ClientId clientId, int clientVersion,
 			ClientVersioningHook hook);
 
+	/**
+	 * Returns the visibility of the given client with respect to the given
+	 * contact.
+	 */
+	Visibility getClientVisibility(Transaction txn, ContactId contactId,
+			ClientId clientId, int clientVersion) throws DbException;
+
 	interface ClientVersioningHook {
 
 		void onClientVisibilityChanging(Transaction txn, Contact c,
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/sync/ClientVersioningManagerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/sync/ClientVersioningManagerImpl.java
index 5594ac5e57331ec89a5d20a5045aca91dc519ee6..5f51690a37d9d2a5bb4797f5d3ec5d8d4645b7ed 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/sync/ClientVersioningManagerImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/sync/ClientVersioningManagerImpl.java
@@ -89,6 +89,28 @@ class ClientVersioningManagerImpl implements ClientVersioningManager, Client,
 		hooks.put(new ClientVersion(clientId, clientVersion), hook);
 	}
 
+	@Override
+	public Visibility getClientVisibility(Transaction txn,
+			ContactId contactId, ClientId clientId, int clientVersion)
+			throws DbException {
+		try {
+			Contact contact = db.getContact(txn, contactId);
+			Group g = getContactGroup(contact);
+			LatestUpdates latest = findLatestUpdates(txn, g.getId());
+			if (latest.local == null) throw new DbException();
+			if (latest.remote == null) return INVISIBLE;
+			Update localUpdate = loadUpdate(txn, latest.local.messageId);
+			Update remoteUpdate = loadUpdate(txn, latest.remote.messageId);
+			Map<ClientVersion, Visibility> visibilities =
+					getVisibilities(localUpdate.states, remoteUpdate.states);
+			ClientVersion cv = new ClientVersion(clientId, clientVersion);
+			Visibility v = visibilities.get(cv);
+			return v == null ? INVISIBLE : v;
+		} catch (FormatException e) {
+			throw new DbException(e);
+		}
+	}
+
 	@Override
 	public void createLocalState(Transaction txn) throws DbException {
 		if (db.containsGroup(txn, localGroup.getId())) return;