diff --git a/bindings/group.go b/bindings/group.go
index 787b17884aebc80038d379168f53fd442073517d..6976022f4aadae1542ad7d7d9ce917aa6c04d61e 100644
--- a/bindings/group.go
+++ b/bindings/group.go
@@ -22,57 +22,57 @@ import (
 )
 
 ////////////////////////////////////////////////////////////////////////////////
-// Group Chat Singleton Tracker                                               //
+// Group Singleton Tracker                                               //
 ////////////////////////////////////////////////////////////////////////////////
 
-// groupChatTrackerSingleton is used to track GroupChat objects so that they can be
+// groupTrackerSingleton is used to track Group objects so that they can be
 // referenced by ID back over the bindings.
-var groupChatTrackerSingleton = &groupChatTracker{
-	tracked: make(map[int]*GroupChat),
+var groupTrackerSingleton = &groupTracker{
+	tracked: make(map[int]*Group),
 	count:   0,
 }
 
-// groupChatTracker is a singleton used to keep track of extant GroupChat objects,
+// groupTracker is a singleton used to keep track of extant Group objects,
 // preventing race conditions created by passing it over the bindings.
-type groupChatTracker struct {
-	tracked map[int]*GroupChat
+type groupTracker struct {
+	tracked map[int]*Group
 	count   int
 	mux     sync.RWMutex
 }
 
-// make create a GroupChat from a groupChat.Wrapper, assigns it a unique ID, and
+// make create a Group from a groupStore.Group, assigns it a unique ID, and
 // adds it to the groupChatTracker.
-func (ut *groupChatTracker) make(gcInt gc.GroupChat) *GroupChat {
+func (ut *groupTracker) make(g gs.Group) *Group {
 	ut.mux.Lock()
 	defer ut.mux.Unlock()
 
 	id := ut.count
 	ut.count++
 
-	ut.tracked[id] = &GroupChat{
-		m:  gc.NewWrapper(gcInt),
+	ut.tracked[id] = &Group{
+		g:  g,
 		id: id,
 	}
 
 	return ut.tracked[id]
 }
 
-// get an GroupChat from the groupChatTracker given its ID.
-func (ut *groupChatTracker) get(id int) (*GroupChat, error) {
+// get a Group from the groupChatTracker given its ID.
+func (ut *groupTracker) get(id int) (*Group, error) {
 	ut.mux.RLock()
 	defer ut.mux.RUnlock()
 
-	c, exist := ut.tracked[id]
+	g, exist := ut.tracked[id]
 	if !exist {
 		return nil, errors.Errorf(
-			"Cannot get GroupChat for ID %d, does not exist", id)
+			"Cannot get Group for ID %d, does not exist", id)
 	}
 
-	return c, nil
+	return g, nil
 }
 
-// delete removes a GroupChat from the groupChatTracker.
-func (ut *groupChatTracker) delete(id int) {
+// delete removes a Group from the groupTracker.
+func (ut *groupTracker) delete(id int) {
 	ut.mux.Lock()
 	defer ut.mux.Unlock()
 
@@ -85,33 +85,17 @@ func (ut *groupChatTracker) delete(id int) {
 
 // GroupChat is a binding-layer group chat manager.
 type GroupChat struct {
-	m  *gc.Wrapper
-	id int
-}
-
-// GroupRequest is a bindings-layer interface that handles a group reception.
-//
-// Parameters:
-//  - payload - a byte serialized representation of a group.
-type GroupRequest interface {
-	Callback(payload Group)
+	m *gc.Wrapper
 }
 
 // LoadOrNewGroupChat creates a bindings-layer group chat manager.
 //
 // Parameters:
 //  - e2eID - e2e object ID in the tracker.
-//  - groupID - GroupChat object ID in the tracker, given from previous call
-//    to LoadOrNewGroupChat.
 //  - requestFunc - a callback to handle group chat requests.
 //  - processor - the group chat message processor.
-func LoadOrNewGroupChat(e2eID, groupID int, requestFunc GroupRequest,
-	processor GroupChatProcessor) (*GroupChat, error) {
-	// Retrieve from singleton
-	groupChat, err := groupChatTrackerSingleton.get(groupID)
-	if err == nil { // If present, return group chat manager from singleton
-		return groupChat, nil
-	}
+func LoadOrNewGroupChat(e2eID int,
+	requestFunc GroupRequest, processor GroupChatProcessor) (*GroupChat, error) {
 
 	// Get user from singleton
 	user, err := e2eTrackerSingleton.get(e2eID)
@@ -121,12 +105,8 @@ func LoadOrNewGroupChat(e2eID, groupID int, requestFunc GroupRequest,
 
 	// Construct a wrapper for the request callback
 	requestCb := func(g gs.Group) {
-		//fixme: review this to see if should be json marshaled.
-		// At the moment, groupStore.DhKeyList is an unsupported
-		// type, it would need a MarshalJson method. If we JSON marshal, change
-		// JoinGroup implementation and docstring accordingly.
-		// As for now, it's matching the construction as defined pre-restructure.
-		requestFunc.Callback(Group{g: g})
+		newGroup := groupTrackerSingleton.make(g)
+		requestFunc.Callback(newGroup.id)
 	}
 
 	// Construct a group chat manager
@@ -137,12 +117,8 @@ func LoadOrNewGroupChat(e2eID, groupID int, requestFunc GroupRequest,
 	}
 
 	// Construct wrapper
-	return groupChatTrackerSingleton.make(gcInt), nil
-}
-
-// GetID returns the groupChatTracker ID for the GroupChat object.
-func (g *GroupChat) GetID() int {
-	return g.id
+	wrapper := gc.NewWrapper(gcInt)
+	return &GroupChat{m: wrapper}, nil
 }
 
 // MakeGroup creates a new Group and sends a group request to all members in the
@@ -226,9 +202,22 @@ func (g *GroupChat) ResendRequest(groupId []byte) ([]byte, error) {
 // JoinGroup allows a user to join a group when a request is received.
 //
 // Parameters:
-//  - group - a bindings-level Group object. This is received by GroupRequest.Callback.
-func (g *GroupChat) JoinGroup(group Group) error {
-	return g.m.JoinGroup(group.g)
+//  - trackedGroupId - the ID to retrieve the Group object within the backend's
+//                     tracking system.
+func (g *GroupChat) JoinGroup(trackedGroupId int) error {
+	// Retrieve group from singleton
+	grp, err := groupTrackerSingleton.get(trackedGroupId)
+	if err != nil {
+		return err
+	}
+
+	// Join group
+	err = g.m.JoinGroup(grp.g)
+	if err != nil {
+		return err
+	}
+
+	return nil
 }
 
 // LeaveGroup deletes a group so a user no longer has access.
@@ -288,26 +277,21 @@ func (g *GroupChat) GetGroups() ([]byte, error) {
 	return json.Marshal(groupIds)
 }
 
-// GetGroup returns the group with the group ID. If no group exists, then the
-// error "failed to find group" is returned.
+// GetGroup returns the Group with the tracked ID from the backend's Group tracker.
 //
 // Parameters:
-//  - groupId - the byte data representing a group ID.
-//    This can be pulled from a marshalled GroupReport.
+//  - trackedGroupId - the ID to retrieve the Group object within the backend's
+//                     tracking system.
 // Returns:
-//  - Group - the bindings-layer representation of a Group.
-func (g *GroupChat) GetGroup(groupId []byte) (*Group, error) {
-	groupID, err := id.Unmarshal(groupId)
+//  - Group - the bindings-layer representation of a group.
+func (g *GroupChat) GetGroup(trackedGroupId int) (*Group, error) {
+	// Retrieve group from singleton
+	group, err := groupTrackerSingleton.get(trackedGroupId)
 	if err != nil {
-		return nil, errors.Errorf("Failed to unmarshal group ID: %+v", err)
-	}
-
-	grp, exists := g.m.GetGroup(groupID)
-	if !exists {
-		return nil, errors.New("failed to find group")
+		return nil, err
 	}
 
-	return &Group{g: grp}, nil
+	return group, nil
 }
 
 // NumGroups returns the number of groups the user is a part of.
@@ -322,7 +306,8 @@ func (g *GroupChat) NumGroups() int {
 // Group structure contains the identifying and membership information of a
 // group chat.
 type Group struct {
-	g gs.Group
+	g  gs.Group
+	id int
 }
 
 // GetName returns the name set by the user for the group.
@@ -369,9 +354,18 @@ func (g *Group) Serialize() []byte {
 }
 
 //////////////////////////////////////////////////////////////////////////////////
-// Group Chat Processor
+// Callbacks
 //////////////////////////////////////////////////////////////////////////////////
 
+// GroupRequest is a bindings-layer interface that handles a group reception.
+//
+// Parameters:
+//  - trackedGroupId - the ID to retrieve the Group object within the backend's
+//                     tracking system.
+type GroupRequest interface {
+	Callback(trackedGroupId int)
+}
+
 // GroupChatProcessor manages the handling of received group chat messages.
 type GroupChatProcessor interface {
 	Process(decryptedMessage, msg, receptionId []byte, ephemeralId,