diff --git a/bindings/follow.go b/bindings/follow.go
index 6267a34125388a681827437d7a1e1cea1aa1c8dd..199990bd69ee51e2b377d501ec537399dca89eab 100644
--- a/bindings/follow.go
+++ b/bindings/follow.go
@@ -10,6 +10,7 @@ package bindings
 import (
 	"encoding/json"
 	"fmt"
+	"gitlab.com/elixxir/client/cmix/message"
 	"time"
 
 	"github.com/pkg/errors"
@@ -168,3 +169,50 @@ func (c *Cmix) RegisterClientErrorCallback(clientError ClientError) {
 		}
 	}()
 }
+
+// TrackServicesCallback is the callback for Cmix.TrackServices.
+// This will pass to the user a JSON-marshalled list of backend services.
+// If there was an error retrieving or marshalling the service list,
+// there is an error for the second parameter which will be non-null.
+//
+// Example JSON:
+//
+// [
+//  {
+//    "Id": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD",
+//    "Services": [
+//      {
+//        "Identifier": null,
+//        "Tag": "test",
+//        "Metadata": null
+//      }
+//    ]
+//  },
+//  {
+//    "Id": "AAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD",
+//    "Services": [
+//      {
+//        "Identifier": null,
+//        "Tag": "test",
+//        "Metadata": null
+//      }
+//    ]
+//  },
+//]
+type TrackServicesCallback interface {
+	Callback(marshalData []byte, err error)
+}
+
+// TrackServices will return via a callback the list of services the
+// backend keeps track of, which is formally referred to as a
+// [message.ServiceList]. This may be passed into other bindings call which
+// may need context on the available services for this client.
+//
+// Parameters:
+//   - cb - A TrackServicesCallback, which will be passed the marshalled
+//     message.ServiceList.
+func (c *Cmix) TrackServices(cb TrackServicesCallback) {
+	c.api.GetCmix().TrackServices(func(list message.ServiceList) {
+		cb.Callback(json.Marshal(list))
+	})
+}
diff --git a/bindings/notifications.go b/bindings/notifications.go
index bbc79ca79c028ceac33a5ba1e972119f904aa4ba..e028ae0ce7a2186a2afd67873e668e7109a33022 100644
--- a/bindings/notifications.go
+++ b/bindings/notifications.go
@@ -7,67 +7,141 @@
 
 package bindings
 
-// FIXME: This is the old NotificationsForMe code that needs to be fixed
-/*
-type NotificationForMeReport struct {
-	ForMe  bool
-	Type   string
+import (
+	"encoding/json"
+	"gitlab.com/elixxir/client/cmix/message"
+	"gitlab.com/elixxir/primitives/notifications"
+)
+
+// NotificationReports is a list of NotificationReport's. This will be returned
+// via GetNotificationsReport as a JSON marshalled byte data.
+//
+// Example JSON:
+//
+// [
+//  {
+//    "ForMe": true,
+//    "Type": "e2e",
+//    "Source": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD"
+//  },
+//  {
+//    "ForMe": true,
+//    "Type": "e2e",
+//    "Source": "AAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD"
+//  },
+//  {
+//    "ForMe": true,
+//    "Type": "e2e",
+//    "Source": "AAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD"
+//  }
+//]
+type NotificationReports []NotificationReport
+
+// NotificationReport is the bindings' representation for notifications for
+// this user.
+//
+// Example NotificationReport JSON:
+//
+// {
+//  "ForMe": true,
+//  "Type": "e2e",
+//  "Source": "dGVzdGVyMTIzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+//}
+//
+// Given the Type, the Source value will have specific contextual meanings.
+// Below is a table that will define the contextual meaning of the Source field
+// given all possible Type fields.
+//
+//      TYPE     |     SOURCE         |    DESCRIPTION
+//     ________________________________________________________________________________________
+//     "default" |  recipient user ID |  A message with no association.
+//	   "request" |  sender user ID    |  A channel request has been received, from Source.
+//     "reset"   |  sender user ID    |  A channel reset has been received.
+//     "confirm" |  sender user ID    |  A channel request has been accepted.
+//     "silent"  |  sender user ID    |  A message where the user should not be notified.
+//     "e2e"     |  sender user ID    |  A reception of an E2E message.
+//     "group"   |  group ID          |  A reception of a group chat message.
+//     "endFT"   |  sender user ID    |  The last message sent confirming end of file transfer.
+//     "groupRQ" |  sender user ID    |  A request from Source to join a group chat.
+//  todo iterate over this docstring, ensure descriptions/sources are
+//    still accurate (they are from the old implementation
+type NotificationReport struct {
+	// ForMe determines whether this value is for the user. If it is
+	// false, this report may be ignored.
+	ForMe bool
+	// Type is the type of notification. The list can be seen
+	Type string
+	// Source is the source of the notification.
 	Source []byte
 }
 
-type ManyNotificationForMeReport struct {
-	Many []*NotificationForMeReport
-}
+// GetNotificationsReport parses the received notification data to determine which
+// notifications are for this user. // This returns the JSON-marshalled
+// NotificationReports.
+//
+// Parameters:
+//  - e2eID - e2e object ID in the tracker
+//  - notificationCSV - the notification data received from the
+//    notifications' server.
+//  - marshalledServices - the JSON-marshalled list of services the backend
+//    keeps track of. Refer to Cmix.TrackServices for information about this.
+//
+// Returns:
+//  - []byte - A JSON marshalled NotificationReports. Some NotificationReport's
+//    within in this structure may have their NotificationReport.ForMe
+//    set to false. These may be ignored.
+func GetNotificationsReport(e2eId int, notificationCSV string,
+	marshalledServices []byte) ([]byte, error) {
+	// Retrieve user
+	user, err := e2eTrackerSingleton.get(e2eId)
+	if err != nil {
+		return nil, err
+	}
 
-// NotificationsForMe Check if a notification received is for me
-// It returns a NotificationForMeReport which contains a ForMe bool stating if it is for the caller,
-// a Type, and a source. These are as follows:
-//	TYPE       	SOURCE				DESCRIPTION
-// 	"default"	recipient user ID	A message with no association
-//	"request"	sender user ID		A channel request has been received
-//	"reset"	    sender user ID		A channel reset has been received
-//	"confirm"	sender user ID		A channel request has been accepted
-//	"silent"	sender user ID		A message which should not be notified on
-//	"e2e"		sender user ID		reception of an E2E message
-//	"group"		group ID			reception of a group chat message
-//  "endFT"     sender user ID		Last message sent confirming end of file transfer
-//  "groupRQ"   sender user ID		Request from sender to join a group chat
-func NotificationsForMe(notifCSV, preimages string) (*ManyNotificationForMeReport, error) {
-	// Handle deserialization of preimages
-	var preimageList []edge.Preimage
-	if err := json.Unmarshal([]byte(preimages), &preimageList); err != nil {
-		return nil, errors.WithMessagef(err, "Failed to unmarshal the " +
-			"preimages list, cannot check if notification is for me")
+	serviceList := message.ServiceList{}
+	err = json.Unmarshal(marshalledServices, &serviceList)
+	if err != nil {
+		return nil, err
 	}
 
-	list, err := notifications.DecodeNotificationsCSV(notifCSV)
+	// Retrieve the services for this user
+	services := serviceList[*user.api.GetReceptionIdentity().ID]
+
+	// Decode notifications' server data
+	notificationList, err := notifications.DecodeNotificationsCSV(notificationCSV)
 	if err != nil {
 		return nil, err
 	}
 
-	notifList := make([]*NotificationForMeReport, len(list))
+	// Construct  a report list
+	reportList := make([]*NotificationReport, len(notificationList))
 
-	for i, notifData := range list {
-		notifList[i] = &NotificationForMeReport{
-			ForMe:  false,
-			Type:   "",
-			Source: nil,
-		}
-		// check if any preimages match with the passed in data
-		for _, preimage := range preimageList {
-			if fingerprint.CheckIdentityFpFromMessageHash(notifData.IdentityFP, notifData.MessageHash, preimage.Data) {
-				notifList[i] = &NotificationForMeReport{
+	// Iterate over data provided by server
+	for i := range notificationList {
+		notifData := notificationList[i]
+
+		// Iterate over all services
+		for j := range services {
+			// Pull data from services and from notification data
+			service := services[j]
+			messageHash := notifData.MessageHash
+			hash := service.HashFromMessageHash(notifData.MessageHash)
+
+			// Check if this notification data is recognized by
+			// this service, ie "ForMe"
+			if service.ForMeFromMessageHash(messageHash, hash) {
+				// Fill report list with service data
+				reportList[i] = &NotificationReport{
 					ForMe:  true,
-					Type:   preimage.Type,
-					Source: preimage.Source,
+					Type:   service.Tag,
+					Source: service.Identifier,
 				}
-				break
 			}
 		}
 	}
 
-	return &ManyNotificationForMeReport{notifList}, nil
-}*/
+	return json.Marshal(reportList)
+}
 
 // RegisterForNotifications allows a client to register for push notifications.
 // The token is a firebase messaging token.
diff --git a/bindings/notifications_test.go b/bindings/notifications_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..390062f08456961cb3e18eb84675e64f18e867b8
--- /dev/null
+++ b/bindings/notifications_test.go
@@ -0,0 +1,28 @@
+package bindings
+
+import (
+	"encoding/json"
+	"fmt"
+	"gitlab.com/elixxir/client/e2e/ratchet"
+	"gitlab.com/xx_network/primitives/id"
+	"testing"
+)
+
+func TestNotificationReport(t *testing.T) {
+	reports := []NotificationReport{}
+
+	for i := 0; i < 3; i++ {
+		nr := NotificationReport{
+			ForMe:  true,
+			Type:   ratchet.E2e,
+			Source: id.NewIdFromUInt(uint64(i), id.User, t).Bytes(),
+		}
+
+		reports = append(reports, nr)
+	}
+
+	nrs := NotificationReports(reports)
+
+	marshal, _ := json.Marshal(nrs)
+	fmt.Printf("%s\n", marshal)
+}
diff --git a/cmix/message/serviceTracker.go b/cmix/message/serviceTracker.go
index 616f6dfda392ba4cb65c8d02179bbae493fe26ec..e3313a4de659d935b26d6e4477c1e5056a558497 100644
--- a/cmix/message/serviceTracker.go
+++ b/cmix/message/serviceTracker.go
@@ -26,7 +26,6 @@ func (sm *ServicesManager) triggerServiceTracking() {
 	if len(sm.trackers) == 0 {
 		return
 	}
-
 	services := make(ServiceList)
 	for uid, tmap := range sm.tmap {
 		tList := make([]Service, 0, len(tmap))
diff --git a/cmix/message/serviceTracker_test.go b/cmix/message/serviceTracker_test.go
index c7b06b46a853bcc23e267830c9e2cda925385b3a..a1a487762c271bde32476a07652cfd4264b311bf 100644
--- a/cmix/message/serviceTracker_test.go
+++ b/cmix/message/serviceTracker_test.go
@@ -13,7 +13,7 @@ import (
 
 func TestServiceList_Marshal_UnmarshalJSON(t *testing.T) {
 	var sl ServiceList = make(map[id.ID][]Service)
-	numServices := 10
+	numServices := 3
 	testString := "test"
 	for i := 0; i < numServices; i++ {
 		uid := id.NewIdFromUInt(uint64(i), id.User, t)
@@ -24,6 +24,8 @@ func TestServiceList_Marshal_UnmarshalJSON(t *testing.T) {
 		t.Errorf(err.Error())
 	}
 
+	t.Logf("%s", jsonResult)
+
 	sl = make(map[id.ID][]Service)
 	err = sl.UnmarshalJSON(jsonResult)
 	if err != nil {