diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c
index cc4b300c417e5b8b3272f226b81e963ad9838a18..c8f980e26c3ea26f3146692cbacf471af5f97343 100644
--- a/coreapi/linphonecore.c
+++ b/coreapi/linphonecore.c
@@ -733,12 +733,31 @@ void linphone_core_cbs_set_account_registration_state_changed(LinphoneCoreCbs *c
                                                               LinphoneCoreCbsAccountRegistrationStateChangedCb cb) {
 	cbs->vtable->account_registration_state_changed = cb;
 }
+
 void linphone_core_cbs_set_new_alert_triggered(LinphoneCoreCbs *cbs, LinphoneCoreCbsNewAlertTriggeredCb alert_cb) {
 	cbs->vtable->new_alert_triggered = alert_cb;
 }
+
 LinphoneCoreCbsNewAlertTriggeredCb linphone_core_cbs_get_new_alert_triggered(LinphoneCoreCbs *cbs) {
 	return cbs->vtable->new_alert_triggered;
 }
+
+void linphone_core_cbs_set_default_account_changed(LinphoneCoreCbs *cbs, LinphoneCoreCbsDefaultAccountChangedCb cb) {
+	cbs->vtable->default_account_changed = cb;
+}
+
+LinphoneCoreCbsDefaultAccountChangedCb linphone_core_cbs_get_default_account_changed(LinphoneCoreCbs *cbs) {
+	return cbs->vtable->default_account_changed;
+}
+
+void linphone_core_cbs_set_new_account_added(LinphoneCoreCbs *cbs, LinphoneCoreCbsNewAccountAddedCb cb) {
+	cbs->vtable->new_account_added = cb;
+}
+
+LinphoneCoreCbsNewAccountAddedCb linphone_core_cbs_get_new_account_added(LinphoneCoreCbs *cbs) {
+	return cbs->vtable->new_account_added;
+}
+
 void lc_callback_obj_init(LCCallbackObj *obj, LinphoneCoreCbFunc func, void *ud) {
 	obj->_func = func;
 	obj->_user_data = ud;
diff --git a/coreapi/private_functions.h b/coreapi/private_functions.h
index 01ff200a329857205fb37d8d392bb606e4bc5f0c..c132c741e75a39f7a6d820d5d6f9131adcaa624a 100644
--- a/coreapi/private_functions.h
+++ b/coreapi/private_functions.h
@@ -886,6 +886,8 @@ void linphone_core_notify_audio_device_changed(LinphoneCore *lc, LinphoneAudioDe
 void linphone_core_notify_audio_devices_list_updated(LinphoneCore *lc);
 void linphone_core_notify_conference_info_received(LinphoneCore *lc, const LinphoneConferenceInfo *conference_info);
 void linphone_core_notify_push_notification_received(LinphoneCore *lc, const char *payload);
+void linphone_core_notify_default_account_changed(LinphoneCore *lc, LinphoneAccount *account);
+void linphone_core_notify_new_account_added(LinphoneCore *lc, LinphoneAccount *account);
 /*
  * return true if at least a registered vtable has a cb for dtmf received*/
 bool_t linphone_core_dtmf_received_has_listener(const LinphoneCore *lc);
diff --git a/coreapi/proxy.c b/coreapi/proxy.c
index 79eaf4c5cb5c1bdb1aa1f607e929fbfef785824d..31b629b60c0669e7b7255af911263b2919c68343 100644
--- a/coreapi/proxy.c
+++ b/coreapi/proxy.c
@@ -666,6 +666,9 @@ LinphoneStatus linphone_core_add_proxy_config(LinphoneCore *lc, LinphoneProxyCon
 	lc->sip_conf.proxies = bctbx_list_append(lc->sip_conf.proxies, (void *)linphone_proxy_config_ref(cfg));
 	lc->sip_conf.accounts = bctbx_list_append(lc->sip_conf.accounts, (void *)linphone_account_ref(cfg->account));
 	linphone_proxy_config_apply(cfg, lc);
+
+	linphone_core_notify_new_account_added(lc, cfg->account);
+
 	return 0;
 }
 
@@ -831,6 +834,9 @@ LinphoneStatus linphone_core_add_account(LinphoneCore *lc, LinphoneAccount *acco
 	}
 
 	Account::toCpp(account)->apply(lc);
+
+	linphone_core_notify_new_account_added(lc, account);
+
 	return 0;
 }
 
@@ -936,6 +942,12 @@ void linphone_core_set_default_account(LinphoneCore *lc, LinphoneAccount *accoun
 			return;
 		}
 	}
+
+	if (lc->default_account == account) {
+		ms_warning("This account is already the default one, skipping.");
+		return;
+	}
+
 	lc->default_account = account;
 	lc->default_proxy = account ? Account::toCpp(account)->getConfig() : NULL;
 	if (linphone_core_ready(lc)) {
@@ -944,6 +956,8 @@ void linphone_core_set_default_account(LinphoneCore *lc, LinphoneAccount *accoun
 		 * different dial prefix */
 		linphone_core_invalidate_friends_maps(lc);
 	}
+
+	linphone_core_notify_default_account_changed(lc, account);
 }
 
 void linphone_proxy_config_write_to_config_file(LpConfig *config, LinphoneProxyConfig *cfg, int index) {
diff --git a/coreapi/vtables.c b/coreapi/vtables.c
index f51b5798d0279d442ba97fd6782bea37405b5c12..d5b3e5b018ed19e593f854cd4241142165f15947 100644
--- a/coreapi/vtables.c
+++ b/coreapi/vtables.c
@@ -533,6 +533,16 @@ void linphone_core_notify_push_notification_received(LinphoneCore *lc, const cha
 	cleanup_dead_vtable_refs(lc);
 }
 
+void linphone_core_notify_default_account_changed(LinphoneCore *lc, LinphoneAccount *account) {
+	NOTIFY_IF_EXIST(default_account_changed, lc, account);
+	cleanup_dead_vtable_refs(lc);
+}
+
+void linphone_core_notify_new_account_added(LinphoneCore *lc, LinphoneAccount *account) {
+	NOTIFY_IF_EXIST(new_account_added, lc, account);
+	cleanup_dead_vtable_refs(lc);
+}
+
 static VTableReference *v_table_reference_new(LinphoneCoreCbs *cbs, bool_t internal) {
 	VTableReference *ref = ms_new0(VTableReference, 1);
 	ref->valid = TRUE;
diff --git a/include/linphone/callbacks.h b/include/linphone/callbacks.h
index 98d87f6979de8b08781d2b37b94a650be45fc206..925b1a9ac1b27f5700802be816e13d35690de8a4 100644
--- a/include/linphone/callbacks.h
+++ b/include/linphone/callbacks.h
@@ -266,6 +266,22 @@ typedef void (*LinphoneCoreCbsReactionRemovedCb)(LinphoneCore *core,
                                                  LinphoneChatMessage *message,
                                                  const LinphoneAddress *address);
 
+/**
+ * Default account changed callback prototype
+ * @param core #LinphoneCore object @notnil
+ * @param account #LinphoneAccount object that has been set as the default account, probably by calling
+ * linphone_core_set_default_account(). @notnil
+ */
+typedef void (*LinphoneCoreCbsDefaultAccountChangedCb)(LinphoneCore *core, LinphoneAccount *account);
+
+/**
+ * New account added callback prototype
+ * @param core #LinphoneCore object @notnil
+ * @param account #LinphoneAccount object that has been added to the Core using linphone_core_add_account() for example.
+ * @notnil
+ */
+typedef void (*LinphoneCoreCbsNewAccountAddedCb)(LinphoneCore *core, LinphoneAccount *account);
+
 /**
  * Chat messages callback prototype.
  * Only called when aggregation is enabled (aka [sip] chat_messages_aggregation == 1 or using
diff --git a/include/linphone/core.h b/include/linphone/core.h
index 67851b5d9cc3331a4beda07ffa306f4f12b38ab1..69914e6e35ce5272ff7d2cee9807db865773f9fa 100644
--- a/include/linphone/core.h
+++ b/include/linphone/core.h
@@ -306,6 +306,8 @@ typedef struct _LinphoneCoreVTable {
 	LinphoneCoreCbsNewMessageReactionCb new_message_reaction;
 	LinphoneCoreCbsReactionRemovedCb reaction_removed;
 	LinphoneCoreCbsReactionRemovedPrivateCb reaction_removed_private;
+	LinphoneCoreCbsDefaultAccountChangedCb default_account_changed;
+	LinphoneCoreCbsNewAccountAddedCb new_account_added;
 	void *user_data; /**<User data associated with the above callbacks */
 } LinphoneCoreVTable;
 
@@ -1286,7 +1288,7 @@ LINPHONE_PUBLIC LinphoneCoreCbsChatRoomExhumedCb linphone_core_cbs_get_chat_room
  */
 LINPHONE_PUBLIC void linphone_core_cbs_set_chat_room_exhumed(LinphoneCoreCbs *cbs, LinphoneCoreCbsChatRoomExhumedCb cb);
 
-/*
+/**
  * Set the account registration state changed callback.
  * @param cbs #LinphoneCoreCbs object. @notnil
  * @param cb The account registration state changed callback to be used.
@@ -1294,6 +1296,35 @@ LINPHONE_PUBLIC void linphone_core_cbs_set_chat_room_exhumed(LinphoneCoreCbs *cb
 LINPHONE_PUBLIC void
 linphone_core_cbs_set_account_registration_state_changed(LinphoneCoreCbs *cbs,
                                                          LinphoneCoreCbsAccountRegistrationStateChangedCb cb);
+/**
+ * Sets the default account changed callback.
+ * @param cbs #LinphoneCoreCbs object. @notnil
+ * @param cb The default account changed callback to be used.
+ */
+LINPHONE_PUBLIC void linphone_core_cbs_set_default_account_changed(LinphoneCoreCbs *cbs,
+                                                                   LinphoneCoreCbsDefaultAccountChangedCb cb);
+
+/**
+ * Gets the default account changed callback.
+ * @param cbs #LinphoneCoreCbs object. @notnil
+ * @return The default account changed callback that will be triggered.
+ */
+LINPHONE_PUBLIC LinphoneCoreCbsDefaultAccountChangedCb
+linphone_core_cbs_get_default_account_changed(LinphoneCoreCbs *cbs);
+
+/**
+ * Sets the new account added callback.
+ * @param cbs #LinphoneCoreCbs object. @notnil
+ * @param cb The new account added callback to be used.
+ */
+LINPHONE_PUBLIC void linphone_core_cbs_set_new_account_added(LinphoneCoreCbs *cbs, LinphoneCoreCbsNewAccountAddedCb cb);
+
+/**
+ * Gets the new account added callback.
+ * @param cbs #LinphoneCoreCbs object. @notnil
+ * @return The new account added callback that will be triggered.
+ */
+LINPHONE_PUBLIC LinphoneCoreCbsNewAccountAddedCb linphone_core_cbs_get_new_account_added(LinphoneCoreCbs *cbs);
 
 /**
  * Get the account registration state changed callback.
diff --git a/tester/call_single_tester.c b/tester/call_single_tester.c
index af55b28f27394a7f1f899c065dc22aa13cccd3fb..d98d07b86c9c68c83263d7016c3b0bd576c0af5a 100644
--- a/tester/call_single_tester.c
+++ b/tester/call_single_tester.c
@@ -7291,7 +7291,9 @@ static void call_rejected_with_403(void) {
 	linphone_account_params_set_register_enabled(accountParams, TRUE);
 	LinphoneAccount *account = linphone_core_create_account(mgr->lc, accountParams);
 	linphone_core_add_account(mgr->lc, account);
+	BC_ASSERT_TRUE(wait_for(mgr->lc, mgr->lc, &mgr->stat.number_of_LinphoneNewAccountAdded, 1));
 	linphone_core_set_default_account(mgr->lc, account);
+	BC_ASSERT_TRUE(wait_for(mgr->lc, mgr->lc, &mgr->stat.number_of_LinphoneDefaultAccountChanged, 1));
 	linphone_core_iterate(mgr->lc);
 
 	LinphoneCall *call = linphone_core_invite(mgr->lc, "sip:nimportequoi@sip.example.org;transport=TLS");
diff --git a/tester/liblinphone_tester.h b/tester/liblinphone_tester.h
index a9705b971ab76ae13d3440add4fcce15ff7331aa..393c5e00f80f1e847f7a8907288301cec2c70015 100644
--- a/tester/liblinphone_tester.h
+++ b/tester/liblinphone_tester.h
@@ -260,6 +260,8 @@ typedef struct _stats {
 	int number_of_LinphoneRegistrationFailed;
 	int number_of_auth_info_requested;
 	int number_of_LinphoneChatRoomExhumed;
+	int number_of_LinphoneNewAccountAdded;
+	int number_of_LinphoneDefaultAccountChanged;
 
 	int number_of_LinphoneCallCreated;
 	int number_of_LinphoneCallIncomingReceived;
diff --git a/tester/tester.c b/tester/tester.c
index f0ec30c0318f785456990108b37e4aacb51311a6..67928bba1a6e0e930363169dcc7bae66275b25ff 100644
--- a/tester/tester.c
+++ b/tester/tester.c
@@ -770,6 +770,18 @@ void core_conference_state_changed(BCTBX_UNUSED(LinphoneCore *core),
 	}
 }
 
+void default_account_changed(LinphoneCore *core, LinphoneAccount *account) {
+	BC_ASSERT_PTR_NOT_NULL(account);
+	LinphoneCoreManager *manager = (LinphoneCoreManager *)linphone_core_get_user_data(core);
+	manager->stat.number_of_LinphoneDefaultAccountChanged++;
+}
+
+void new_account_added(LinphoneCore *core, LinphoneAccount *account) {
+	BC_ASSERT_PTR_NOT_NULL(account);
+	LinphoneCoreManager *manager = (LinphoneCoreManager *)linphone_core_get_user_data(core);
+	manager->stat.number_of_LinphoneNewAccountAdded++;
+}
+
 LinphoneStatus add_participant_to_local_conference_through_invite(bctbx_list_t *lcs,
                                                                   LinphoneCoreManager *conf_mgr,
                                                                   bctbx_list_t *participants,
@@ -2440,6 +2452,8 @@ void linphone_core_manager_init2(LinphoneCoreManager *mgr, BCTBX_UNUSED(const ch
 	linphone_core_cbs_set_audio_devices_list_updated(mgr->cbs, audio_devices_list_updated);
 	linphone_core_cbs_set_imee_user_registration(mgr->cbs, liblinphone_tester_x3dh_user_created);
 	linphone_core_cbs_set_conference_state_changed(mgr->cbs, core_conference_state_changed);
+	linphone_core_cbs_set_default_account_changed(mgr->cbs, default_account_changed);
+	linphone_core_cbs_set_new_account_added(mgr->cbs, new_account_added);
 
 	mgr->phone_alias = phone_alias ? ms_strdup(phone_alias) : NULL;