Add missing scheduled_events.md file
diff --git a/source/docs/2.4.0/celix/documents/scheduled_events.md b/source/docs/2.4.0/celix/documents/scheduled_events.md
new file mode 100644
index 0000000..988c734
--- /dev/null
+++ b/source/docs/2.4.0/celix/documents/scheduled_events.md
@@ -0,0 +1,136 @@
+---
+title: Apache Celix Events
+---
+
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+   
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+# Apache Celix Scheduled Events
+
+Apache Celix provides supports to schedule events on the Apache Celix Event Thread. This allows users to 
+reuse the existing Apache Celix events thread to do tasks on the event thread.
+
+Scheduled events will be called repeatedly using a provided interval or once if 
+only an initial delay is provided. For the interval time, a monotonic clock is used.
+
+The event callback should be relatively fast, and the scheduled event interval should be relatively high; otherwise, 
+the framework event queue will be blocked, and the framework will not function properly. 
+Network IO should not be done in the event callback, but instead, a separate thread should be used for this.
+
+## Scheduling an Event
+
+To schedule an event in the Apache Celix framework, use the `celix_bundleContext_scheduleEvent` C function or 
+`celix::BundleContext::scheduleEvent` C++ method. For C, an options struct is used to configure the scheduled event, 
+and for C++, a builder pattern is used to configure the scheduled event.
+
+### C Example
+
+```c
+#include <stdio.h>
+#include <celix_bundle_activator.h>
+
+typedef struct schedule_events_bundle_activator_data {
+    celix_bundle_context_t* ctx;
+    long scheduledEventId;
+} schedule_events_bundle_activator_data_t;
+
+void scheduleEventsBundle_oneShot(void* data) {
+    schedule_events_bundle_activator_data_t* act = data;
+    celix_bundleContext_log(act->ctx, CELIX_LOG_LEVEL_INFO, "One shot scheduled event fired");
+}
+
+void scheduleEventsBundle_process(void* data) {
+    schedule_events_bundle_activator_data_t* act = data;
+    celix_bundleContext_log(act->ctx, CELIX_LOG_LEVEL_INFO, "Recurring scheduled event fired");
+}
+
+static celix_status_t scheduleEventsBundle_start(schedule_events_bundle_activator_data_t *data, celix_bundle_context_t *ctx) {
+    data->ctx = ctx;
+
+    //schedule recurring event
+    {
+        celix_scheduled_event_options_t opts = CELIX_EMPTY_SCHEDULED_EVENT_OPTIONS;
+        opts.name = "recurring scheduled event example";
+        opts.initialDelayInSeconds = 0.1;
+        opts.intervalInSeconds = 1.0;
+        opts.callbackData = data;
+        opts.callback = scheduleEventsBundle_process;
+        data->scheduledEventId = celix_bundleContext_scheduleEvent(ctx, &opts);
+    }
+
+    //schedule one time event
+    {
+        celix_scheduled_event_options_t opts = CELIX_EMPTY_SCHEDULED_EVENT_OPTIONS;
+        opts.name = "one shot scheduled event example";
+        opts.initialDelayInSeconds = 0.1;
+        opts.callbackData = data;
+        opts.callback = scheduleEventsBundle_oneShot;
+        celix_bundleContext_scheduleEvent(ctx, &opts);
+    }
+
+    return CELIX_SUCCESS;
+}
+
+static celix_status_t scheduleEventsBundle_stop(schedule_events_bundle_activator_data_t *data, celix_bundle_context_t *ctx) {
+    celix_bundleContext_removeScheduledEvent(ctx, data->scheduledEventId);
+    return CELIX_SUCCESS;
+}
+
+CELIX_GEN_BUNDLE_ACTIVATOR(schedule_events_bundle_activator_data_t, scheduleEventsBundle_start, scheduleEventsBundle_stop)
+```
+
+### C++ Example
+
+```cpp
+#include <iostream>
+#include "celix/BundleActivator.h"
+
+class ScheduleEventsBundleActivator {
+public:
+    explicit ScheduleEventsBundleActivator(const std::shared_ptr<celix::BundleContext>& ctx) {
+        //schedule recurring event
+        event = ctx->scheduledEvent()
+                .withInitialDelay(std::chrono::milliseconds{10})
+                .withInterval(std::chrono::seconds{1})
+                .withCallback([ctx] {
+                    ctx->logInfo("Recurring scheduled event fired");
+                })
+                .build();
+
+        //schedule one time event
+        ctx->scheduledEvent()
+                .withInitialDelay(std::chrono::milliseconds{10})
+                .withCallback([ctx] {
+                    ctx->logInfo("One shot scheduled event fired");
+                })
+                .build();
+    }
+
+    ~ScheduleEventsBundleActivator() noexcept {
+        std::cout << "Goodbye world" << std::endl;
+    }
+private:
+    celix::ScheduledEvent event{};
+};
+
+CELIX_GEN_CXX_BUNDLE_ACTIVATOR(ScheduleEventsBundleActivator)
+```
+
+## Waking up a Scheduled Event
+
+To process a scheduled event directly, you can use the `celix_bundleContext_wakeupScheduledEvent` C function or 
+`celix::ScheduledEvent::wakup` C++ method. This will wake up the scheduled event and call its callback function.