diff --git a/epicardium/main.c b/epicardium/main.c
index 84abf8d9ae37d936ef2535204575e986cec7b274..cd989f4cf101b5754bbdaddd757947a0de51120a 100644
--- a/epicardium/main.c
+++ b/epicardium/main.c
@@ -31,21 +31,6 @@ TaskHandle_t dispatcher_task_id;
 
 void vBleTask(void *pvParameters);
 
-/*
- * API dispatcher task.  This task will sleep until an API call is issued and
- * then wake up to dispatch it.
- */
-void vApiDispatcher(void *pvParameters)
-{
-	LOG_DEBUG("dispatcher", "Ready.");
-	while (1) {
-		if (api_dispatcher_poll()) {
-			api_dispatcher_exec();
-		}
-		ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
-	}
-}
-
 int main(void)
 {
 	LOG_INFO("startup", "Epicardium startup ...");
diff --git a/epicardium/modules/dispatcher.c b/epicardium/modules/dispatcher.c
new file mode 100644
index 0000000000000000000000000000000000000000..60f1c1f818dcd8f41ddeb1f4b4a11b2e2400e938
--- /dev/null
+++ b/epicardium/modules/dispatcher.c
@@ -0,0 +1,34 @@
+#include "modules/log.h"
+
+#include "api/dispatcher.h"
+
+#include "FreeRTOS.h"
+#include "task.h"
+#include "semphr.h"
+
+#define TIMEOUT pdMS_TO_TICKS(2000)
+
+static StaticSemaphore_t api_mutex_data;
+SemaphoreHandle_t api_mutex = NULL;
+
+/*
+ * API dispatcher task.  This task will sleep until an API call is issued and
+ * then wake up to dispatch it.
+ */
+void vApiDispatcher(void *pvParameters)
+{
+	api_mutex = xSemaphoreCreateMutexStatic(&api_mutex_data);
+
+	LOG_DEBUG("dispatcher", "Ready.");
+	while (1) {
+		if (api_dispatcher_poll()) {
+			if (xSemaphoreTake(api_mutex, TIMEOUT) != pdTRUE) {
+				LOG_ERR("dispatcher", "API mutex blocked");
+				continue;
+			}
+			api_dispatcher_exec();
+			xSemaphoreGive(api_mutex);
+		}
+		ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
+	}
+}
diff --git a/epicardium/modules/meson.build b/epicardium/modules/meson.build
index b3cf4eb2ee679963768a76a54834208de0a30ad8..9a70957d0c4b70083c92c5386ca5edd3f513102c 100644
--- a/epicardium/modules/meson.build
+++ b/epicardium/modules/meson.build
@@ -1,4 +1,5 @@
 module_sources = files(
+  'dispatcher.c',
   'display.c',
   'fileops.c',
   'leds.c',
diff --git a/epicardium/modules/modules.h b/epicardium/modules/modules.h
index 4a7bc2557aea29d2d79a96e0c00cefc786f917f5..ea2a313f4970e1d607be99adc9ac843aefcfdea5 100644
--- a/epicardium/modules/modules.h
+++ b/epicardium/modules/modules.h
@@ -1,12 +1,19 @@
 #ifndef MODULES_H
 #define MODULES_H
 
+#include "FreeRTOS.h"
+#include "semphr.h"
+
 #include <stdint.h>
 
+/* ---------- Dispatcher --------------------------------------------------- */
+void vApiDispatcher(void *pvParameters);
+extern SemaphoreHandle_t api_mutex;
+extern TaskHandle_t dispatcher_task_id;
+
 /* ---------- Serial ------------------------------------------------------- */
 #define SERIAL_READ_BUFFER_SIZE 128
 void vSerialTask(void *pvParameters);
-
 void serial_enqueue_char(char chr);
 
 /* ---------- PMIC --------------------------------------------------------- */