diff --git a/CHANGELOG.md b/CHANGELOG.md
index f65aa5fb..69d0f49d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,7 +2,7 @@
 
 All notable changes to this project will be documented in this file.
 
-## [0.12.0 - 2024-02-28]
+## [0.12.0 - 2024-04-02]
 
 Update with new features only for `NextcloudApp` class. #233
 
@@ -12,6 +12,10 @@ Update with new features only for `NextcloudApp` class. #233
 - `ex_app.integration_fastapi.fetch_models_task` are now public function, added `progress_init_start_value` param.
 - Global authentication when used now sets `request.scope["username"]` for easy use.
 
+### Changed
+
+- `UiActionFileInfo` class marked as deprecated, instead `ActionFileInfo` class should be used.
+
 ## [0.11.0 - 2024-02-17]
 
 ### Added
diff --git a/docs/NextcloudApp.rst b/docs/NextcloudApp.rst
index 87e078bb..d597453e 100644
--- a/docs/NextcloudApp.rst
+++ b/docs/NextcloudApp.rst
@@ -242,8 +242,8 @@ an empty response (which will be a status of 200) and in the background already
 The last parameter is a structure describing the action and the file on which it needs to be performed,
 which is passed by the AppAPI when clicking on the drop-down context menu of the file.
 
-We use the built method :py:meth:`~nc_py_api.ex_app.ui.files_actions.UiActionFileInfo.to_fs_node` into the structure to convert it
-into a standard :py:class:`~nc_py_api.files.FsNode` class that describes the file and pass the FsNode class instance to the background task.
+We use the built-in ``to_fs_node`` method of :py:class:`~nc_py_api.files.ActionFileInfo` to get a standard
+:py:class:`~nc_py_api.files.FsNode` class that describes the file and pass the FsNode class instance to the background task.
 
 In the **convert_video_to_gif** function, a standard conversion using ``OpenCV`` from a video file to a GIF image occurs,
 and since this is not directly related to working with NextCloud, we will skip this for now.
@@ -261,7 +261,7 @@ This is a modified endpoint from ``to_gif`` example:
 
     @APP.post("/video_to_gif")
     async def video_to_gif(
-        file: UiFileActionHandlerInfo,
+        file: ActionFileInfo,
         nc: Annotated[NextcloudApp, Depends(nc_app)],
         background_tasks: BackgroundTasks,
     ):
diff --git a/docs/conf.py b/docs/conf.py
index 546a1c18..4cbe72d9 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -68,6 +68,8 @@
     (r"py:class", r"starlette\.requests\.Request"),
     (r"py:class", r"starlette\.requests\.HTTPConnection"),
     (r"py:class", r"ComputedFieldInfo"),
+    (r"py:class", r"FieldInfo"),
+    (r"py:class", r"ConfigDict"),
     (r"py:.*", r"httpx.*"),
 ]
 
diff --git a/docs/reference/Files/Files.rst b/docs/reference/Files/Files.rst
index f2bb37f6..be3a9b53 100644
--- a/docs/reference/Files/Files.rst
+++ b/docs/reference/Files/Files.rst
@@ -26,3 +26,6 @@ All File APIs are designed to work relative to the current user.
 
 .. autoclass:: nc_py_api.files.FsNodeLockInfo
     :members:
+
+.. autoclass:: nc_py_api.files.ActionFileInfo
+    :members: fileId, name, directory, etag, mime, fileType, size, favorite, permissions, mtime, userId, instanceId, to_fs_node
diff --git a/examples/as_app/to_gif/lib/main.py b/examples/as_app/to_gif/lib/main.py
index cf99d388..cc1e56ba 100644
--- a/examples/as_app/to_gif/lib/main.py
+++ b/examples/as_app/to_gif/lib/main.py
@@ -14,9 +14,9 @@
 
 from nc_py_api import FsNode, NextcloudApp
 from nc_py_api.ex_app import (
+    ActionFileInfo,
     AppAPIAuthMiddleware,
     LogLvl,
-    UiActionFileInfo,
     nc_app,
     run_app,
     set_handlers,
@@ -77,7 +77,7 @@ def convert_video_to_gif(input_file: FsNode, nc: NextcloudApp):
 
 @APP.post("/video_to_gif")
 async def video_to_gif(
-    file: UiActionFileInfo,
+    file: ActionFileInfo,
     nc: Annotated[NextcloudApp, Depends(nc_app)],
     background_tasks: BackgroundTasks,
 ):
diff --git a/nc_py_api/_version.py b/nc_py_api/_version.py
index 9b683c0c..467f6a06 100644
--- a/nc_py_api/_version.py
+++ b/nc_py_api/_version.py
@@ -1,3 +1,3 @@
 """Version of nc_py_api."""
 
-__version__ = "0.12.0.dev0"
+__version__ = "0.12.0"
diff --git a/nc_py_api/ex_app/__init__.py b/nc_py_api/ex_app/__init__.py
index 657a0884..b784b081 100644
--- a/nc_py_api/ex_app/__init__.py
+++ b/nc_py_api/ex_app/__init__.py
@@ -1,6 +1,7 @@
 """All possible ExApp stuff for NextcloudApp that can be used."""
 
-from .defs import LogLvl
+from ..files import ActionFileInfo
+from .defs import FileSystemEventNotification, LogLvl
 from .integration_fastapi import (
     AppAPIAuthMiddleware,
     anc_app,
@@ -15,6 +16,9 @@
     persistent_storage,
     verify_version,
 )
-from .ui.files_actions import UiActionFileInfo
 from .ui.settings import SettingsField, SettingsFieldType, SettingsForm
 from .uvicorn_fastapi import run_app
+
+
+class UiActionFileInfo(ActionFileInfo):
+    """``Deprecated``: use :py:class:`~nc_py_api.ex_app.ActionFileInfo` instead."""
diff --git a/nc_py_api/ex_app/defs.py b/nc_py_api/ex_app/defs.py
index 5296e164..8d6c4141 100644
--- a/nc_py_api/ex_app/defs.py
+++ b/nc_py_api/ex_app/defs.py
@@ -2,6 +2,10 @@
 
 import enum
 
+from pydantic import BaseModel
+
+from ..files import ActionFileInfo
+
 
 class LogLvl(enum.IntEnum):
     """Log levels."""
@@ -16,3 +20,18 @@ class LogLvl(enum.IntEnum):
     """Error log level"""
     FATAL = 4
     """Fatal log level"""
+
+
+class FileSystemEventData(BaseModel):
+    """FileSystem events format."""
+
+    target: ActionFileInfo
+    source: ActionFileInfo | None = None
+
+
+class FileSystemEventNotification(BaseModel):
+    """AppAPI event notification common data."""
+
+    event_type: str
+    event_subtype: str
+    event_data: FileSystemEventData
diff --git a/nc_py_api/ex_app/ui/files_actions.py b/nc_py_api/ex_app/ui/files_actions.py
index e4475864..11d76cac 100644
--- a/nc_py_api/ex_app/ui/files_actions.py
+++ b/nc_py_api/ex_app/ui/files_actions.py
@@ -1,15 +1,10 @@
 """Nextcloud API for working with drop-down file's menu."""
 
 import dataclasses
-import datetime
-import os
-
-from pydantic import BaseModel
 
 from ..._exceptions import NextcloudExceptionNotFound
 from ..._misc import require_capabilities
 from ..._session import AsyncNcSessionApp, NcSessionApp
-from ...files import FsNode, permissions_to_str
 
 
 @dataclasses.dataclass
@@ -63,61 +58,6 @@ def __repr__(self):
         return f"<{self.__class__.__name__} name={self.name}, mime={self.mime}, handler={self.action_handler}>"
 
 
-class UiActionFileInfo(BaseModel):
-    """File Information Nextcloud sends to the External Application."""
-
-    fileId: int
-    """FileID without Nextcloud instance ID"""
-    name: str
-    """Name of the file/directory"""
-    directory: str
-    """Directory relative to the user's home directory"""
-    etag: str
-    mime: str
-    fileType: str
-    """**file** or **dir**"""
-    size: int
-    """size of file/directory"""
-    favorite: str
-    """**true** or **false**"""
-    permissions: int
-    """Combination of :py:class:`~nc_py_api.files.FilePermissions` values"""
-    mtime: int
-    """Last modified time"""
-    userId: str
-    """The ID of the user performing the action."""
-    shareOwner: str | None
-    """If the object is shared, this is a display name of the share owner."""
-    shareOwnerId: str | None
-    """If the object is shared, this is the owner ID of the share."""
-    instanceId: str | None
-    """Nextcloud instance ID."""
-
-    def to_fs_node(self) -> FsNode:
-        """Returns usual :py:class:`~nc_py_api.files.FsNode` created from this class."""
-        user_path = os.path.join(self.directory, self.name).rstrip("/")
-        is_dir = bool(self.fileType.lower() == "dir")
-        if is_dir:
-            user_path += "/"
-        full_path = os.path.join(f"files/{self.userId}", user_path.lstrip("/"))
-        file_id = str(self.fileId).rjust(8, "0")
-
-        permissions = "S" if self.shareOwnerId else ""
-        permissions += permissions_to_str(self.permissions, is_dir)
-        return FsNode(
-            full_path,
-            etag=self.etag,
-            size=self.size,
-            content_length=0 if is_dir else self.size,
-            permissions=permissions,
-            favorite=bool(self.favorite.lower() == "true"),
-            file_id=file_id + self.instanceId if self.instanceId else file_id,
-            fileid=self.fileId,
-            last_modified=datetime.datetime.utcfromtimestamp(self.mtime).replace(tzinfo=datetime.timezone.utc),
-            mimetype=self.mime,
-        )
-
-
 class _UiFilesActionsAPI:
     """API for the drop-down menu in Nextcloud **Files app**, avalaible as **nc.ui.files_dropdown_menu.<method>**."""
 
diff --git a/nc_py_api/files/__init__.py b/nc_py_api/files/__init__.py
index 828576f5..7c151708 100644
--- a/nc_py_api/files/__init__.py
+++ b/nc_py_api/files/__init__.py
@@ -4,8 +4,11 @@
 import datetime
 import email.utils
 import enum
+import os
 import warnings
 
+from pydantic import BaseModel
+
 from .. import _misc
 
 
@@ -461,3 +464,58 @@ def __str__(self):
             f"{self.share_type.name}: `{self.path}` with id={self.share_id}"
             f" from {self.share_owner} to {self.share_with}"
         )
+
+
+class ActionFileInfo(BaseModel):
+    """Information Nextcloud sends to the External Application about File Nodes affected in action."""
+
+    fileId: int
+    """FileID without Nextcloud instance ID"""
+    name: str
+    """Name of the file/directory"""
+    directory: str
+    """Directory relative to the user's home directory"""
+    etag: str
+    mime: str
+    fileType: str
+    """**file** or **dir**"""
+    size: int
+    """size of file/directory"""
+    favorite: str
+    """**true** or **false**"""
+    permissions: int
+    """Combination of :py:class:`~nc_py_api.files.FilePermissions` values"""
+    mtime: int
+    """Last modified time"""
+    userId: str
+    """The ID of the user performing the action."""
+    shareOwner: str | None = None
+    """If the object is shared, this is a display name of the share owner."""
+    shareOwnerId: str | None = None
+    """If the object is shared, this is the owner ID of the share."""
+    instanceId: str | None = None
+    """Nextcloud instance ID."""
+
+    def to_fs_node(self) -> FsNode:
+        """Returns usual :py:class:`~nc_py_api.files.FsNode` created from this class."""
+        user_path = os.path.join(self.directory, self.name).rstrip("/")
+        is_dir = bool(self.fileType.lower() == "dir")
+        if is_dir:
+            user_path += "/"
+        full_path = os.path.join(f"files/{self.userId}", user_path.lstrip("/"))
+        file_id = str(self.fileId).rjust(8, "0")
+
+        permissions = "S" if self.shareOwnerId else ""
+        permissions += permissions_to_str(self.permissions, is_dir)
+        return FsNode(
+            full_path,
+            etag=self.etag,
+            size=self.size,
+            content_length=0 if is_dir else self.size,
+            permissions=permissions,
+            favorite=bool(self.favorite.lower() == "true"),
+            file_id=file_id + self.instanceId if self.instanceId else file_id,
+            fileid=self.fileId,
+            last_modified=datetime.datetime.utcfromtimestamp(self.mtime).replace(tzinfo=datetime.timezone.utc),
+            mimetype=self.mime,
+        )