diff --git a/lib/ziti-tunnel-cbs/include/ziti/ziti_tunnel_cbs.h b/lib/ziti-tunnel-cbs/include/ziti/ziti_tunnel_cbs.h
index 3b12ac5c..0aaf3917 100644
--- a/lib/ziti-tunnel-cbs/include/ziti/ziti_tunnel_cbs.h
+++ b/lib/ziti-tunnel-cbs/include/ziti/ziti_tunnel_cbs.h
@@ -236,7 +236,7 @@ XX(ContextEvent, __VA_ARGS__) \
 XX(ServiceEvent, __VA_ARGS__)  \
 XX(MFAEvent, __VA_ARGS__)      \
 XX(MFAStatusEvent, __VA_ARGS__) \
-XX(APIEvent, __VA_ARGS__)      \
+XX(ConfigEvent, __VA_ARGS__)      \
 XX(ExtJWTEvent, __VA_ARGS__)
 
 DECLARE_ENUM(TunnelEvent, TUNNEL_EVENTS)
@@ -279,12 +279,10 @@ XX(provisioning_url, model_string, none, provisioning_url, __VA_ARGS__) \
 XX(recovery_codes, model_string, array, recovery_codes, __VA_ARGS__) \
 XX(code, model_number, none, code, __VA_ARGS__)
 
-#define ZTX_API_EVENT_MODEL(XX, ...)  \
+#define CONFIG_EVENT_MODEL(XX, ...)  \
 BASE_EVENT_MODEL(XX, __VA_ARGS__)     \
 XX(config_json, json, none, config, __VA_ARGS__) \
-XX(new_ctrl_address, model_string, none, new_ctrl_address, __VA_ARGS__) \
-XX(new_ca_bundle, model_string, none, new_ca_bundle, __VA_ARGS__)
-
+XX(identity_name, model_string, none, identity_name, __VA_ARGS__)
 
 #define EXT_JWT_PROVIDER(XX, ...) \
 XX(name, model_string, none, name, __VA_ARGS__) \
@@ -299,7 +297,7 @@ DECLARE_MODEL(base_event, BASE_EVENT_MODEL)
 DECLARE_MODEL(ziti_ctx_event, ZTX_EVENT_MODEL)
 DECLARE_MODEL(mfa_event, MFA_EVENT_MODEL)
 DECLARE_MODEL(service_event, ZTX_SVC_EVENT_MODEL)
-DECLARE_MODEL(api_event, ZTX_API_EVENT_MODEL)
+DECLARE_MODEL(config_event, CONFIG_EVENT_MODEL)
 
 DECLARE_MODEL(jwt_provider, EXT_JWT_PROVIDER)
 DECLARE_MODEL(ext_signer_event, EXT_SIGNER_EVENT_MODEL)
diff --git a/lib/ziti-tunnel-cbs/ziti_tunnel_ctrl.c b/lib/ziti-tunnel-cbs/ziti_tunnel_ctrl.c
index 41cd4a12..f402e8e8 100644
--- a/lib/ziti-tunnel-cbs/ziti_tunnel_ctrl.c
+++ b/lib/ziti-tunnel-cbs/ziti_tunnel_ctrl.c
@@ -1133,12 +1133,11 @@ static void on_ziti_event(ziti_context ztx, const ziti_event_t *event) {
         case ZitiConfigEvent: {
             if (event->cfg.config) {
                 char *cfg_json = ziti_config_to_json(event->cfg.config, 0, NULL);
-                api_event ev = {0};
-                ev.event_type = TunnelEvents.APIEvent;
+                config_event ev = {0};
+                ev.event_type = TunnelEvents.ConfigEvent;
                 ev.identifier = instance->identifier;
-                ev.new_ctrl_address = event->cfg.config->controller_url;
-                ev.new_ca_bundle = event->cfg.config->id.ca;
                 ev.config_json = cfg_json;
+                ev.identity_name = event->cfg.identity_name;
                 CMD_CTX.on_event((const base_event *) &ev);
                 free(cfg_json);
             } else {
@@ -1529,7 +1528,7 @@ IMPL_MODEL(base_event, BASE_EVENT_MODEL)
 IMPL_MODEL(ziti_ctx_event, ZTX_EVENT_MODEL)
 IMPL_MODEL(mfa_event, MFA_EVENT_MODEL)
 IMPL_MODEL(service_event, ZTX_SVC_EVENT_MODEL)
-IMPL_MODEL(api_event, ZTX_API_EVENT_MODEL)
+IMPL_MODEL(config_event, CONFIG_EVENT_MODEL)
 IMPL_MODEL(tunnel_command_inline, TUNNEL_CMD_INLINE)
 
 IMPL_MODEL(jwt_provider, EXT_JWT_PROVIDER)
diff --git a/programs/ziti-edge-tunnel/include/model/dtos.h b/programs/ziti-edge-tunnel/include/model/dtos.h
index 0ac66686..72a18d04 100644
--- a/programs/ziti-edge-tunnel/include/model/dtos.h
+++ b/programs/ziti-edge-tunnel/include/model/dtos.h
@@ -25,6 +25,7 @@ extern "C" {
 
 #define TUNNEL_CONFIG(XX, ...) \
 XX(ZtAPI, model_string, none, ztAPI, __VA_ARGS__) \
+XX(ZtAPIs, model_string, array, ztAPIs, __VA_ARGS__) \
 XX(ConfigTypes, model_string, array, ConfigTypes, __VA_ARGS__)
 
 #define TUNNEL_METRICS(XX, ...) \
diff --git a/programs/ziti-edge-tunnel/ziti-edge-tunnel.c b/programs/ziti-edge-tunnel/ziti-edge-tunnel.c
index b2996210..729f102d 100644
--- a/programs/ziti-edge-tunnel/ziti-edge-tunnel.c
+++ b/programs/ziti-edge-tunnel/ziti-edge-tunnel.c
@@ -742,35 +742,54 @@ static void on_event(const base_event *ev) {
             break;
         }
 
-        case TunnelEvent_APIEvent: {
-            const api_event *api_ev = (api_event *) ev;
-            ZITI_LOG(INFO, "ztx[%s] API Event with controller address : %s", api_ev->identifier, api_ev->new_ctrl_address);
+        case TunnelEvent_ConfigEvent: {
+            const config_event *config_ev = (config_event *) ev;
+            ZITI_LOG(INFO, "ztx[%s] Config Event", config_ev->identifier);
             if (id == NULL) {
                 break;
             }
 
-            update_identity_config(global_loop_ref, api_ev->identifier, api_ev->config_json);
+            update_identity_config(global_loop_ref, config_ev->identifier, config_ev->config_json);
+            ziti_config zc;
+            int rc = parse_ziti_config(&zc, config_ev->config_json, strlen(config_ev->config_json));
+            if (rc < 0) {
+                ZITI_LOG(ERROR, "unable to parse '%s' as ziti_config", config_ev->config_json);
+                break;
+            }
+
             identity_event id_event = {0};
             id_event.Op = strdup("identity");
             id_event.Action = strdup(event_name(event_updated));
             id_event.Id = id;
-            if (id_event.Id->FingerPrint) {
-                id_event.Fingerprint = strdup(id_event.Id->FingerPrint);
+            if (id->FingerPrint) {
+                id_event.Fingerprint = strdup(id->FingerPrint);
             }
-            id_event.Id->Loaded = true;
-            bool updated = false;
-            if (api_ev->new_ctrl_address) {
-                if (id_event.Id->Config == NULL) {
-                    id_event.Id->Config = calloc(1, sizeof(tunnel_config));
-                    id_event.Id->Config->ZtAPI = strdup(api_ev->new_ctrl_address);
-                    updated = true;
-                } else if (id_event.Id->Config->ZtAPI != NULL && strcmp(id_event.Id->Config->ZtAPI, api_ev->new_ctrl_address) != 0) {
-                    free((char*)id_event.Id->Config->ZtAPI);
-                    id_event.Id->Config->ZtAPI = strdup(api_ev->new_ctrl_address);
-                    updated = true;
-                }
+            id->Loaded = true;
+
+            if (id->Config == NULL) {
+                id->Config = calloc(1, sizeof(tunnel_config));
             }
-            if (updated) {
+
+            free((char *) id->Config->ZtAPI);
+            id->Config->ZtAPI = strdup(zc.controller_url);
+
+            // free previous controllers
+            int i;
+            for (i = 0; id->Config->ZtAPIs != NULL && id->Config->ZtAPIs[i] != NULL; i++) {
+                free((char *) id->Config->ZtAPIs[i]);
+            }
+            free(id->Config->ZtAPIs);
+
+            // copy new controllers into the identity
+            size_t num_ctrls = model_list_size(&zc.controllers);
+            id->Config->ZtAPIs = calloc(num_ctrls + 1, sizeof(model_string));
+            i = 0;
+            model_string ctrl;
+            MODEL_LIST_FOREACH(ctrl, zc.controllers) {
+                id->Config->ZtAPIs[i++] = strdup(ctrl);
+            }
+
+            if (true /* for now assume something was updated or else this event would not have arrived */) {
                 send_events_message(&id_event, (to_json_fn) identity_event_to_json, true);
             }
             id_event.Id = NULL;