diff --git a/algo/data/CMakeLists.txt b/algo/data/CMakeLists.txt
index 0fd4f3a931d02d9e079cbf78302af3751074336d..c2454df911348c990a0702546de4f79290ddea93 100644
--- a/algo/data/CMakeLists.txt
+++ b/algo/data/CMakeLists.txt
@@ -4,13 +4,18 @@
 
 set(SRCS
   ${CMAKE_SOURCE_DIR}/core/data/sts/CbmStsDigi.cxx
-)
+  ${CMAKE_SOURCE_DIR}/core/data/global/CbmDigiEvent.cxx
+  ${CMAKE_SOURCE_DIR}/core/data/global/CbmDigiTimeslice.cxx
+ )
 
 add_library(OnlineData SHARED ${SRCS})
 
 target_include_directories(OnlineData
   PUBLIC ${CMAKE_SOURCE_DIR}/core/data
+  PUBLIC ${CMAKE_SOURCE_DIR}/core/data/base
   PUBLIC ${CMAKE_SOURCE_DIR}/core/data/sts
+  PUBLIC ${CMAKE_SOURCE_DIR}/core/data/global
+  PUBLIC ${CMAKE_SOURCE_DIR}/external/ipc/ipc/lib/fles_ipc
 )
 
 target_include_directories(OnlineData SYSTEM
diff --git a/core/data/CMakeLists.txt b/core/data/CMakeLists.txt
index a0f1b2f63cf8c0924061e176e164f19bb1caedf2..ab31041c84179db0b35acce22a3f7aec5b4a6b92 100644
--- a/core/data/CMakeLists.txt
+++ b/core/data/CMakeLists.txt
@@ -14,6 +14,7 @@ set(INCLUDE_DIRECTORIES
   ${CMAKE_CURRENT_SOURCE_DIR}/rich
   ${CMAKE_CURRENT_SOURCE_DIR}/psd
   ${CMAKE_CURRENT_SOURCE_DIR}/global
+  ${CMAKE_SOURCE_DIR}/external/ipc/ipc/lib/fles_ipc
 )
 include_directories( ${INCLUDE_DIRECTORIES})
 
@@ -113,6 +114,8 @@ set(SRCS
   psd/CbmPsdAddress.cxx
   psd/CbmPsdMCbmHit.cxx
 
+  global/CbmDigiEvent.cxx
+  global/CbmDigiTimeslice.cxx
   global/CbmGlobalTrack.cxx
   global/CbmVertex.cxx
   global/CbmTofTrack.cxx
diff --git a/core/data/base/CbmDigiData.h b/core/data/base/CbmDigiData.h
new file mode 100644
index 0000000000000000000000000000000000000000..2b7732313ab83939d55642dbf264496fbc3913ce
--- /dev/null
+++ b/core/data/base/CbmDigiData.h
@@ -0,0 +1,62 @@
+/* Copyright (C) 2021 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Volker Friese [committer] */
+
+
+#ifndef CBMDIGIDATA_H
+#define CBMDIGIDATA_H 1
+
+#include "CbmStsDigi.h"
+
+#include <boost/serialization/access.hpp>
+
+#include <vector>
+
+#ifndef NO_ROOT
+#include <Rtypes.h>  // for ClassDef
+#endif
+
+
+/** @struct CbmDigiVector
+ ** @brief Digi collection in a std::vector
+ **
+ ** This is the simplest form of a collection of detector digis. A detector-specific
+ ** implementation may choose a different representation (i.e., several vectors) or
+ ** add meta-data.
+ **/
+template<class Digi>
+struct CbmDigiVec {
+  std::vector<Digi> fDigis;
+  friend class boost::serialization::access;
+  template<class Archive>
+  void serialize(Archive& ar, const unsigned int /*version*/)
+  {
+    ar& fDigis;
+  }
+};
+
+
+/** @struct CbmDigiData
+ ** @brief Collection of digis from all detector systems
+ **
+ ** If no detector-specific collection class is provided, the simplest form (DigiVector)
+ ** is used.
+ **
+ ** The current implementation uses STS only - to be expanded for all systems.
+ **/
+struct CbmDigiData {
+  friend class boost::serialization::access;
+  typedef CbmDigiVec<CbmStsDigi> StsDigiData;
+  StsDigiData fSts;
+  template<class Archive>
+  void serialize(Archive& ar, const unsigned int /*version*/)
+  {
+    ar& fSts;
+  }
+#ifndef NO_ROOT
+  ClassDefNV(CbmDigiData, 1);
+#endif
+};
+
+
+#endif /* CBMDIGIDATA_H */
diff --git a/core/data/global/CbmDigiEvent.cxx b/core/data/global/CbmDigiEvent.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..ee09a0a22d7b43bc005d6f5d288d308ecfb165b4
--- /dev/null
+++ b/core/data/global/CbmDigiEvent.cxx
@@ -0,0 +1,5 @@
+/* Copyright (C) 2021 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Volker Friese [committer] */
+
+#include "CbmDigiEvent.h"
diff --git a/core/data/global/CbmDigiEvent.h b/core/data/global/CbmDigiEvent.h
new file mode 100644
index 0000000000000000000000000000000000000000..d116059f448633c1fad72ba2a257221ad9ad011e
--- /dev/null
+++ b/core/data/global/CbmDigiEvent.h
@@ -0,0 +1,36 @@
+/* Copyright (C) 2021 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Volker Friese [committer] */
+
+#ifndef CBMDIGIEVENT_H
+#define CBMDIGIEVENT_H 1
+
+#include "CbmDigiData.h"
+
+#include <boost/serialization/access.hpp>
+
+#ifndef NO_ROOT
+#include <Rtypes.h>  // for ClassDef
+#endif
+
+/** @struct CbmDigiEvent
+ ** @brief Container of digis from all detectors in an event
+ **/
+struct CbmDigiEvent {
+  CbmDigiData fData;  ///< Event data
+  uint64_t fNumber;   ///< Event identifier
+  double fTime;       ///< Event trigger time [ns]
+  friend class boost::serialization::access;
+  template<class Archive>
+  void serialize(Archive& ar, const unsigned int /*version*/)
+  {
+    ar& fData;
+    ar& fNumber;
+    ar& fTime;
+  }
+#ifndef NO_ROOT
+  ClassDefNV(CbmDigiEvent, 1);
+#endif
+};
+
+#endif /* CBMDIGIEVENT_H */
diff --git a/core/data/global/CbmDigiTimeslice.cxx b/core/data/global/CbmDigiTimeslice.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..5a9231250e6d3f990f8bb22ce5a7546152511ece
--- /dev/null
+++ b/core/data/global/CbmDigiTimeslice.cxx
@@ -0,0 +1,5 @@
+/* Copyright (C) 2021 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Volker Friese [committer] */
+
+#include "CbmDigiTimeslice.h"
diff --git a/core/data/global/CbmDigiTimeslice.h b/core/data/global/CbmDigiTimeslice.h
new file mode 100644
index 0000000000000000000000000000000000000000..c818a4577dedfc073113d2991b842ee8ddc7d317
--- /dev/null
+++ b/core/data/global/CbmDigiTimeslice.h
@@ -0,0 +1,30 @@
+/* Copyright (C) 2021 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Volker Friese [committer] */
+
+#ifndef CBMDIGITIMESLICE_H
+#define CBMDIGITIMESLICE_H 1
+
+#include "CbmDigiData.h"
+
+#include "TimesliceDescriptor.hpp"
+
+#include <boost/serialization/access.hpp>
+
+
+/** @struct CbmDigiTimeslice
+ ** @brief Container of digis from all detectors in a time slice
+ **/
+struct CbmDigiTimeslice {
+  CbmDigiData fData;
+  fles::TimesliceDescriptor fDesc;
+  friend class boost::serialization::access;
+  template<class Archive>
+  void serialize(Archive& ar, const unsigned int /*version*/)
+  {
+    ar& fData;
+    ar& fDesc;
+  }
+};
+
+#endif /* CBMDIGITIMESLICE_H */
diff --git a/reco/eventbuilder/digis/CbmBuildEventsIdeal.cxx b/reco/eventbuilder/digis/CbmBuildEventsIdeal.cxx
index 6b9290ee7c7d4090972c861246f592ebb654422c..916bbaa8789e3e5a805babc018f7b6462d3e7a58 100644
--- a/reco/eventbuilder/digis/CbmBuildEventsIdeal.cxx
+++ b/reco/eventbuilder/digis/CbmBuildEventsIdeal.cxx
@@ -73,6 +73,7 @@ void CbmBuildEventsIdeal::Exec(Option_t*)
 
   // --- Bookkeeping: Map from (input number, event number) to event
   map<pair<Int_t, Int_t>, CbmEvent*> eventMap;
+  map<pair<Int_t, Int_t>, CbmDigiEvent*> digiEventMap;
 
   // --- Loop over all detector systems
   for (ECbmModuleId& system : fSystems) {
@@ -109,10 +110,10 @@ void CbmBuildEventsIdeal::Exec(Option_t*)
 
       // --- Get the MC input and event numbers through the match object
 
-      CbmMatch digiEvents = EventsInMatch(fDigiMan->GetMatch(system, iDigi));
+      CbmMatch matchedEvents = EventsInMatch(fDigiMan->GetMatch(system, iDigi));
 
-      for (Int_t iLink = 0; iLink < digiEvents.GetNofLinks(); iLink++) {
-        const auto& link = digiEvents.GetLink(iLink);
+      for (Int_t iLink = 0; iLink < matchedEvents.GetNofLinks(); iLink++) {
+        const auto& link = matchedEvents.GetLink(iLink);
         auto eventID     = make_pair(link.GetFile(), link.GetEntry());
 
         // --- Get event pointer. If event is not yet present, create it.
@@ -126,13 +127,29 @@ void CbmBuildEventsIdeal::Exec(Option_t*)
           event = it->second;
         }
         event->AddData(digiType, iDigi);
+
+        // --- Get event pointer. If event is not yet present, create it.
+        CbmDigiEvent* digiEvent = nullptr;
+        auto it2                = digiEventMap.find(eventID);
+        if (it2 == digiEventMap.end()) {
+          digiEvent             = new CbmDigiEvent();
+          digiEventMap[eventID] = digiEvent;
+        }
+        else {
+          digiEvent = it2->second;
+        }
+        if (system == ECbmModuleId::kSts) {
+          digiEvent->fData.fSts.fDigis.push_back(*(fDigiMan->Get<CbmStsDigi>(iDigi)));
+        }
+
+
       }  //# links
 
       // --- Empty match objects or negative event numbers signal noise
-      if (!digiEvents.GetNofLinks() == 0) { nNoise++; }
+      if (matchedEvents.GetNofLinks() == 0) { nNoise++; }
 
       // --- Count occurrences of multiple MC events in match
-      if (digiEvents.GetNofLinks() > 1) { nAmbig++; }
+      if (matchedEvents.GetNofLinks() > 1) { nAmbig++; }
 
     }  //# digis
     LOG(debug) << GetName() << ": Detector " << CbmModuleList::GetModuleNameCaps(system) << ", digis " << nDigis << " ("
@@ -153,6 +170,14 @@ void CbmBuildEventsIdeal::Exec(Option_t*)
     it->second = nullptr;  // for a case
   }
 
+  // Store CbmDigiEvent
+  for (auto it = digiEventMap.begin(); it != digiEventMap.end(); it++) {
+    fDigiEvents->push_back(*(it->second));
+    delete it->second;
+    it->second = nullptr;
+  }
+
+
   // --- Timeslice log and statistics
   timer.Stop();
   stringstream logOut;
@@ -230,6 +255,7 @@ InitStatus CbmBuildEventsIdeal::Init()
   }
 
   // Register output array (CbmEvent)
+  // TODO: This shall be removed once reconstruction from DigiEvent is established.
   if (ioman->GetObject("CbmEvent")) {
     LOG(fatal) << GetName() << ": Branch CbmEvent already exists!";
     return kFATAL;
@@ -241,6 +267,19 @@ InitStatus CbmBuildEventsIdeal::Init()
     return kFATAL;
   }
 
+  // Register output array (CbmDigiEvent)
+  if (ioman->GetObject("DigiEvent")) {
+    LOG(fatal) << GetName() << ": Branch DigiEvent already exists!";
+    return kFATAL;
+  }
+  fDigiEvents = new std::vector<CbmDigiEvent>;
+  ioman->RegisterAny("DigiEvent", fDigiEvents, IsOutputBranchPersistent("DigiEvent"));
+  if (!fDigiEvents) {
+    LOG(fatal) << GetName() << ": Output branch could not be created!";
+    return kFATAL;
+  }
+
+
   LOG(info) << "==================================================";
   std::cout << std::endl;
 
diff --git a/reco/eventbuilder/digis/CbmBuildEventsIdeal.h b/reco/eventbuilder/digis/CbmBuildEventsIdeal.h
index 16f4d1dd8bb5a3f80eb35abdaa57a020c8d7c004..c8e04059fac490dc17a6e70eed63261818606fb0 100644
--- a/reco/eventbuilder/digis/CbmBuildEventsIdeal.h
+++ b/reco/eventbuilder/digis/CbmBuildEventsIdeal.h
@@ -13,6 +13,7 @@
 
 
 #include "CbmDefs.h"
+#include "CbmDigiEvent.h"
 #include "CbmMatch.h"
 
 #include <FairTask.h>
@@ -69,16 +70,17 @@ private:  // methods
   CbmMatch EventsInMatch(const CbmMatch* match);
 
 
-private:                                  // members
-  CbmDigiManager* fDigiMan = nullptr;     //!
-  std::vector<ECbmModuleId> fSystems {};  //  List of detector systems
-  TClonesArray* fEvents   = nullptr;      //! Output array (class CbmEvent)
-  Int_t fNofEntries       = 0;            //  Number of processed time slices
-  Long64_t fNofEvents     = 0;
-  Double_t fNofDigisTotal = 0.;
-  Double_t fNofDigisAmbig = 0.;
-  Double_t fNofDigisNoise = 0.;
-  Double_t fTime          = 0.;
+private:                                             // members
+  CbmDigiManager* fDigiMan = nullptr;                //!
+  std::vector<ECbmModuleId> fSystems {};             //  List of detector systems
+  TClonesArray* fEvents                  = nullptr;  //! Output array (class CbmEvent)
+  Int_t fNofEntries                      = 0;        //  Number of processed time slices
+  Long64_t fNofEvents                    = 0;
+  Double_t fNofDigisTotal                = 0.;
+  Double_t fNofDigisAmbig                = 0.;
+  Double_t fNofDigisNoise                = 0.;
+  Double_t fTime                         = 0.;
+  std::vector<CbmDigiEvent>* fDigiEvents = nullptr;
 
 
   ClassDef(CbmBuildEventsIdeal, 3);