diff --git a/typo3/sysext/core/Documentation/Changelog/12.2/Feature-99430-AddEventAfterRecordPublishingInWorkspaces.rst b/typo3/sysext/core/Documentation/Changelog/12.2/Feature-99430-AddEventAfterRecordPublishingInWorkspaces.rst
new file mode 100644
index 0000000000000000000000000000000000000000..8c4e058e52d1045396533bddc9bf8849ab85e496
--- /dev/null
+++ b/typo3/sysext/core/Documentation/Changelog/12.2/Feature-99430-AddEventAfterRecordPublishingInWorkspaces.rst
@@ -0,0 +1,58 @@
+.. include:: /Includes.rst.txt
+
+.. _feature-99430-1672129914:
+
+=================================================================
+Feature: #99430 - Add event after record publishing in workspaces
+=================================================================
+
+See :issue:`99430`
+
+Description
+===========
+
+A new PSR-14 event :php:`\TYPO3\CMS\Workspaces\Event\AfterRecordPublishedEvent`
+has been added to allow extension developers to react on record publishing
+in workspaces.
+
+The new event is fired after a record has been published in a workspace and
+provides the following information:
+
+- :php:`getTable()`: The records' table name
+- :php:`getRecordId()`: The records' uid
+- :php:`getWorkspaceId()`: The workspace the record has been published in
+
+Example
+=======
+
+Registration of the :php:`AfterRecordPublishedEvent` in your extensions'
+:file:`Services.yaml`:
+
+..  code-block:: yaml
+
+    MyVendor\MyPackage\Workspaces\MyEventListener:
+      tags:
+        - name: event.listener
+          identifier: 'my-package/after-record-published'
+
+The corresponding event listener class:
+
+..  code-block:: php
+
+    use TYPO3\CMS\Workspaces\Event\AfterRecordPublishedEvent;
+
+    class MyEventListener {
+
+        public function __invoke(AfterRecordPublishedEvent $event): void
+        {
+            // Do your magic here
+        }
+    }
+
+Impact
+======
+
+With the new PSR-14 :php:`AfterRecordPublishedEvent` it is possible to
+execute custom functionality after a record has been published in a workspace.
+
+.. index:: PHP-API, ext:workspaces
diff --git a/typo3/sysext/workspaces/Classes/Event/AfterRecordPublishedEvent.php b/typo3/sysext/workspaces/Classes/Event/AfterRecordPublishedEvent.php
new file mode 100644
index 0000000000000000000000000000000000000000..684b3a78ab545c6a70f37d970147af3221809afc
--- /dev/null
+++ b/typo3/sysext/workspaces/Classes/Event/AfterRecordPublishedEvent.php
@@ -0,0 +1,46 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+namespace TYPO3\CMS\Workspaces\Event;
+
+/**
+ * Event that is fired after a record has been published ina workspace.
+ */
+final class AfterRecordPublishedEvent
+{
+    public function __construct(
+        private readonly string $table,
+        private readonly int $recordId,
+        private readonly int $workspaceId,
+    ) {
+    }
+
+    public function getTable(): string
+    {
+        return $this->table;
+    }
+
+    public function getRecordId(): int
+    {
+        return $this->recordId;
+    }
+
+    public function getWorkspaceId(): int
+    {
+        return $this->workspaceId;
+    }
+}
diff --git a/typo3/sysext/workspaces/Classes/Hook/DataHandlerHook.php b/typo3/sysext/workspaces/Classes/Hook/DataHandlerHook.php
index e9050c14cf7ecebf0c96ea516035d6beb722f5c2..9841f5b06a3870e8b70d40810e0905042f2c8e73 100644
--- a/typo3/sysext/workspaces/Classes/Hook/DataHandlerHook.php
+++ b/typo3/sysext/workspaces/Classes/Hook/DataHandlerHook.php
@@ -16,6 +16,7 @@
 namespace TYPO3\CMS\Workspaces\Hook;
 
 use Doctrine\DBAL\Exception as DBALException;
+use Psr\EventDispatcher\EventDispatcherInterface;
 use TYPO3\CMS\Backend\Utility\BackendUtility;
 use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
 use TYPO3\CMS\Core\Cache\CacheManager;
@@ -34,6 +35,7 @@ use TYPO3\CMS\Core\Utility\ArrayUtility;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Versioning\VersionState;
 use TYPO3\CMS\Workspaces\DataHandler\CommandMap;
+use TYPO3\CMS\Workspaces\Event\AfterRecordPublishedEvent;
 use TYPO3\CMS\Workspaces\Notification\StageChangeNotification;
 use TYPO3\CMS\Workspaces\Service\StagesService;
 use TYPO3\CMS\Workspaces\Service\WorkspaceService;
@@ -45,6 +47,10 @@ use TYPO3\CMS\Workspaces\Service\WorkspaceService;
  */
 class DataHandlerHook
 {
+    public function __construct(private readonly EventDispatcherInterface $eventDispatcher)
+    {
+    }
+
     /**
      * For accumulating information about workspace stages raised
      * on elements so a single mail is sent as notification.
@@ -709,6 +715,7 @@ class DataHandlerHook
                 $dataHandler->deleteEl($table, $id, true);
                 $dataHandler->BE_USER->workspace = $currentUserWorkspace;
             }
+            $this->eventDispatcher->dispatch(new AfterRecordPublishedEvent($table, $id, $workspaceId));
             $dataHandler->log($table, $id, DatabaseAction::PUBLISH, 0, SystemLogErrorClassification::MESSAGE, 'Publishing successful for table "{table}" uid {liveId}=>{versionId}', -1, ['table' => $table, 'versionId' => $swapWith, 'liveId' => $id], $dataHandler->eventPid($table, $id, $swapVersion['pid']));
 
             // Set log entry for live record:
@@ -945,6 +952,7 @@ class DataHandlerHook
         if ($dataHandler->enableLogging) {
             $dataHandler->log($table, $id, DatabaseAction::PUBLISH, 0, SystemLogErrorClassification::MESSAGE, 'Publishing successful for table "{table}" uid {uid} (new record)', -1, ['table' => $table, 'uid' => $id], $dataHandler->eventPid($table, $id, $newRecordInWorkspace['pid']));
         }
+        $this->eventDispatcher->dispatch(new AfterRecordPublishedEvent($table, $id, $workspaceId));
 
         // Set log entry for record
         $propArr = $dataHandler->getRecordPropertiesFromRow($table, $newRecordInWorkspace);
diff --git a/typo3/sysext/workspaces/Configuration/Services.yaml b/typo3/sysext/workspaces/Configuration/Services.yaml
index adeaa923f67045eabf6240f020d8f1622a3d3f70..1b704351ee7a9cae3a30bd16b5a2be6ad2ee8430 100644
--- a/typo3/sysext/workspaces/Configuration/Services.yaml
+++ b/typo3/sysext/workspaces/Configuration/Services.yaml
@@ -40,6 +40,9 @@ services:
   TYPO3\CMS\Workspaces\Controller\Remote\ActionHandler:
     public: true
 
+  TYPO3\CMS\Workspaces\Hook\DataHandlerHook:
+    public: true
+
   TYPO3\CMS\Workspaces\Hook\BackendUtilityHook:
     tags:
       - name: event.listener
diff --git a/typo3/sysext/workspaces/Tests/Functional/Hook/DataHandlerHookTest.php b/typo3/sysext/workspaces/Tests/Functional/Hook/DataHandlerHookTest.php
index 2801856107184964f8e35776c1e4ab2a1aaa619c..a9b29f2ca4dcafcb7ff374f66245a62e9a90d744 100644
--- a/typo3/sysext/workspaces/Tests/Functional/Hook/DataHandlerHookTest.php
+++ b/typo3/sysext/workspaces/Tests/Functional/Hook/DataHandlerHookTest.php
@@ -17,11 +17,14 @@ declare(strict_types=1);
 
 namespace TYPO3\CMS\Workspaces\Tests\Functional\Hook;
 
+use Symfony\Component\DependencyInjection\Container;
 use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
 use TYPO3\CMS\Core\Context\Context;
 use TYPO3\CMS\Core\Context\WorkspaceAspect;
 use TYPO3\CMS\Core\Core\Bootstrap;
+use TYPO3\CMS\Core\EventDispatcher\ListenerProvider;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Workspaces\Event\AfterRecordPublishedEvent;
 use TYPO3\TestingFramework\Core\Functional\Framework\DataHandling\ActionService;
 use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
 
@@ -84,4 +87,39 @@ class DataHandlerHookTest extends FunctionalTestCase
 
         $this->assertCSVDataSet(__DIR__ . '/DataSet/deletingSysWorkspaceDeletesWorkspaceRecordsResult.csv');
     }
+
+    /**
+     * @test
+     */
+    public function flushByTagEventIsTriggered(): void
+    {
+        $afterRecordPublishedEvent = null;
+
+        /** @var Container $container */
+        $container = $this->getContainer();
+        $container->set(
+            'after-record-published-event',
+            static function (AfterRecordPublishedEvent $event) use (&$afterRecordPublishedEvent) {
+                $afterRecordPublishedEvent = $event;
+            }
+        );
+
+        $eventListener = $container->get(ListenerProvider::class);
+        $eventListener->addListener(AfterRecordPublishedEvent::class, 'after-record-published-event');
+
+        $this->importCSVDataSet(__DIR__ . '/DataSet/deletingSysWorkspaceDeletesWorkspaceRecords.csv');
+
+        $workspaceId = 1;
+        $tableName = 'tt_content';
+        $recordId = 301;
+
+        $this->setWorkspaceId($workspaceId);
+        $this->actionService->modifyRecord($tableName, $recordId, ['header' => '[Translate to Dansk:] Regular Element #1 Changed']);
+        $this->actionService->publishRecord($tableName, $recordId);
+
+        self::assertInstanceOf(AfterRecordPublishedEvent::class, $afterRecordPublishedEvent);
+        self::assertEquals($tableName, $afterRecordPublishedEvent->getTable());
+        self::assertEquals($recordId, $afterRecordPublishedEvent->getRecordId());
+        self::assertEquals($workspaceId, $afterRecordPublishedEvent->getWorkspaceId());
+    }
 }
diff --git a/typo3/sysext/workspaces/Tests/Unit/Event/AfterRecordPublishedEventTest.php b/typo3/sysext/workspaces/Tests/Unit/Event/AfterRecordPublishedEventTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..b46cfbd2992083a760b5c30f7a2ce5a59f312419
--- /dev/null
+++ b/typo3/sysext/workspaces/Tests/Unit/Event/AfterRecordPublishedEventTest.php
@@ -0,0 +1,40 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+namespace TYPO3\CMS\Workspaces\Tests\Unit\Event;
+
+use TYPO3\CMS\Workspaces\Event\AfterRecordPublishedEvent;
+use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
+
+class AfterRecordPublishedEventTest extends UnitTestCase
+{
+    /**
+     * @test
+     */
+    public function gettersReturnInitializedObjects(): void
+    {
+        $table = 'some_table';
+        $recordId = 2004;
+        $workspaceId = 13;
+
+        $event = new AfterRecordPublishedEvent($table, $recordId, $workspaceId);
+
+        self::assertEquals($table, $event->getTable());
+        self::assertEquals($recordId, $event->getRecordId());
+        self::assertEquals($workspaceId, $event->getWorkspaceId());
+    }
+}