diff --git a/source/RobotAPI/components/ArViz/Client/Client.h b/source/RobotAPI/components/ArViz/Client/Client.h
index 4f2d4dd70855d78a4066f8cef6bd5eb2ad2bb460..c0d5708317ace3c10ea684482e32942b85d6f57c 100644
--- a/source/RobotAPI/components/ArViz/Client/Client.h
+++ b/source/RobotAPI/components/ArViz/Client/Client.h
@@ -38,6 +38,15 @@ namespace viz
             data_.updates.push_back(layer.data_);
         }
 
+        void add(std::initializer_list<Layer> layers)
+        {
+            data_.updates.reserve(data_.updates.size() + layers.size());
+            for (Layer const& layer : layers)
+            {
+                data_.updates.push_back(layer.data_);
+            }
+        }
+
         /**
          * @brief Request interaction feedback for a particular layer.
          * @param layer The layer you want to get interaction feedback for.
@@ -74,6 +83,27 @@ namespace viz
         Transform,
     };
 
+    inline const char* toString(InteractionFeedbackType type)
+    {
+        switch (type)
+        {
+        case InteractionFeedbackType::None:
+            return "None";
+        case InteractionFeedbackType::Select:
+            return "Select";
+        case InteractionFeedbackType::Deselect:
+            return "Deselect";
+        case InteractionFeedbackType::ContextMenuOpen:
+            return "ContextMenuOpen";
+        case InteractionFeedbackType::ContextMenuChosen:
+            return "ContextMenuChosen";
+        case InteractionFeedbackType::Transform:
+            return "Transform";
+        default:
+            return "<Unknown>";
+        }
+    }
+
     inline Eigen::Matrix4f toEigen(data::GlobalPose const& pose)
     {
         Eigen::Quaternionf ori(pose.qw, pose.qx, pose.qy, pose.qz);
@@ -202,6 +232,16 @@ namespace viz
             return end_;
         }
 
+        std::size_t size() const
+        {
+            return end_ - begin_;
+        }
+
+        bool empty() const
+        {
+            return begin_ == end_;
+        }
+
         InteractionFeedback const* begin_;
         InteractionFeedback const* end_;
     };
@@ -247,9 +287,11 @@ namespace viz
             return StagedCommit();
         }
 
-        void apply(StagedCommit const& commit)
+        CommitResult apply(StagedCommit const& commit)
         {
-            // TODO: Implement
+            CommitResult result;
+            result.data_ = storage->commitAndReceiveInteractions(commit.data_);
+            return result;
         }
 
         void commit(Layer const& layer)
diff --git a/source/RobotAPI/components/ArViz/Example/ArVizExample.cpp b/source/RobotAPI/components/ArViz/Example/ArVizExample.cpp
index df75428333532a8975f4a142700d08c41ac13b90..97899d9cfa00f3c53fe7c0249f9e4d96739a72a4 100644
--- a/source/RobotAPI/components/ArViz/Example/ArVizExample.cpp
+++ b/source/RobotAPI/components/ArViz/Example/ArVizExample.cpp
@@ -556,28 +556,34 @@ namespace armarx
         viz::Layer robotHandsLayer = arviz.layer("RobotHands");
         viz::Layer interactionLayer = arviz.layer("Interaction");
 
+        viz::StagedCommit stage = arviz.stage();
 
         // These layers are not updated in the loop.
         {
             viz::Layer permanentLayer = arviz.layer("Permanent");
             fillPermanentLayer(permanentLayer);
-            arviz.commit({permanentLayer});
+            stage.add(permanentLayer);
         }
         bool manyElements = getProperty<bool>("layers.ManyElements");
         if (manyElements)
         {
             viz::Layer manyElementsLayer = arviz.layer("ManyElements");
             fillManyElementsLayer(manyElementsLayer, 0);
-            arviz.commit({manyElementsLayer});
+            stage.add(manyElementsLayer);
         }
         {
             viz::Layer colorMapsLayer = arviz.layer("ColorMaps");
             fillColorMapsLayer(colorMapsLayer, 0);
-            arviz.commit({colorMapsLayer});
+            stage.add(colorMapsLayer);
         }
 
         fillInteractionLayer(interactionLayer);
-        arviz.commit({interactionLayer});
+        stage.add(interactionLayer);
+
+        // Apply the staged commits in a single network call
+        viz::CommitResult result = arviz.apply(stage);
+        ARMARX_INFO << "Permanent layers committed in revision: "
+                    << result.revision();
 
 
         CycleUtil c(20);
@@ -602,7 +608,29 @@ namespace armarx
                 fillRobotHandsLayer(robotHandsLayer);
             }
 
-            arviz.commit({testLayer, exampleLayer, pointsLayer, objectsLayer, disAppearingLayer, robotHandsLayer});
+            // We can reuse a staged commit
+            stage.reset();
+            // We can stage multiple layers at once.
+            // This is equivalent to calling add(layer) multiple times.
+            stage.add({testLayer, exampleLayer, pointsLayer, objectsLayer, disAppearingLayer, robotHandsLayer});
+            // We can request interaction feedback for specific layers
+            stage.requestInteraction(interactionLayer);
+
+            // This sends the layer updates and receives interaction feedback in a single network call
+            result = arviz.apply(stage);
+            // Be careful: The interactions are stored in the CommitResult
+            // So the range is only valid as long as result is in scope and not overriden.
+            viz::InteractionFeedbackRange interactions = result.interactions();
+            if (interactions.size() > 0)
+            {
+                ARMARX_INFO << "We got some interactions: " << interactions.size();
+                for (viz::InteractionFeedback const& interaction: interactions)
+                {
+                    ARMARX_INFO << "[" << interaction.layer()
+                                << "/" << interaction.element()
+                                << "] " << toString(interaction.type());
+                }
+            }
 
             c.waitForCycleDuration();
         }