diff --git a/Sources/XXClient/Models/NotificationReport.swift b/Sources/XXClient/Models/NotificationReport.swift
index 31c106a34f5a083478522acf542d8b608544a333..06eb1d89c273fcfec99e8d4615936a1d9b8ff237 100644
--- a/Sources/XXClient/Models/NotificationReport.swift
+++ b/Sources/XXClient/Models/NotificationReport.swift
@@ -1,7 +1,7 @@
 import Foundation
 
 public struct NotificationReport: Equatable {
-  public enum ReportType: String, Equatable {
+  public enum ReportType: String, Equatable, CaseIterable {
     case `default`
     case request
     case reset
diff --git a/Sources/XXMessengerClient/Messenger/Functions/MessengerGetNotificationReport.swift b/Sources/XXMessengerClient/Messenger/Functions/MessengerGetNotificationReport.swift
new file mode 100644
index 0000000000000000000000000000000000000000..6de0ead8402d7b0065f45a47c014121191fe6d39
--- /dev/null
+++ b/Sources/XXMessengerClient/Messenger/Functions/MessengerGetNotificationReport.swift
@@ -0,0 +1,39 @@
+import XXClient
+import XCTestDynamicOverlay
+
+public struct MessengerGetNotificationReport {
+  public enum Error: Swift.Error, Equatable {
+    case notConnected
+    case serviceListMissing
+  }
+
+  public var run: (String) throws -> NotificationReport
+
+  public func callAsFunction(notificationCSV: String) throws -> NotificationReport {
+    try run(notificationCSV)
+  }
+}
+
+extension MessengerGetNotificationReport {
+  public static func live(_ env: MessengerEnvironment) -> MessengerGetNotificationReport {
+    MessengerGetNotificationReport { notificationCSV in
+      guard let e2e = env.e2e() else {
+        throw Error.notConnected
+      }
+      guard let serviceList = env.serviceList() else {
+        throw Error.serviceListMissing
+      }
+      return try env.getNotificationsReport(
+        e2eId: e2e.getId(),
+        notificationCSV: notificationCSV,
+        services: serviceList
+      )
+    }
+  }
+}
+
+extension MessengerGetNotificationReport {
+  public static let unimplemented = MessengerGetNotificationReport(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
diff --git a/Sources/XXMessengerClient/Messenger/MessengerEnvironment.swift b/Sources/XXMessengerClient/Messenger/MessengerEnvironment.swift
index d8c687875d7526c5fc7882ff48ff910e423aaa44..76707e352ad472aed566118f10963e6bb8600177 100644
--- a/Sources/XXMessengerClient/Messenger/MessengerEnvironment.swift
+++ b/Sources/XXMessengerClient/Messenger/MessengerEnvironment.swift
@@ -16,6 +16,7 @@ public struct MessengerEnvironment {
   public var getE2EFileTransferParams: GetE2EFileTransferParams
   public var getE2EParams: GetE2EParams
   public var getFileTransferParams: GetFileTransferParams
+  public var getNotificationsReport: GetNotificationsReport
   public var getSingleUseParams: GetSingleUseParams
   public var initFileTransfer: InitFileTransfer
   public var initializeBackup: InitializeBackup
@@ -68,6 +69,7 @@ extension MessengerEnvironment {
       getE2EFileTransferParams: .liveDefault,
       getE2EParams: .liveDefault,
       getFileTransferParams: .liveDefault,
+      getNotificationsReport: .live,
       getSingleUseParams: .liveDefault,
       initFileTransfer: .live,
       initializeBackup: .live,
@@ -115,6 +117,7 @@ extension MessengerEnvironment {
     getE2EFileTransferParams: .unimplemented,
     getE2EParams: .unimplemented,
     getFileTransferParams: .unimplemented,
+    getNotificationsReport: .unimplemented,
     getSingleUseParams: .unimplemented,
     initFileTransfer: .unimplemented,
     initializeBackup: .unimplemented,
diff --git a/Tests/XXMessengerClientTests/Messenger/Functions/MessengerGetNotificationReportTests.swift b/Tests/XXMessengerClientTests/Messenger/Functions/MessengerGetNotificationReportTests.swift
new file mode 100644
index 0000000000000000000000000000000000000000..236cfae7920e35932990585f8e2a6256a20b32aa
--- /dev/null
+++ b/Tests/XXMessengerClientTests/Messenger/Functions/MessengerGetNotificationReportTests.swift
@@ -0,0 +1,88 @@
+import CustomDump
+import XCTest
+import XCTestDynamicOverlay
+import XXClient
+@testable import XXMessengerClient
+
+final class MessengerGetNotificationReportTests: XCTestCase {
+  func testGetReport() throws {
+    let e2eId = 123
+    let serviceList = MessageServiceList.stub()
+    let notificationCSV = "notification-csv"
+    let notificationReport = NotificationReport.stub()
+
+    struct GetNotificationsReportParams: Equatable {
+      var e2eId: Int
+      var notificationCSV: String
+      var serviceList: MessageServiceList
+    }
+    var didGetNotificationsReport: [GetNotificationsReportParams] = []
+
+    var env: MessengerEnvironment = .unimplemented
+    env.e2e.get = {
+      var e2e: E2E = .unimplemented
+      e2e.getId.run = { e2eId }
+      return e2e
+    }
+    env.serviceList.get = {
+      serviceList
+    }
+    env.getNotificationsReport.run = { e2eId, notificationCSV, serviceList in
+      didGetNotificationsReport.append(.init(
+        e2eId: e2eId,
+        notificationCSV: notificationCSV,
+        serviceList: serviceList
+      ))
+      return notificationReport
+    }
+    let getReport: MessengerGetNotificationReport = .live(env)
+
+    let report = try getReport(notificationCSV: notificationCSV)
+
+    XCTAssertNoDifference(didGetNotificationsReport, [
+      .init(
+        e2eId: e2eId,
+        notificationCSV: notificationCSV,
+        serviceList: serviceList
+      )
+    ])
+    XCTAssertNoDifference(report, notificationReport)
+  }
+
+  func testGetReportWhenNotConnected() {
+    var env: MessengerEnvironment = .unimplemented
+    env.e2e.get = { nil }
+    let getReport: MessengerGetNotificationReport = .live(env)
+
+    XCTAssertThrowsError(try getReport(notificationCSV: "")) { error in
+      XCTAssertNoDifference(
+        error as? MessengerGetNotificationReport.Error,
+        .notConnected
+      )
+    }
+  }
+
+  func testGetReportWhenServiceListMissing() {
+    var env: MessengerEnvironment = .unimplemented
+    env.e2e.get = { .unimplemented }
+    env.serviceList.get = { nil }
+    let getReport: MessengerGetNotificationReport = .live(env)
+
+    XCTAssertThrowsError(try getReport(notificationCSV: "")) { error in
+      XCTAssertNoDifference(
+        error as? MessengerGetNotificationReport.Error,
+        .serviceListMissing
+      )
+    }
+  }
+}
+
+extension NotificationReport {
+  static func stub() -> NotificationReport {
+    NotificationReport(
+      forMe: .random(),
+      type: ReportType.allCases.randomElement()!,
+      source: "source-\(Int.random(in: 100...999))".data(using: .utf8)!
+    )
+  }
+}