diff --git a/coreapi/friend.c b/coreapi/friend.c
index 0fdc8f6049a4b831d5d62a9291e0e9ba1ad2ebc3..33c7174d361d50ad325fe3ffc4d4759dadf74d07 100644
--- a/coreapi/friend.c
+++ b/coreapi/friend.c
@@ -1761,3 +1761,86 @@ int linphone_friend_get_capabilities(const LinphoneFriend *lf) {
 bool_t linphone_friend_has_capability(const LinphoneFriend *lf, const LinphoneFriendCapability capability) {
 	return static_cast<bool_t>(linphone_friend_get_capabilities(lf) & capability);
 }
+
+bool_t linphone_friend_has_capability_with_version(const LinphoneFriend *lf, const LinphoneFriendCapability capability, float version) {
+	const LinphonePresenceModel *presence = NULL;
+	const bctbx_list_t* addrs = linphone_friend_get_addresses(lf);
+	bctbx_list_t* phones = linphone_friend_get_phone_numbers(lf);
+	bctbx_list_t *it;
+	bool_t result = FALSE;
+
+	for (it = (bctbx_list_t *)addrs; it!= NULL; it = it->next) {
+		LinphoneAddress *addr = (LinphoneAddress*)it->data;
+		char *uri = linphone_address_as_string_uri_only(addr);
+		presence = linphone_friend_get_presence_model_for_uri_or_tel(lf, uri);
+		ms_free(uri);
+
+		if (!presence) continue;
+		if(linphone_presence_model_has_capability_with_version(presence, capability, version)) result = TRUE;
+	}
+	for (it = phones; it!= NULL; it = it->next) {
+		presence = linphone_friend_get_presence_model_for_uri_or_tel(lf, reinterpret_cast<const char *>(it->data));
+
+		if (!presence) continue;
+		if(linphone_presence_model_has_capability_with_version(presence, capability, version)) result = TRUE;
+	}
+	bctbx_list_free(phones);
+
+	return result;
+}
+
+bool_t linphone_friend_has_capability_with_version_or_more(const LinphoneFriend *lf, const LinphoneFriendCapability capability, float version) {
+	const LinphonePresenceModel *presence = NULL;
+	const bctbx_list_t* addrs = linphone_friend_get_addresses(lf);
+	bctbx_list_t* phones = linphone_friend_get_phone_numbers(lf);
+	bctbx_list_t *it;
+	bool_t result = FALSE;
+
+	for (it = (bctbx_list_t *)addrs; it!= NULL; it = it->next) {
+		LinphoneAddress *addr = (LinphoneAddress*)it->data;
+		char *uri = linphone_address_as_string_uri_only(addr);
+		presence = linphone_friend_get_presence_model_for_uri_or_tel(lf, uri);
+		ms_free(uri);
+
+		if (!presence) continue;
+		if (linphone_presence_model_has_capability_with_version_or_more(presence, capability, version)) result = TRUE;
+	}
+	for (it = phones; it!= NULL; it = it->next) {
+		presence = linphone_friend_get_presence_model_for_uri_or_tel(lf, reinterpret_cast<const char *>(it->data));
+
+		if (!presence) continue;
+		if (linphone_presence_model_has_capability_with_version_or_more(presence, capability, version)) result = TRUE;
+	}
+	bctbx_list_free(phones);
+
+	return result;
+}
+
+float linphone_friend_get_capability_version(const LinphoneFriend *lf, const LinphoneFriendCapability capability) {
+	const LinphonePresenceModel *presence = NULL;
+	const bctbx_list_t* addrs = linphone_friend_get_addresses(lf);
+	bctbx_list_t* phones = linphone_friend_get_phone_numbers(lf);
+	bctbx_list_t *it;
+	float version = -1.0;
+
+	for (it = (bctbx_list_t *)addrs; it!= NULL; it = it->next) {
+		LinphoneAddress *addr = (LinphoneAddress*)it->data;
+		char *uri = linphone_address_as_string_uri_only(addr);
+		presence = linphone_friend_get_presence_model_for_uri_or_tel(lf, uri);
+		ms_free(uri);
+
+		if (!presence) continue;
+		float presence_version = linphone_presence_model_get_capability_version(presence, capability);
+		if (presence_version > version) version = presence_version;
+	}
+	for (it = phones; it!= NULL; it = it->next) {
+		presence = linphone_friend_get_presence_model_for_uri_or_tel(lf, reinterpret_cast<const char *>(it->data));
+
+		if (!presence) continue;
+		float presence_version = linphone_presence_model_get_capability_version(presence, capability);
+		if (presence_version > version) version = presence_version;
+	}
+	bctbx_list_free(phones);
+
+	return version;
+}
diff --git a/coreapi/presence.c b/coreapi/presence.c
index 43e85573456ede39a5fd232643c2f4ad99def30a..634797cc3bbfdb147cf1e6e99641760dcf7c1cad 100644
--- a/coreapi/presence.c
+++ b/coreapi/presence.c
@@ -17,6 +17,10 @@ along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
 
+#include <cmath>
+
+#include <bctoolbox/map.h>
+
 #include "linphone/core.h"
 #include "linphone/lpconfig.h"
 #include "linphone/presence.h"
@@ -49,6 +53,7 @@ struct _LinphonePresenceService {
 	bctbx_list_t *notes;				/**< A list of _LinphonePresenceNote structures. */
 	time_t timestamp;
 	bctbx_list_t *service_descriptions;
+	bctbx_map_t *capabilities;
 };
 
 BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphonePresenceService);
@@ -138,6 +143,7 @@ static LinphonePresenceService * presence_service_new(const char *id, LinphonePr
 	}
 	service->status = status;
 	service->timestamp = time(NULL);
+	service->capabilities = bctbx_mmap_cchar_new();
 	return service;
 }
 
@@ -150,6 +156,7 @@ static void presence_service_uninit(LinphonePresenceService *service) {
 	}
 	bctbx_list_for_each(service->notes, presence_note_unref);
 	bctbx_list_free(service->notes);
+	bctbx_mmap_cchar_delete_with_data(service->capabilities, bctbx_free);
 };
 
 static void presence_service_unref(void *service) {
@@ -814,6 +821,54 @@ LinphoneStatus linphone_presence_service_set_service_descriptions(LinphonePresen
 	return 0;
 }
 
+namespace {
+	const std::unordered_map<int, std::string> CapabilityToString {
+		{ LinphoneFriendCapabilityGroupChat, "groupchat" },
+		{ LinphoneFriendCapabilityLimeX3dh, "lime" }
+	};
+}
+static std::string capability_to_string (const LinphoneFriendCapability capability) {
+	const auto &it = CapabilityToString.find(static_cast<int>(capability));
+	return (it == CapabilityToString.cend()) ? "none" : it->second;
+}
+static const float EPSILON = 0.1f;
+bool_t linphone_presence_service_has_capability_with_version(
+	const LinphonePresenceService *service,
+	const LinphoneFriendCapability capability,
+	float version
+) {
+	const auto &it = bctbx_map_cchar_find_key(service->capabilities, capability_to_string(capability).c_str());
+	if (!bctbx_iterator_equals(it, bctbx_map_cchar_end(service->capabilities)))
+		return static_cast<bool_t>(fabs(std::stof(std::string((const char *)bctbx_pair_cchar_get_second(bctbx_iterator_cchar_get_pair(it)))) - version) < EPSILON);
+
+	return FALSE;
+}
+
+bool_t linphone_presence_service_has_capability_with_version_or_more(
+	const LinphonePresenceService *service,
+	const LinphoneFriendCapability capability,
+	float version
+) {
+	const auto &it = bctbx_map_cchar_find_key(service->capabilities, capability_to_string(capability).c_str());
+	if (!bctbx_iterator_equals(it, bctbx_map_cchar_end(service->capabilities)))
+		return static_cast<bool_t>(std::stof(std::string((const char *)bctbx_pair_cchar_get_second(bctbx_iterator_cchar_get_pair(it)))) >= version);
+
+	return FALSE;
+}
+
+float linphone_presence_service_get_capability_version(const LinphonePresenceService *service, const LinphoneFriendCapability capability) {
+	const auto &it = bctbx_map_cchar_find_key(service->capabilities, capability_to_string(capability).c_str());
+	if (!bctbx_iterator_equals(it, bctbx_map_cchar_end(service->capabilities)))
+		return std::stof(std::string((const char *)bctbx_pair_cchar_get_second(bctbx_iterator_cchar_get_pair(it))));
+
+	return -1.0;
+}
+
+void linphone_presence_service_add_capability(LinphonePresenceService *service, const char *capability_name, const char *version) {
+	const bctbx_pair_cchar_t *pair = bctbx_pair_cchar_new(capability_name, (void *)version);
+	bctbx_map_cchar_insert(service->capabilities, (const bctbx_pair_t *)pair);
+}
+
 unsigned int linphone_presence_service_get_nb_notes(const LinphonePresenceService *service) {
 	return (unsigned int)bctbx_list_size(service->notes);
 }
@@ -1157,13 +1212,13 @@ void * linphone_presence_model_get_user_data(const LinphonePresenceModel *model)
 }
 
 namespace {
-	const std::unordered_map<std::string, LinphoneFriendCapability> StringToCapability{
+	const std::unordered_map<std::string, LinphoneFriendCapability> StringToCapability {
 		{ "groupchat", LinphoneFriendCapabilityGroupChat },
 		{ "lime", LinphoneFriendCapabilityLimeX3dh }
 	};
 }
 static LinphoneFriendCapability get_capability_from_string (const std::string &capabilityName) {
-	auto it = StringToCapability.find(capabilityName);
+	const auto &it = StringToCapability.find(capabilityName);
 	return (it == StringToCapability.cend()) ? LinphoneFriendCapabilityNone : it->second;
 }
 int linphone_presence_model_get_capabilities(const LinphonePresenceModel *model) {
@@ -1189,6 +1244,52 @@ bool_t linphone_presence_model_has_capability(const LinphonePresenceModel *model
 	return static_cast<bool_t>(linphone_presence_model_get_capabilities(model) & capability);
 }
 
+bool_t linphone_presence_model_has_capability_with_version(
+	const LinphonePresenceModel *model,
+	const LinphoneFriendCapability capability,
+	float version
+) {
+	unsigned int nbServices = linphone_presence_model_get_nb_services(model);
+	for (unsigned int i = 0; i < nbServices; i++) {
+		LinphonePresenceService *service = linphone_presence_model_get_nth_service(model, i);
+		if (!service) continue;
+
+		if (linphone_presence_service_has_capability_with_version(service, capability, version)) return TRUE;
+	}
+
+	return FALSE;
+}
+
+bool_t linphone_presence_model_has_capability_with_version_or_more(
+	const LinphonePresenceModel *model,
+	const LinphoneFriendCapability capability,
+	float version
+) {
+	unsigned int nbServices = linphone_presence_model_get_nb_services(model);
+	for (unsigned int i = 0; i < nbServices; i++) {
+		LinphonePresenceService *service = linphone_presence_model_get_nth_service(model, i);
+		if (!service) continue;
+
+		if (linphone_presence_service_has_capability_with_version_or_more(service, capability, version)) return TRUE;
+	}
+
+	return FALSE;
+}
+
+float linphone_presence_model_get_capability_version(const LinphonePresenceModel *model, const LinphoneFriendCapability capability) {
+	float version = -1.0;
+	unsigned int nbServices = linphone_presence_model_get_nb_services(model);
+	for (unsigned int i = 0; i < nbServices; i++) {
+		LinphonePresenceService *service = linphone_presence_model_get_nth_service(model, i);
+		if (!service) continue;
+
+		float service_version = linphone_presence_service_get_capability_version(service, capability);
+		if (service_version > version) version = service_version;
+	}
+
+	return version;
+}
+
 LinphonePresenceService * linphone_presence_service_ref(LinphonePresenceService *service) {
 	return (LinphonePresenceService *)belle_sip_object_ref(service);
 }
@@ -1353,11 +1454,17 @@ static int process_pidf_xml_presence_services(xmlparsing_context_t *xml_ctx, Lin
 			if (service_descriptions && service_descriptions->nodesetval) {
 				for (int j = 1; j <= service_descriptions->nodesetval->nodeNr; j++) {
 					char *service_id = nullptr;
+					char *version = nullptr;
 					linphone_xml_xpath_context_set_node(xml_ctx, xmlXPathNodeSetItem(service_descriptions->nodesetval, j-1));
 					service_id = linphone_get_xml_text_content(xml_ctx, "./oma-pres:service-id");
 					if (service_id) {
+						version = linphone_get_xml_text_content(xml_ctx, "./oma-pres:version");
 						services = bctbx_list_append(services, ms_strdup(service_id));
+
+						if (service) linphone_presence_service_add_capability(service, ms_strdup(service_id), ms_strdup(version));
+
 						linphone_free_xml_text_content(service_id);
+						linphone_free_xml_text_content(version);
 					}
 				}
 			}
diff --git a/include/linphone/friend.h b/include/linphone/friend.h
index b73c5646417141e23143a8313e75d8b849484c63..c21d596b9327fa7259e5ee897ae2a18cae0ab6f6 100644
--- a/include/linphone/friend.h
+++ b/include/linphone/friend.h
@@ -353,6 +353,32 @@ LINPHONE_PUBLIC int linphone_friend_get_capabilities(const LinphoneFriend *lf);
  */
 LINPHONE_PUBLIC bool_t linphone_friend_has_capability(const LinphoneFriend *lf, const LinphoneFriendCapability capability);
 
+/**
+ * Returns whether or not a friend has a capbility with a given version.
+ * @param[in] lf #LinphoneFriend object
+ * @param[in] capability #LinphoneFriendCapability object
+ * @param[in] version the version to test
+ * @return whether or not a friend has a capbility with a given version or -1.0 if friend has not capability.
+ */
+LINPHONE_PUBLIC bool_t linphone_friend_has_capability_with_version(const LinphoneFriend *lf, const LinphoneFriendCapability capability, float version);
+
+/**
+ * Returns whether or not a friend has a capbility with a given version or more.
+ * @param[in] lf #LinphoneFriend object
+ * @param[in] capability #LinphoneFriendCapability object
+ * @param[in] version the version to test
+ * @return whether or not a friend has a capbility with a given version or more.
+ */
+LINPHONE_PUBLIC bool_t linphone_friend_has_capability_with_version_or_more(const LinphoneFriend *lf, const LinphoneFriendCapability capability, float version);
+
+/**
+ * Returns the version of a friend's capbility.
+ * @param[in] lf #LinphoneFriend object
+ * @param[in] capability #LinphoneFriendCapability object
+ * @return the version of a friend's capbility.
+ */
+LINPHONE_PUBLIC float linphone_friend_get_capability_version(const LinphoneFriend *lf, const LinphoneFriendCapability capability);
+
 /**
  * @}
  */
diff --git a/include/linphone/presence.h b/include/linphone/presence.h
index 2ec8448e4ddd3bf4d6287696c608606e0325edf1..446a3ce9acd6cd7e28da1351b29b9c0540982d9a 100644
--- a/include/linphone/presence.h
+++ b/include/linphone/presence.h
@@ -670,6 +670,40 @@ LINPHONE_PUBLIC int linphone_presence_model_get_capabilities(const LinphonePrese
  */
 LINPHONE_PUBLIC bool_t linphone_presence_model_has_capability(const LinphonePresenceModel *model, const LinphoneFriendCapability capability);
 
+/**
+ * Returns whether or not the #LinphonePresenceModel object has a given capability with a certain version.
+ * @param[in] model The #LinphonePresenceModel object for which to set the contact.
+ * @param[in] capability The capability to test.
+ * @param[in] version The wanted version to test.
+ * @return whether or not the #LinphonePresenceModel object has a given capability with a certain version.
+ */
+LINPHONE_PUBLIC bool_t linphone_presence_model_has_capability_with_version(
+	const LinphonePresenceModel *model,
+	const LinphoneFriendCapability capability,
+	float version
+);
+
+/**
+ * Returns whether or not the #LinphonePresenceModel object has a given capability with a certain version or more.
+ * @param[in] model The #LinphonePresenceModel object for which to set the contact.
+ * @param[in] capability The capability to test.
+ * @param[in] version The wanted version to test.
+ * @return whether or not the #LinphonePresenceModel object has a given capability with a certain version or more.
+ */
+LINPHONE_PUBLIC bool_t linphone_presence_model_has_capability_with_version_or_more(
+	const LinphonePresenceModel *model,
+	const LinphoneFriendCapability capability,
+	float version
+);
+
+/**
+ * Returns the version of the capability of a #LinphonePresenceModel.
+ * @param[in] model The #LinphonePresenceModel object for which to set the contact.
+ * @param[in] capability The capability to test.
+ * @return the version of the capability of a #LinphonePresenceModel or -1.0 if the model has not the capability.
+ */
+LINPHONE_PUBLIC float linphone_presence_model_get_capability_version(const LinphonePresenceModel *model, const LinphoneFriendCapability capability);
+
 /**
  * Increase the reference count of the #LinphonePresenceService object.
  * @param[in] service The #LinphonePresenceService object for which the reference count is to be increased.
diff --git a/tester/presence_server_tester.c b/tester/presence_server_tester.c
index c990e2238e05935bbfd38b248ccbed5666ed3f76..efd4ccaf4fa7c58d82ef654b6882499ffdf32f43 100644
--- a/tester/presence_server_tester.c
+++ b/tester/presence_server_tester.c
@@ -1864,11 +1864,13 @@ static void notify_friend_capabilities(void) {
 	LinphoneCoreManager *laure = linphone_core_manager_create("laure_tcp_rc");
 	LinphoneCoreManager *chloe = linphone_core_manager_create("chloe_rc");
 	LinphoneCoreManager *chloe2 = linphone_core_manager_create("chloe_rc");
+	LinphoneCoreManager *chloe3 = linphone_core_manager_create("chloe_rc");
 
-	linphone_core_set_linphone_specs(pauline->lc, "groupchat");
+	linphone_core_set_linphone_specs(pauline->lc, "groupchat/1.1");
 	linphone_core_set_linphone_specs(pauline2->lc, "lime");
-	linphone_core_set_linphone_specs(laure->lc, "groupchat");
-	linphone_core_set_linphone_specs(chloe->lc, "groupchat, lime");
+	linphone_core_set_linphone_specs(laure->lc, "groupchat/2.0");
+	linphone_core_set_linphone_specs(chloe->lc, "groupchat/2.1, lime/1.5");
+	linphone_core_set_linphone_specs(chloe3->lc, "groupchat/2.1, lime/1.7");
 
 	linphone_core_manager_start(marie, TRUE);
 	linphone_core_manager_start(pauline, TRUE);
@@ -1876,6 +1878,7 @@ static void notify_friend_capabilities(void) {
 	linphone_core_manager_start(laure, TRUE);
 	linphone_core_manager_start(chloe, TRUE);
 	linphone_core_manager_start(chloe2, TRUE);
+	linphone_core_manager_start(chloe3, TRUE);
 
 	LinphoneFriendList *mFriendList = linphone_core_get_default_friend_list(marie->lc);
 	LinphoneFriend *mPaulineFriend = linphone_core_create_friend_with_address(marie->lc, get_identity(pauline));
@@ -1913,6 +1916,7 @@ static void notify_friend_capabilities(void) {
 	lcs = bctbx_list_append(lcs, laure->lc);
 	lcs = bctbx_list_append(lcs, chloe->lc);
 	lcs = bctbx_list_append(lcs, chloe2->lc);
+	lcs = bctbx_list_append(lcs, chloe3->lc);
 
 	linphone_core_set_user_agent(marie->lc, "full-presence-support", NULL);
 	linphone_core_set_user_agent(marie->lc, "full-presence-support-bypass", NULL);
@@ -1981,80 +1985,116 @@ static void notify_friend_capabilities(void) {
 	BC_ASSERT_TRUE(linphone_friend_has_capability(mPaulineFriend, LinphoneFriendCapabilityGroupChat));
 	BC_ASSERT_TRUE(linphone_friend_get_capabilities(mPaulineFriend) & LinphoneFriendCapabilityLimeX3dh);
 	BC_ASSERT_TRUE(linphone_friend_has_capability(mPaulineFriend, LinphoneFriendCapabilityLimeX3dh));
+	BC_ASSERT_TRUE(linphone_friend_has_capability_with_version(mPaulineFriend, LinphoneFriendCapabilityGroupChat, 1.1f));
+	BC_ASSERT_TRUE(linphone_friend_has_capability_with_version(mPaulineFriend, LinphoneFriendCapabilityLimeX3dh, 1.0f));
+	BC_ASSERT_TRUE(linphone_friend_get_capability_version(mPaulineFriend, LinphoneFriendCapabilityGroupChat) - 1.1f < 0.1f);
+	BC_ASSERT_TRUE(linphone_friend_get_capability_version(mPaulineFriend, LinphoneFriendCapabilityLimeX3dh) - 1.0f < 0.1f);
 
 	BC_ASSERT_TRUE(linphone_friend_get_capabilities(mLaureFriend) & LinphoneFriendCapabilityGroupChat);
 	BC_ASSERT_TRUE(linphone_friend_has_capability(mLaureFriend, LinphoneFriendCapabilityGroupChat));
 	BC_ASSERT_FALSE(linphone_friend_get_capabilities(mLaureFriend) & LinphoneFriendCapabilityLimeX3dh);
 	BC_ASSERT_FALSE(linphone_friend_has_capability(mLaureFriend, LinphoneFriendCapabilityLimeX3dh));
+	BC_ASSERT_TRUE(linphone_friend_has_capability_with_version(mLaureFriend, LinphoneFriendCapabilityGroupChat, 2.0f));
+	BC_ASSERT_FALSE(linphone_friend_has_capability_with_version(mLaureFriend, LinphoneFriendCapabilityLimeX3dh, 1.0f));
+	BC_ASSERT_TRUE(linphone_friend_get_capability_version(mLaureFriend, LinphoneFriendCapabilityGroupChat) - 2.0f < 0.1f);
+	BC_ASSERT_TRUE(linphone_friend_get_capability_version(mLaureFriend, LinphoneFriendCapabilityLimeX3dh) - (-1.0f) < 0.1f);
 
 	BC_ASSERT_TRUE(linphone_friend_get_capabilities(mChloeFriend) & LinphoneFriendCapabilityGroupChat);
 	BC_ASSERT_TRUE(linphone_friend_has_capability(mChloeFriend, LinphoneFriendCapabilityGroupChat));
 	BC_ASSERT_TRUE(linphone_friend_get_capabilities(mChloeFriend) & LinphoneFriendCapabilityLimeX3dh);
 	BC_ASSERT_TRUE(linphone_friend_has_capability(mChloeFriend, LinphoneFriendCapabilityLimeX3dh));
+	BC_ASSERT_TRUE(linphone_friend_has_capability_with_version(mChloeFriend, LinphoneFriendCapabilityGroupChat, 2.1f));
+	BC_ASSERT_TRUE(linphone_friend_has_capability_with_version(mChloeFriend, LinphoneFriendCapabilityLimeX3dh, 1.7f));
+	BC_ASSERT_TRUE(linphone_friend_get_capability_version(mChloeFriend, LinphoneFriendCapabilityGroupChat) - 2.1f < 0.1f);
+	BC_ASSERT_TRUE(linphone_friend_get_capability_version(mChloeFriend, LinphoneFriendCapabilityLimeX3dh) - 1.7f < 0.1f);
 
 	// Pauline's received presence
 	BC_ASSERT_FALSE(linphone_friend_get_capabilities(p1MarieFriend) & LinphoneFriendCapabilityGroupChat);
 	BC_ASSERT_FALSE(linphone_friend_has_capability(p1MarieFriend, LinphoneFriendCapabilityGroupChat));
 	BC_ASSERT_FALSE(linphone_friend_get_capabilities(p1MarieFriend) & LinphoneFriendCapabilityLimeX3dh);
 	BC_ASSERT_FALSE(linphone_friend_has_capability(p1MarieFriend, LinphoneFriendCapabilityLimeX3dh));
+	BC_ASSERT_FALSE(linphone_friend_has_capability_with_version(p1MarieFriend, LinphoneFriendCapabilityGroupChat, 1.0f));
+	BC_ASSERT_FALSE(linphone_friend_has_capability_with_version(p1MarieFriend, LinphoneFriendCapabilityLimeX3dh, 1.0f));
 
 	BC_ASSERT_TRUE(linphone_friend_get_capabilities(p1LaureFriend) & LinphoneFriendCapabilityGroupChat);
 	BC_ASSERT_TRUE(linphone_friend_has_capability(p1LaureFriend, LinphoneFriendCapabilityGroupChat));
 	BC_ASSERT_FALSE(linphone_friend_get_capabilities(p1LaureFriend) & LinphoneFriendCapabilityLimeX3dh);
 	BC_ASSERT_FALSE(linphone_friend_has_capability(p1LaureFriend, LinphoneFriendCapabilityLimeX3dh));
+	BC_ASSERT_TRUE(linphone_friend_has_capability_with_version(p1LaureFriend, LinphoneFriendCapabilityGroupChat, 2.0f));
+	BC_ASSERT_FALSE(linphone_friend_has_capability_with_version(p1LaureFriend, LinphoneFriendCapabilityLimeX3dh, 1.0f));
 
 	BC_ASSERT_TRUE(linphone_friend_get_capabilities(p1ChloeFriend) & LinphoneFriendCapabilityGroupChat);
 	BC_ASSERT_TRUE(linphone_friend_has_capability(p1ChloeFriend, LinphoneFriendCapabilityGroupChat));
 	BC_ASSERT_TRUE(linphone_friend_get_capabilities(p1ChloeFriend) & LinphoneFriendCapabilityLimeX3dh);
 	BC_ASSERT_TRUE(linphone_friend_has_capability(p1ChloeFriend, LinphoneFriendCapabilityLimeX3dh));
+	BC_ASSERT_TRUE(linphone_friend_has_capability_with_version(p1ChloeFriend, LinphoneFriendCapabilityGroupChat, 2.1f));
+	BC_ASSERT_TRUE(linphone_friend_has_capability_with_version(p1ChloeFriend, LinphoneFriendCapabilityLimeX3dh, 1.7f));
 
 	// Pauline2's received presence
 	BC_ASSERT_FALSE(linphone_friend_get_capabilities(p2MarieFriend) & LinphoneFriendCapabilityGroupChat);
 	BC_ASSERT_FALSE(linphone_friend_has_capability(p2MarieFriend, LinphoneFriendCapabilityGroupChat));
 	BC_ASSERT_FALSE(linphone_friend_get_capabilities(p2MarieFriend) & LinphoneFriendCapabilityLimeX3dh);
 	BC_ASSERT_FALSE(linphone_friend_has_capability(p2MarieFriend, LinphoneFriendCapabilityLimeX3dh));
+	BC_ASSERT_FALSE(linphone_friend_has_capability_with_version(p2MarieFriend, LinphoneFriendCapabilityGroupChat, 1.0f));
+	BC_ASSERT_FALSE(linphone_friend_has_capability_with_version(p2MarieFriend, LinphoneFriendCapabilityLimeX3dh, 1.0f));
 
 	BC_ASSERT_TRUE(linphone_friend_get_capabilities(p2LaureFriend) & LinphoneFriendCapabilityGroupChat);
 	BC_ASSERT_TRUE(linphone_friend_has_capability(p2LaureFriend, LinphoneFriendCapabilityGroupChat));
 	BC_ASSERT_FALSE(linphone_friend_get_capabilities(p2LaureFriend) & LinphoneFriendCapabilityLimeX3dh);
 	BC_ASSERT_FALSE(linphone_friend_has_capability(p2LaureFriend, LinphoneFriendCapabilityLimeX3dh));
+	BC_ASSERT_TRUE(linphone_friend_has_capability_with_version(p2LaureFriend, LinphoneFriendCapabilityGroupChat, 2.0f));
+	BC_ASSERT_FALSE(linphone_friend_has_capability_with_version(p2LaureFriend, LinphoneFriendCapabilityLimeX3dh, 1.0f));
 
 	BC_ASSERT_TRUE(linphone_friend_get_capabilities(p2ChloeFriend) & LinphoneFriendCapabilityGroupChat);
 	BC_ASSERT_TRUE(linphone_friend_has_capability(p2ChloeFriend, LinphoneFriendCapabilityGroupChat));
 	BC_ASSERT_TRUE(linphone_friend_get_capabilities(p2ChloeFriend) & LinphoneFriendCapabilityLimeX3dh);
 	BC_ASSERT_TRUE(linphone_friend_has_capability(p2ChloeFriend, LinphoneFriendCapabilityLimeX3dh));
+	BC_ASSERT_TRUE(linphone_friend_has_capability_with_version(p2ChloeFriend, LinphoneFriendCapabilityGroupChat, 2.1f));
+	BC_ASSERT_TRUE(linphone_friend_has_capability_with_version(p2ChloeFriend, LinphoneFriendCapabilityLimeX3dh, 1.7f));
 
 	// Laure's received presence
 	BC_ASSERT_FALSE(linphone_friend_get_capabilities(lMarieFriend) & LinphoneFriendCapabilityGroupChat);
 	BC_ASSERT_FALSE(linphone_friend_has_capability(lMarieFriend, LinphoneFriendCapabilityGroupChat));
 	BC_ASSERT_FALSE(linphone_friend_get_capabilities(lMarieFriend) & LinphoneFriendCapabilityLimeX3dh);
 	BC_ASSERT_FALSE(linphone_friend_has_capability(lMarieFriend, LinphoneFriendCapabilityLimeX3dh));
+	BC_ASSERT_FALSE(linphone_friend_has_capability_with_version(lMarieFriend, LinphoneFriendCapabilityGroupChat, 1.0f));
+	BC_ASSERT_FALSE(linphone_friend_has_capability_with_version(lMarieFriend, LinphoneFriendCapabilityLimeX3dh, 1.0f));
 
 	BC_ASSERT_TRUE(linphone_friend_get_capabilities(lPaulineFriend) & LinphoneFriendCapabilityGroupChat);
 	BC_ASSERT_TRUE(linphone_friend_has_capability(lPaulineFriend, LinphoneFriendCapabilityGroupChat));
 	BC_ASSERT_TRUE(linphone_friend_get_capabilities(lPaulineFriend) & LinphoneFriendCapabilityLimeX3dh);
 	BC_ASSERT_TRUE(linphone_friend_has_capability(lPaulineFriend, LinphoneFriendCapabilityLimeX3dh));
+	BC_ASSERT_TRUE(linphone_friend_has_capability_with_version(lPaulineFriend, LinphoneFriendCapabilityGroupChat, 1.1f));
+	BC_ASSERT_TRUE(linphone_friend_has_capability_with_version(lPaulineFriend, LinphoneFriendCapabilityLimeX3dh, 1.0f));
 
 	BC_ASSERT_TRUE(linphone_friend_get_capabilities(lChloeFriend) & LinphoneFriendCapabilityGroupChat);
 	BC_ASSERT_TRUE(linphone_friend_has_capability(lChloeFriend, LinphoneFriendCapabilityGroupChat));
 	BC_ASSERT_TRUE(linphone_friend_get_capabilities(lChloeFriend) & LinphoneFriendCapabilityLimeX3dh);
 	BC_ASSERT_TRUE(linphone_friend_has_capability(lChloeFriend, LinphoneFriendCapabilityLimeX3dh));
+	BC_ASSERT_TRUE(linphone_friend_has_capability_with_version(lChloeFriend, LinphoneFriendCapabilityGroupChat, 2.1f));
+	BC_ASSERT_TRUE(linphone_friend_has_capability_with_version(lChloeFriend, LinphoneFriendCapabilityLimeX3dh, 1.7f));
 
 	// Chloe's received presence
 	BC_ASSERT_FALSE(linphone_friend_get_capabilities(cMarieFriend) & LinphoneFriendCapabilityGroupChat);
 	BC_ASSERT_FALSE(linphone_friend_has_capability(cMarieFriend, LinphoneFriendCapabilityGroupChat));
 	BC_ASSERT_FALSE(linphone_friend_get_capabilities(cMarieFriend) & LinphoneFriendCapabilityLimeX3dh);
 	BC_ASSERT_FALSE(linphone_friend_has_capability(cMarieFriend, LinphoneFriendCapabilityLimeX3dh));
+	BC_ASSERT_FALSE(linphone_friend_has_capability_with_version(cMarieFriend, LinphoneFriendCapabilityGroupChat, 1.0f));
+	BC_ASSERT_FALSE(linphone_friend_has_capability_with_version(cMarieFriend, LinphoneFriendCapabilityLimeX3dh, 1.0f));
 
 	BC_ASSERT_TRUE(linphone_friend_get_capabilities(cPaulineFriend) & LinphoneFriendCapabilityGroupChat);
 	BC_ASSERT_TRUE(linphone_friend_has_capability(cPaulineFriend, LinphoneFriendCapabilityGroupChat));
 	BC_ASSERT_TRUE(linphone_friend_get_capabilities(cPaulineFriend) & LinphoneFriendCapabilityLimeX3dh);
 	BC_ASSERT_TRUE(linphone_friend_has_capability(cPaulineFriend, LinphoneFriendCapabilityLimeX3dh));
+	BC_ASSERT_TRUE(linphone_friend_has_capability_with_version(cPaulineFriend, LinphoneFriendCapabilityGroupChat, 1.1f));
+	BC_ASSERT_TRUE(linphone_friend_has_capability_with_version(cPaulineFriend, LinphoneFriendCapabilityLimeX3dh, 1.0f));
 
 	BC_ASSERT_TRUE(linphone_friend_get_capabilities(cLaureFriend) & LinphoneFriendCapabilityGroupChat);
 	BC_ASSERT_TRUE(linphone_friend_has_capability(cLaureFriend, LinphoneFriendCapabilityGroupChat));
 	BC_ASSERT_FALSE(linphone_friend_get_capabilities(cLaureFriend) & LinphoneFriendCapabilityLimeX3dh);
 	BC_ASSERT_FALSE(linphone_friend_has_capability(cLaureFriend, LinphoneFriendCapabilityLimeX3dh));
+	BC_ASSERT_TRUE(linphone_friend_has_capability_with_version(cLaureFriend, LinphoneFriendCapabilityGroupChat, 2.0f));
+	BC_ASSERT_FALSE(linphone_friend_has_capability_with_version(cLaureFriend, LinphoneFriendCapabilityLimeX3dh, 1.0f));
 
 	linphone_friend_unref(mPaulineFriend);
 	linphone_friend_unref(mLaureFriend);
@@ -2094,6 +2134,9 @@ static void notify_friend_capabilities(void) {
 	linphone_core_manager_stop(chloe2);
 	linphone_core_manager_destroy(chloe2);
 
+	linphone_core_manager_stop(chloe3);
+	linphone_core_manager_destroy(chloe3);
+
 	bctbx_list_free(lcs);
 }