diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt
index de76e76a..de19f813 100644
--- a/app/CMakeLists.txt
+++ b/app/CMakeLists.txt
@@ -36,6 +36,7 @@ target_sources(app PRIVATE src/events/keycode_state_changed.c)
 target_sources(app PRIVATE src/events/modifiers_state_changed.c)
 target_sources(app PRIVATE src/events/sensor_event.c)
 target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/events/ble_active_profile_changed.c)
+target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/events/battery_state_changed.c)
 target_sources_ifdef(CONFIG_USB app PRIVATE src/events/usb_conn_state_changed.c)
 if (NOT CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL)
   target_sources(app PRIVATE src/behaviors/behavior_key_press.c)
diff --git a/app/include/zmk/events/battery-state-changed.h b/app/include/zmk/events/battery-state-changed.h
new file mode 100644
index 00000000..a5901708
--- /dev/null
+++ b/app/include/zmk/events/battery-state-changed.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2020 The ZMK Contributors
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#pragma once
+
+#include <zephyr.h>
+#include <zmk/event-manager.h>
+
+struct battery_state_changed {
+    struct zmk_event_header header;
+    // TODO: Other battery channels
+    u8_t state_of_charge;
+};
+
+ZMK_EVENT_DECLARE(battery_state_changed);
\ No newline at end of file
diff --git a/app/src/battery.c b/app/src/battery.c
index 9496570c..e78b2fba 100644
--- a/app/src/battery.c
+++ b/app/src/battery.c
@@ -14,6 +14,9 @@
 
 LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
 
+#include <zmk/event-manager.h>
+#include <zmk/events/battery-state-changed.h>
+
 struct device *battery;
 
 static int zmk_battery_update(struct device *battery) {
@@ -35,7 +38,16 @@ static int zmk_battery_update(struct device *battery) {
 
     LOG_DBG("Setting BAS GATT battery level to %d.", state_of_charge.val1);
 
-    return bt_gatt_bas_set_battery_level(state_of_charge.val1);
+    rc = bt_gatt_bas_set_battery_level(state_of_charge.val1);
+
+    if (rc != 0) {
+        LOG_WRN("Failed to set BAS GATT battery level (err %d)", rc);
+        return rc;
+    }
+
+    struct battery_state_changed *ev = new_battery_state_changed();
+    ev->state_of_charge = state_of_charge.val1;
+    return ZMK_EVENT_RAISE(ev);
 }
 
 static void zmk_battery_work(struct k_work *work) {
diff --git a/app/src/events/battery_state_changed.c b/app/src/events/battery_state_changed.c
new file mode 100644
index 00000000..4b937e34
--- /dev/null
+++ b/app/src/events/battery_state_changed.c
@@ -0,0 +1,10 @@
+/*
+ * Copyright (c) 2020 The ZMK Contributors
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#include <kernel.h>
+#include <zmk/events/battery-state-changed.h>
+
+ZMK_EVENT_IMPL(battery_state_changed);
\ No newline at end of file