Index: ChapterX.Application/Notify/Commands/AddHandler.cs
===================================================================
--- ChapterX.Application/Notify/Commands/AddHandler.cs	(revision 877c13c3dd0934c1d31da7988d0d2c2c5925ed55)
+++ ChapterX.Application/Notify/Commands/AddHandler.cs	(revision 877c13c3dd0934c1d31da7988d0d2c2c5925ed55)
@@ -0,0 +1,31 @@
+using ChapterX.Domain.Repositories;
+using MediatR;
+using Microsoft.Extensions.Logging;
+
+namespace ChapterX.Application.Notify.Commands
+{
+    public class AddHandler : IRequestHandler<AddRequest, AddResponse>
+    {
+        private readonly INotifyRepository _notifyRepository;
+        private readonly ILogger<AddHandler> _logger;
+
+        public AddHandler(INotifyRepository notifyRepository, ILogger<AddHandler> logger)
+        {
+            _notifyRepository = notifyRepository;
+            _logger = logger;
+        }
+
+        public async Task<AddResponse> Handle(AddRequest request, CancellationToken cancellationToken)
+        {
+            var notify = new Domain.Entities.Notify
+            {
+                UserId = request.UserId,
+                NotificationId = request.NotificationId
+            };
+
+            await _notifyRepository.AddAsync(notify, cancellationToken);
+
+            return new AddResponse(notify.Id);
+        }
+    }
+}
Index: ChapterX.Application/Notify/Commands/AddRequest.cs
===================================================================
--- ChapterX.Application/Notify/Commands/AddRequest.cs	(revision 877c13c3dd0934c1d31da7988d0d2c2c5925ed55)
+++ ChapterX.Application/Notify/Commands/AddRequest.cs	(revision 877c13c3dd0934c1d31da7988d0d2c2c5925ed55)
@@ -0,0 +1,6 @@
+using MediatR;
+
+namespace ChapterX.Application.Notify.Commands
+{
+    public record AddRequest(int UserId, int NotificationId) : IRequest<AddResponse>;
+}
Index: ChapterX.Application/Notify/Commands/AddResponse.cs
===================================================================
--- ChapterX.Application/Notify/Commands/AddResponse.cs	(revision 877c13c3dd0934c1d31da7988d0d2c2c5925ed55)
+++ ChapterX.Application/Notify/Commands/AddResponse.cs	(revision 877c13c3dd0934c1d31da7988d0d2c2c5925ed55)
@@ -0,0 +1,4 @@
+namespace ChapterX.Application.Notify.Commands
+{
+    public record AddResponse(int Id);
+}
Index: ChapterX.Application/Notify/Commands/DeleteHandler.cs
===================================================================
--- ChapterX.Application/Notify/Commands/DeleteHandler.cs	(revision 877c13c3dd0934c1d31da7988d0d2c2c5925ed55)
+++ ChapterX.Application/Notify/Commands/DeleteHandler.cs	(revision 877c13c3dd0934c1d31da7988d0d2c2c5925ed55)
@@ -0,0 +1,29 @@
+using ChapterX.Domain.Repositories;
+using MediatR;
+using Microsoft.Extensions.Logging;
+
+namespace ChapterX.Application.Notify.Commands
+{
+    public class DeleteHandler : IRequestHandler<DeleteRequest, DeleteResponse>
+    {
+        private readonly INotifyRepository _notifyRepository;
+        private readonly ILogger<DeleteHandler> _logger;
+
+        public DeleteHandler(INotifyRepository notifyRepository, ILogger<DeleteHandler> logger)
+        {
+            _notifyRepository = notifyRepository;
+            _logger = logger;
+        }
+
+        public async Task<DeleteResponse> Handle(DeleteRequest request, CancellationToken cancellationToken)
+        {
+            var notify = await _notifyRepository.GetByIdAsync(request.Id, cancellationToken);
+            if (notify is null)
+                return new DeleteResponse(false);
+
+            await _notifyRepository.DeleteAsync(notify, cancellationToken);
+
+            return new DeleteResponse(true);
+        }
+    }
+}
Index: ChapterX.Application/Notify/Commands/DeleteRequest.cs
===================================================================
--- ChapterX.Application/Notify/Commands/DeleteRequest.cs	(revision 877c13c3dd0934c1d31da7988d0d2c2c5925ed55)
+++ ChapterX.Application/Notify/Commands/DeleteRequest.cs	(revision 877c13c3dd0934c1d31da7988d0d2c2c5925ed55)
@@ -0,0 +1,6 @@
+using MediatR;
+
+namespace ChapterX.Application.Notify.Commands
+{
+    public record DeleteRequest(int Id) : IRequest<DeleteResponse>;
+}
Index: ChapterX.Application/Notify/Commands/DeleteResponse.cs
===================================================================
--- ChapterX.Application/Notify/Commands/DeleteResponse.cs	(revision 877c13c3dd0934c1d31da7988d0d2c2c5925ed55)
+++ ChapterX.Application/Notify/Commands/DeleteResponse.cs	(revision 877c13c3dd0934c1d31da7988d0d2c2c5925ed55)
@@ -0,0 +1,4 @@
+namespace ChapterX.Application.Notify.Commands
+{
+    public record DeleteResponse(bool Success);
+}
Index: ChapterX.Application/Notify/Commands/UpdateHandler.cs
===================================================================
--- ChapterX.Application/Notify/Commands/UpdateHandler.cs	(revision 877c13c3dd0934c1d31da7988d0d2c2c5925ed55)
+++ ChapterX.Application/Notify/Commands/UpdateHandler.cs	(revision 877c13c3dd0934c1d31da7988d0d2c2c5925ed55)
@@ -0,0 +1,31 @@
+using ChapterX.Domain.Repositories;
+using MediatR;
+using Microsoft.Extensions.Logging;
+
+namespace ChapterX.Application.Notify.Commands
+{
+    public class UpdateHandler : IRequestHandler<UpdateRequest, UpdateResponse>
+    {
+        private readonly INotifyRepository _notifyRepository;
+        private readonly ILogger<UpdateHandler> _logger;
+
+        public UpdateHandler(INotifyRepository notifyRepository, ILogger<UpdateHandler> logger)
+        {
+            _notifyRepository = notifyRepository;
+            _logger = logger;
+        }
+
+        public async Task<UpdateResponse> Handle(UpdateRequest request, CancellationToken cancellationToken)
+        {
+            var notify = await _notifyRepository.GetByIdAsync(request.Id, cancellationToken);
+            if (notify is null)
+                return new UpdateResponse(false);
+
+            // No updatable fields on Notify entity
+
+            await _notifyRepository.UpdateAsync(notify, cancellationToken);
+
+            return new UpdateResponse(true);
+        }
+    }
+}
Index: ChapterX.Application/Notify/Commands/UpdateRequest.cs
===================================================================
--- ChapterX.Application/Notify/Commands/UpdateRequest.cs	(revision 877c13c3dd0934c1d31da7988d0d2c2c5925ed55)
+++ ChapterX.Application/Notify/Commands/UpdateRequest.cs	(revision 877c13c3dd0934c1d31da7988d0d2c2c5925ed55)
@@ -0,0 +1,6 @@
+using MediatR;
+
+namespace ChapterX.Application.Notify.Commands
+{
+    public record UpdateRequest(int Id, bool IsRead) : IRequest<UpdateResponse>;
+}
Index: ChapterX.Application/Notify/Commands/UpdateResponse.cs
===================================================================
--- ChapterX.Application/Notify/Commands/UpdateResponse.cs	(revision 877c13c3dd0934c1d31da7988d0d2c2c5925ed55)
+++ ChapterX.Application/Notify/Commands/UpdateResponse.cs	(revision 877c13c3dd0934c1d31da7988d0d2c2c5925ed55)
@@ -0,0 +1,4 @@
+namespace ChapterX.Application.Notify.Commands
+{
+    public record UpdateResponse(bool Success);
+}
