diff --git a/e2e/ratchet/interface.go b/e2e/ratchet/interface.go
index 889dba56feede2f1953dfb7c03ba1224533f5ee4..4e1bb580bf4266eb7791426043d75ec48356ae3f 100644
--- a/e2e/ratchet/interface.go
+++ b/e2e/ratchet/interface.go
@@ -2,17 +2,22 @@ package ratchet
 
 import (
 	"github.com/cloudflare/circl/dh/sidh"
+	"gitlab.com/elixxir/client/e2e/ratchet/partner"
 	"gitlab.com/elixxir/client/e2e/ratchet/partner/session"
 	"gitlab.com/elixxir/client/network/message"
 	"gitlab.com/elixxir/crypto/cyclic"
 	"gitlab.com/xx_network/primitives/id"
 )
 
-type Ratchet interface {
+type Ratchet2 interface {
+	// AddPartner adds a partner. Automatically creates both send and receive
+	// sessions using the passed cryptographic data and per the parameters sent
+	//
 	AddPartner(partnerID *id.ID, partnerPubKey, myPrivKey *cyclic.Int,
 		partnerSIDHPubKey *sidh.PublicKey, mySIDHPrivKey *sidh.PrivateKey,
 		sendParams, receiveParams session.Params)
-	GetPartner(partnerID *id.ID) (*Manager, error)
+
+	GetPartner(partnerID *id.ID) (*partner.Manager, error)
 	DeletePartner(partnerId *id.ID)
 	GetAllPartnerIDs() []*id.ID
 	GetDHPrivateKey() *cyclic.Int
diff --git a/e2e/ratchet/partner/manager.go b/e2e/ratchet/partner/manager.go
index d9643ca39dc4b4051d6681f10414735e3168f010..f32c5224fdc9d9b72b7f0aba01b72024b31d7477 100644
--- a/e2e/ratchet/partner/manager.go
+++ b/e2e/ratchet/partner/manager.go
@@ -90,7 +90,7 @@ func NewManager(kv *versioned.KV, myID, partnerID *id.ID, myPrivKey,
 	return m
 }
 
-//loads a relationship and all buffers and sessions from disk
+//LoadManager loads a relationship and all buffers and sessions from disk
 func LoadManager(kv *versioned.KV, myID, partnerID *id.ID,
 	cyHandler session.CypherHandler, grp *cyclic.Group,
 	rng *fastRNG.StreamGenerator) (*Manager, error) {
diff --git a/e2e/ratchet/partner/relationship.go b/e2e/ratchet/partner/relationship.go
index 571f255d1d5d47dae69430f97d7e0f1f67b21a26..9f080d7c9fb998b2153713901b177e778ccb9c0c 100644
--- a/e2e/ratchet/partner/relationship.go
+++ b/e2e/ratchet/partner/relationship.go
@@ -58,6 +58,7 @@ type ServiceHandler interface {
 // fixme - this is weird becasue it creates the relationsip and the session.
 // Should be refactored to create an empty relationship, with a second call
 // adding the session
+// todo - doscstring
 func NewRelationship(kv *versioned.KV, t session.RelationshipType,
 	myID, partnerID *id.ID, myOriginPrivateKey,
 	partnerOriginPublicKey *cyclic.Int, originMySIDHPrivKey *sidh.PrivateKey,
@@ -110,6 +111,7 @@ func NewRelationship(kv *versioned.KV, t session.RelationshipType,
 	return r
 }
 
+// todo - doscstring
 func LoadRelationship(kv *versioned.KV, t session.RelationshipType, myID,
 	partnerID *id.ID, cyHandler session.CypherHandler, grp *cyclic.Group,
 	rng *fastRNG.StreamGenerator) (*relationship, error) {
@@ -223,6 +225,7 @@ func (r *relationship) unmarshal(b []byte) error {
 	return nil
 }
 
+// todo - doscstring
 func (r *relationship) Delete() {
 	r.mux.Lock()
 	defer r.mux.Unlock()
@@ -232,6 +235,7 @@ func (r *relationship) Delete() {
 	}
 }
 
+// todo - doscstring
 func (r *relationship) AddSession(myPrivKey, partnerPubKey, baseKey *cyclic.Int,
 	mySIDHPrivKey *sidh.PrivateKey, partnerSIDHPubKey *sidh.PublicKey,
 	trigger session.SessionID, negotiationStatus session.Negotiation,
@@ -252,12 +256,14 @@ func (r *relationship) AddSession(myPrivKey, partnerPubKey, baseKey *cyclic.Int,
 	return s
 }
 
+// todo - doscstring
 func (r *relationship) addSession(s *session.Session) {
 	r.sessions = append([]*session.Session{s}, r.sessions...)
 	r.sessionByID[s.GetID()] = s
 	return
 }
 
+// todo - doscstring
 func (r *relationship) GetNewest() *session.Session {
 	r.mux.RLock()
 	defer r.mux.RUnlock()
@@ -328,6 +334,7 @@ func (r *relationship) getSessionForSending() *session.Session {
 	return nil
 }
 
+// todo - doscstring
 // returns a list of session that need rekeys. Nil instances mean a new rekey
 // from scratch
 func (r *relationship) TriggerNegotiation() []*session.Session {
@@ -386,12 +393,14 @@ func (r *relationship) getNewestRekeyableSession() *session.Session {
 	return unconfirmed
 }
 
+// todo - doscstring
 func (r *relationship) GetByID(id session.SessionID) *session.Session {
 	r.mux.RLock()
 	defer r.mux.RUnlock()
 	return r.sessionByID[id]
 }
 
+// todo - doscstring
 // sets the passed session ID as confirmed. Call "GetSessionRotation" after
 // to get any sessions that are to be deleted and then "DeleteSession" to
 // remove them
@@ -420,6 +429,7 @@ func (r *relationship) getInternalBufferShallowCopy() []*session.Session {
 	return r.sessions
 }
 
+// todo - doscstring
 func (r *relationship) clean() {
 
 	numConfirmed := uint(0)
diff --git a/e2e/ratchet/partner/session/session.go b/e2e/ratchet/partner/session/session.go
index 9b0543ac70ceb803a946683db443ab3f46230545..33970009fc6d92ed6bbe0db02385ba57e52fc155 100644
--- a/e2e/ratchet/partner/session/session.go
+++ b/e2e/ratchet/partner/session/session.go
@@ -182,7 +182,7 @@ func NewSession(kv *versioned.KV, t RelationshipType, partner *id.ID, myPrivKey,
 	return session
 }
 
-// Load session and state vector from kv and populate runtime fields
+// LoadSession and state vector from kv and populate runtime fields
 func LoadSession(kv *versioned.KV, sessionID SessionID,
 	relationshipFingerprint []byte, cyHandler CypherHandler,
 	grp *cyclic.Group, rng *fastRNG.StreamGenerator) (*Session, error) {
@@ -220,6 +220,7 @@ func LoadSession(kv *versioned.KV, sessionID SessionID,
 	return &session, nil
 }
 
+// todo - doscstring
 func (s *Session) Save() error {
 
 	now := netTime.Now()
@@ -404,7 +405,8 @@ func (s *Session) unmarshal(b []byte) error {
 }
 
 //key usage
-// Pops the first unused key, skipping any which are denoted as used.
+
+// Popkey Pops the first unused key, skipping any which are denoted as used.
 // will return if the remaining keys are designated as rekeys
 func (s *Session) PopKey() (*Cypher, error) {
 	if s.keyState.GetNumAvailable() <= uint32(s.e2eParams.NumRekeys) {
@@ -428,6 +430,7 @@ func (s *Session) PopReKey() (*Cypher, error) {
 	return newKey(s, keyNum), nil
 }
 
+// todo - doscstring
 func (s *Session) GetRelationshipFingerprint() []byte {
 	return s.relationshipFingerprint
 }
@@ -476,12 +479,14 @@ var legalStateChanges = [][]bool{
 	{false, false, true, false, false, false},  // NewCreat
 }
 
+// todo - doscstring
 func (s *Session) SetNegotiationStatus(status Negotiation) {
 	if err := s.TrySetNegotiationStatus(status); err != nil {
 		jww.FATAL.Panicf("Failed to set Negotiation status: %s", err)
 	}
 }
 
+// todo - doscstring
 func (s *Session) TrySetNegotiationStatus(status Negotiation) error {
 	s.mux.Lock()
 	defer s.mux.Unlock()
@@ -512,7 +517,7 @@ func (s *Session) TrySetNegotiationStatus(status Negotiation) error {
 	return nil
 }
 
-// This function, in a mostly thread safe manner, checks if the session needs a
+// TriggerNegotiation in a mostly thread safe manner, checks if the session needs a
 // negotiation, returns if it does while updating the session to denote the
 // negotiation was triggered
 // WARNING: This function relies on proper action by the caller for data safety.
@@ -578,20 +583,21 @@ func (s *Session) TriggerNegotiation() bool {
 	return false
 }
 
-// checks if the session has been confirmed
+// NegotiationStatus checks if the session has been confirmed
 func (s *Session) NegotiationStatus() Negotiation {
 	s.mux.RLock()
 	defer s.mux.RUnlock()
 	return s.negotiationStatus
 }
 
-// checks if the session has been confirmed
+// IsConfirmed checks if the session has been confirmed
 func (s *Session) IsConfirmed() bool {
 	c := s.NegotiationStatus()
 	//fmt.Println(c)
 	return c >= Confirmed
 }
 
+// todo - doscstring
 func (s *Session) String() string {
 	partner := s.GetPartner()
 	if partner != nil {
@@ -607,6 +613,7 @@ func (s *Session) useKey(keynum uint32) {
 	s.keyState.Use(keynum)
 }
 
+// todo - doscstring
 // finalizeKeyNegotiation generates keys from the base data stored in the session object.
 // myPrivKey will be generated if not present
 func (s *Session) finalizeKeyNegotiation() {
@@ -635,6 +642,7 @@ func (s *Session) finalizeKeyNegotiation() {
 	s.sID = GetSessionIDFromBaseKey(s.baseKey)
 }
 
+// todo - doscstring
 func (s *Session) buildChildKeys() {
 	p := s.e2eParams
 	h, _ := hash.NewCMixHash()
@@ -687,6 +695,7 @@ func MakeSessionPrefix(sid SessionID) string {
 	return fmt.Sprintf(sessionPrefix, sid)
 }
 
+// todo - doscstring
 func decideIfResendRekey(genRng *fastRNG.StreamGenerator, ratio float64) bool {
 	stream := genRng.GetStream()
 	b := make([]byte, 8)
diff --git a/e2e/ratchet/serviceList.go b/e2e/ratchet/serviceList.go
index 3f4d2747c4f481f42e3d417df6dee1d707a7f525..1f6fb32e824e9ada47a5ea2ebf9ff33abd10a6bf 100644
--- a/e2e/ratchet/serviceList.go
+++ b/e2e/ratchet/serviceList.go
@@ -15,53 +15,53 @@ type Services interface {
 		processor message.Processor)
 }
 
-func (s *Store) add(m *partner.Manager) {
-	s.servicesmux.RLock()
-	defer s.servicesmux.RUnlock()
-	for tag, process := range s.services {
-		s.sInteface.AddService(s.myID, m.MakeService(tag), process)
+func (r *Ratchet) add(m *partner.Manager) {
+	r.servicesmux.RLock()
+	defer r.servicesmux.RUnlock()
+	for tag, process := range r.services {
+		r.sInteface.AddService(r.myID, m.MakeService(tag), process)
 	}
 }
 
-func (s *Store) delete(m *partner.Manager) {
-	s.servicesmux.RLock()
-	defer s.servicesmux.RUnlock()
-	for tag, process := range s.services {
-		s.sInteface.DeleteService(s.myID, m.MakeService(tag), process)
+func (r *Ratchet) delete(m *partner.Manager) {
+	r.servicesmux.RLock()
+	defer r.servicesmux.RUnlock()
+	for tag, process := range r.services {
+		r.sInteface.DeleteService(r.myID, m.MakeService(tag), process)
 	}
 }
 
-func (s *Store) AddService(tag string, processor message.Processor) error {
-	s.servicesmux.Lock()
-	defer s.servicesmux.Unlock()
+func (r *Ratchet) AddService(tag string, processor message.Processor) error {
+	r.servicesmux.Lock()
+	defer r.servicesmux.Unlock()
 	//add the services to the list
-	if _, exists := s.services[tag]; exists {
-		return errors.Errorf("Cannot add more than one service '%s'", tag)
+	if _, exists := r.services[tag]; exists {
+		return errors.Errorf("Cannot add more than one service '%r'", tag)
 	}
-	s.services[tag] = processor
+	r.services[tag] = processor
 
 	//add a service for every manager
-	for _, m := range s.managers {
-		s.sInteface.AddService(s.myID, m.MakeService(tag), processor)
+	for _, m := range r.managers {
+		r.sInteface.AddService(r.myID, m.MakeService(tag), processor)
 	}
 
 	return nil
 }
 
-func (s *Store) RemoveService(tag string) error {
-	s.servicesmux.Lock()
-	defer s.servicesmux.Unlock()
+func (r *Ratchet) RemoveService(tag string) error {
+	r.servicesmux.Lock()
+	defer r.servicesmux.Unlock()
 
-	oldServiceProcess, exists := s.services[tag]
+	oldServiceProcess, exists := r.services[tag]
 	if !exists {
 		return errors.Errorf("Cannot remove a service that doesnt "+
-			"exist: '%s'", tag)
+			"exist: '%r'", tag)
 	}
 
-	delete(s.services, tag)
+	delete(r.services, tag)
 
-	for _, m := range s.managers {
-		s.sInteface.DeleteService(s.myID, m.MakeService(tag), oldServiceProcess)
+	for _, m := range r.managers {
+		r.sInteface.DeleteService(r.myID, m.MakeService(tag), oldServiceProcess)
 	}
 
 	return nil
diff --git a/e2e/ratchet/standardServices.go b/e2e/ratchet/standardServices.go
new file mode 100644
index 0000000000000000000000000000000000000000..0d28c336b789e6ba182fcbb7c85a04fceed06f2e
--- /dev/null
+++ b/e2e/ratchet/standardServices.go
@@ -0,0 +1,4 @@
+package ratchet
+
+const Silent = "silent"
+const E2e = "e2e"
diff --git a/e2e/ratchet/store.go b/e2e/ratchet/store.go
index 193b05dc8038042e7da42b4c6b839017ec1fd62f..0cf1ca902210122ab812113ddc3a7c28c57f6570 100644
--- a/e2e/ratchet/store.go
+++ b/e2e/ratchet/store.go
@@ -28,16 +28,14 @@ import (
 const (
 	currentStoreVersion = 0
 	packagePrefix       = "e2eSession"
-	storeKey            = "Store"
+	storeKey            = "Ratchet"
 	pubKeyKey           = "DhPubKey"
 	privKeyKey          = "DhPrivKey"
-	sidhPubKeyKey       = "SidhPubKey"
-	sidhPrivKeyKey      = "SidhPrivKey"
 )
 
 var NoPartnerErrorStr = "No relationship with partner found"
 
-type Store struct {
+type Ratchet struct {
 	managers map[id.ID]*partner.Manager
 	mux      sync.RWMutex
 
@@ -57,17 +55,23 @@ type Store struct {
 	kv *versioned.KV
 }
 
-func NewStore(kv *versioned.KV, privKey *cyclic.Int,
+// NewRatchet creates a new store for the passed user id and private key.
+// The store can then be accessed by calling LoadStore.
+// Does not create at a unique prefix, if multiple Ratchets are needed, make
+// sure to add a uint prefix to the KV before instantiation.
+func NewRatchet(kv *versioned.KV, privKey *cyclic.Int,
 	myID *id.ID, grp *cyclic.Group, cyHandler session.CypherHandler,
-	rng *fastRNG.StreamGenerator) (*Store, error) {
+	services Services, rng *fastRNG.StreamGenerator) error {
+
 	// Generate public key
 	pubKey := diffieHellman.GeneratePublicKey(privKey, grp)
 
 	// Modify the prefix of the KV
 	kv = kv.Prefix(packagePrefix)
 
-	s := &Store{
+	r := &Ratchet{
 		managers: make(map[id.ID]*partner.Manager),
+		services: make(map[string]message.Processor),
 
 		myID:         myID,
 		dhPrivateKey: privKey,
@@ -78,30 +82,33 @@ func NewStore(kv *versioned.KV, privKey *cyclic.Int,
 		cyHandler: cyHandler,
 		grp:       grp,
 		rng:       rng,
+		sInteface: services,
 	}
 
 	err := util.StoreCyclicKey(kv, pubKey, pubKeyKey)
 	if err != nil {
-		return nil, errors.WithMessage(err,
+		return errors.WithMessage(err,
 			"Failed to store e2e DH public key")
 	}
 
 	err = util.StoreCyclicKey(kv, privKey, privKeyKey)
 	if err != nil {
-		return nil, errors.WithMessage(err,
+		return errors.WithMessage(err,
 			"Failed to store e2e DH private key")
 	}
 
-	return s, s.save()
+	return r.save()
 }
 
-func LoadStore(kv *versioned.KV, myID *id.ID, grp *cyclic.Group,
-	cyHandler session.CypherHandler, rng *fastRNG.StreamGenerator) (
-	*Store, error) {
+// LoadRatchet loads an extant ratchet from disk
+func LoadRatchet(kv *versioned.KV, myID *id.ID, grp *cyclic.Group,
+	cyHandler session.CypherHandler, services Services, rng *fastRNG.StreamGenerator) (
+	*Ratchet, error) {
 	kv = kv.Prefix(packagePrefix)
 
-	s := &Store{
+	r := &Ratchet{
 		managers: make(map[id.ID]*partner.Manager),
+		services: make(map[string]message.Processor),
 
 		myID: myID,
 
@@ -110,6 +117,7 @@ func LoadStore(kv *versioned.KV, myID *id.ID, grp *cyclic.Group,
 		cyHandler: cyHandler,
 		grp:       grp,
 		rng:       rng,
+		sInteface: services,
 	}
 
 	obj, err := kv.Get(storeKey, currentStoreVersion)
@@ -117,18 +125,28 @@ func LoadStore(kv *versioned.KV, myID *id.ID, grp *cyclic.Group,
 		return nil, err
 	}
 
-	err = s.unmarshal(obj.Data)
+	err = r.unmarshal(obj.Data)
 	if err != nil {
 		return nil, err
 	}
 
-	return s, nil
+	// add standard services
+	if err = r.AddService(Silent, nil); err != nil {
+		jww.FATAL.Panicf("Could not add standard %r "+
+			"service: %+v", Silent, err)
+	}
+	if err = r.AddService(E2e, nil); err != nil {
+		jww.FATAL.Panicf("Could not add standard %r "+
+			"service: %+v", E2e, err)
+	}
+
+	return r, nil
 }
 
-func (s *Store) save() error {
+func (r *Ratchet) save() error {
 	now := netTime.Now()
 
-	data, err := s.marshal()
+	data, err := r.marshal()
 	if err != nil {
 		return err
 	}
@@ -139,59 +157,69 @@ func (s *Store) save() error {
 		Data:      data,
 	}
 
-	return s.kv.Set(storeKey, currentStoreVersion, &obj)
+	return r.kv.Set(storeKey, currentStoreVersion, &obj)
 }
 
-func (s *Store) AddPartner(partnerID *id.ID, partnerPubKey,
+// AddPartner adds a partner. Automatically creates both send and receive
+// sessions using the passed cryptographic data and per the parameters sent
+func (r *Ratchet) AddPartner(partnerID *id.ID, partnerPubKey,
 	myPrivKey *cyclic.Int, partnerSIDHPubKey *sidh.PublicKey,
 	mySIDHPrivKey *sidh.PrivateKey, sendParams,
-	receiveParams session.Params) error {
-	s.mux.Lock()
-	defer s.mux.Unlock()
+	receiveParams session.Params) (*partner.Manager, error) {
+	r.mux.Lock()
+	defer r.mux.Unlock()
 
-	jww.INFO.Printf("Adding Partner %s:\n\tMy Private Key: %s"+
-		"\n\tPartner Public Key: %s",
+	jww.INFO.Printf("Adding Partner %r:\n\tMy Private Key: %r"+
+		"\n\tPartner Public Key: %r",
 		partnerID,
 		myPrivKey.TextVerbose(16, 0),
 		partnerPubKey.TextVerbose(16, 0))
 
-	if _, ok := s.managers[*partnerID]; ok {
-		return errors.New("Cannot overwrite existing partner")
+	if _, ok := r.managers[*partnerID]; ok {
+		return nil, errors.New("Cannot overwrite existing partner")
 	}
 
-	m := partner.NewManager(s.kv, s.myID, partnerID, myPrivKey, partnerPubKey,
+	m := partner.NewManager(r.kv, r.myID, partnerID, myPrivKey, partnerPubKey,
 		mySIDHPrivKey, partnerSIDHPubKey,
-		sendParams, receiveParams, s.cyHandler, s.grp, s.rng)
+		sendParams, receiveParams, r.cyHandler, r.grp, r.rng)
 
-	s.managers[*partnerID] = m
-	if err := s.save(); err != nil {
-		jww.FATAL.Printf("Failed to add Partner %s: Save of store failed: %s",
+	r.managers[*partnerID] = m
+	if err := r.save(); err != nil {
+		jww.FATAL.Printf("Failed to add Partner %r: Save of store failed: %r",
 			partnerID, err)
 	}
 
-	return nil
+	//add services for the manager
+	r.add(m)
+
+	return m, nil
 }
 
 // DeletePartner removes the associated contact from the E2E store
-func (s *Store) DeletePartner(partnerId *id.ID) error {
-	m, ok := s.managers[*partnerId]
+func (r *Ratchet) DeletePartner(partnerId *id.ID) error {
+	m, ok := r.managers[*partnerId]
 	if !ok {
 		return errors.New(NoPartnerErrorStr)
 	}
 
-	if err := partner.ClearManager(m, s.kv); err != nil {
-		return errors.WithMessagef(err, "Could not remove partner %s from store", partnerId)
+	if err := partner.ClearManager(m, r.kv); err != nil {
+		return errors.WithMessagef(err, "Could not remove partner %r from store", partnerId)
 	}
 
-	delete(s.managers, *partnerId)
-	return s.save()
+	//delete services
+	r.delete(m)
+
+	delete(r.managers, *partnerId)
+	return r.save()
+
 }
 
-func (s *Store) GetPartner(partnerID *id.ID) (*partner.Manager, error) {
-	s.mux.RLock()
-	defer s.mux.RUnlock()
+// GetPartner returns the partner per its ID, if it exists
+func (r *Ratchet) GetPartner(partnerID *id.ID) (*partner.Manager, error) {
+	r.mux.RLock()
+	defer r.mux.RUnlock()
 
-	m, ok := s.managers[*partnerID]
+	m, ok := r.managers[*partnerID]
 
 	if !ok {
 		return nil, errors.New(NoPartnerErrorStr)
@@ -202,13 +230,13 @@ func (s *Store) GetPartner(partnerID *id.ID) (*partner.Manager, error) {
 
 // GetAllPartnerIDs returns a list of all partner IDs that the user has
 // an E2E relationship with.
-func (s *Store) GetAllPartnerIDs() []*id.ID {
-	s.mux.RLock()
-	defer s.mux.RUnlock()
+func (r *Ratchet) GetAllPartnerIDs() []*id.ID {
+	r.mux.RLock()
+	defer r.mux.RUnlock()
 
-	partnerIds := make([]*id.ID, 0, len(s.managers))
+	partnerIds := make([]*id.ID, 0, len(r.managers))
 
-	for partnerId := range s.managers {
+	for partnerId := range r.managers {
 		partnerIds = append(partnerIds, &partnerId)
 	}
 
@@ -216,21 +244,21 @@ func (s *Store) GetAllPartnerIDs() []*id.ID {
 }
 
 // GetDHPrivateKey returns the diffie hellman private key.
-func (s *Store) GetDHPrivateKey() *cyclic.Int {
-	return s.dhPrivateKey
+func (r *Ratchet) GetDHPrivateKey() *cyclic.Int {
+	return r.dhPrivateKey
 }
 
 // GetDHPublicKey returns the diffie hellman public key.
-func (s *Store) GetDHPublicKey() *cyclic.Int {
-	return s.dhPublicKey
+func (r *Ratchet) GetDHPublicKey() *cyclic.Int {
+	return r.dhPublicKey
 }
 
 // ekv functions
-func (s *Store) marshal() ([]byte, error) {
-	contacts := make([]id.ID, len(s.managers))
+func (r *Ratchet) marshal() ([]byte, error) {
+	contacts := make([]id.ID, len(r.managers))
 
 	index := 0
-	for partnerID := range s.managers {
+	for partnerID := range r.managers {
 		contacts[index] = partnerID
 		index++
 	}
@@ -238,7 +266,7 @@ func (s *Store) marshal() ([]byte, error) {
 	return json.Marshal(&contacts)
 }
 
-func (s *Store) unmarshal(b []byte) error {
+func (r *Ratchet) unmarshal(b []byte) error {
 
 	var contacts []id.ID
 
@@ -253,29 +281,32 @@ func (s *Store) unmarshal(b []byte) error {
 		partnerID := (&contacts[i]).DeepCopy()
 		// Load the relationship. The relationship handles adding the fingerprints via the
 		// context object
-		manager, err := partner.LoadManager(s.kv, s.myID, partnerID,
-			s.cyHandler, s.grp, s.rng)
+		manager, err := partner.LoadManager(r.kv, r.myID, partnerID,
+			r.cyHandler, r.grp, r.rng)
 		if err != nil {
-			jww.FATAL.Panicf("Failed to load relationship for partner %s: %s",
+			jww.FATAL.Panicf("Failed to load relationship for partner %r: %r",
 				partnerID, err.Error())
 		}
 
 		if !manager.GetPartnerID().Cmp(partnerID) {
 			jww.FATAL.Panicf("Loaded a manager with the wrong partner "+
-				"ID: \n\t loaded: %s \n\t present: %s",
+				"ID: \n\t loaded: %r \n\t present: %r",
 				partnerID, manager.GetPartnerID())
 		}
 
-		s.managers[*partnerID] = manager
+		//add services for the manager
+		r.add(manager)
+
+		r.managers[*partnerID] = manager
 	}
 
-	s.dhPrivateKey, err = util.LoadCyclicKey(s.kv, privKeyKey)
+	r.dhPrivateKey, err = util.LoadCyclicKey(r.kv, privKeyKey)
 	if err != nil {
 		return errors.WithMessage(err,
 			"Failed to load e2e DH private key")
 	}
 
-	s.dhPublicKey, err = util.LoadCyclicKey(s.kv, pubKeyKey)
+	r.dhPublicKey, err = util.LoadCyclicKey(r.kv, pubKeyKey)
 	if err != nil {
 		return errors.WithMessage(err,
 			"Failed to load e2e DH public key")
diff --git a/e2e/ratchet/store_test.go b/e2e/ratchet/store_test.go
index feacc60c94494df0d02af10d81153a2d147b7903..53cd33181ff12e240d09d0c84ba6e2cc7354b6ee 100644
--- a/e2e/ratchet/store_test.go
+++ b/e2e/ratchet/store_test.go
@@ -39,7 +39,7 @@ func TestNewStore(t *testing.T) {
 	fingerprints := newFingerprints()
 	rng := fastRNG.NewStreamGenerator(12, 3, csprng.NewSystemRNG)
 	e2eP := params.GetDefaultE2ESessionParams()
-	expectedStore := &Store{
+	expectedStore := &Ratchet{
 		managers:     make(map[id.ID]*partner.Manager),
 		dhPrivateKey: privKey,
 		dhPublicKey:  diffieHellman.GeneratePublicKey(privKey, grp),
@@ -65,18 +65,18 @@ func TestNewStore(t *testing.T) {
 	}
 
 	if !reflect.DeepEqual(expectedStore, store) {
-		t.Errorf("NewStore() returned incorrect Store."+
+		t.Errorf("NewStore() returned incorrect Ratchet."+
 			"\n\texpected: %+v\n\treceived: %+v", expectedStore,
 			store)
 	}
 
 	key, err := expectedStore.kv.Get(storeKey, 0)
 	if err != nil {
-		t.Errorf("get() error when getting Store from KV: %v", err)
+		t.Errorf("get() error when getting Ratchet from KV: %v", err)
 	}
 
 	if !bytes.Equal(expectedData, key.Data) {
-		t.Errorf("NewStore() returned incorrect Store."+
+		t.Errorf("NewStore() returned incorrect Ratchet."+
 			"\n\texpected: %+v\n\treceived: %+v", expectedData,
 			key.Data)
 	}
@@ -92,13 +92,13 @@ func TestLoadStore(t *testing.T) {
 	}
 
 	if !reflect.DeepEqual(expectedStore, store) {
-		t.Errorf("LoadStore() returned incorrect Store."+
+		t.Errorf("LoadStore() returned incorrect Ratchet."+
 			"\n\texpected: %#v\n\treceived: %#v", expectedStore,
 			store)
 	}
 }
 
-// Tests happy path of Store.AddPartner.
+// Tests happy path of Ratchet.AddPartner.
 func TestStore_AddPartner(t *testing.T) {
 	rng := csprng.NewSystemRNG()
 	s, _, _ := makeTestStore()
@@ -164,7 +164,7 @@ func TestStore_DeletePartner(t *testing.T) {
 
 }
 
-// Tests happy path of Store.GetPartner.
+// Tests happy path of Ratchet.GetPartner.
 func TestStore_GetPartner(t *testing.T) {
 	rng := csprng.NewSystemRNG()
 	s, _, _ := makeTestStore()
@@ -189,7 +189,7 @@ func TestStore_GetPartner(t *testing.T) {
 	}
 }
 
-// Tests that Store.GetPartner returns an error for non existent partnerID.
+// Tests that Ratchet.GetPartner returns an error for non existent partnerID.
 func TestStore_GetPartner_Error(t *testing.T) {
 	s, _, _ := makeTestStore()
 	partnerID := id.NewIdFromUInt(rand.Uint64(), id.User, t)
@@ -205,7 +205,7 @@ func TestStore_GetPartner_Error(t *testing.T) {
 	}
 }
 
-// Tests happy path of Store.GetPartnerContact.
+// Tests happy path of Ratchet.GetPartnerContact.
 func TestStore_GetPartnerContact(t *testing.T) {
 	s, _, _ := makeTestStore()
 	partnerID := id.NewIdFromUInt(rand.Uint64(), id.User, t)
@@ -233,7 +233,7 @@ func TestStore_GetPartnerContact(t *testing.T) {
 	}
 }
 
-// Tests that Store.GetPartnerContact returns an error for non existent partnerID.
+// Tests that Ratchet.GetPartnerContact returns an error for non existent partnerID.
 func TestStore_GetPartnerContact_Error(t *testing.T) {
 	s, _, _ := makeTestStore()
 	partnerID := id.NewIdFromUInt(rand.Uint64(), id.User, t)
@@ -245,7 +245,7 @@ func TestStore_GetPartnerContact_Error(t *testing.T) {
 	}
 }
 
-// Tests happy path of Store.PopKey.
+// Tests happy path of Ratchet.PopKey.
 func TestStore_PopKey(t *testing.T) {
 	s, _, _ := makeTestStore()
 	se, _ := session.makeTestSession()
@@ -279,7 +279,7 @@ func TestStore_PopKey(t *testing.T) {
 	}
 }
 
-// Tests happy path of Store.CheckKey.
+// Tests happy path of Ratchet.CheckKey.
 func TestStore_CheckKey(t *testing.T) {
 	s, _, _ := makeTestStore()
 	se, _ := session.makeTestSession()
@@ -303,7 +303,7 @@ func TestStore_CheckKey(t *testing.T) {
 	}
 }
 
-// Tests happy path of Store.GetDHPrivateKey.
+// Tests happy path of Ratchet.GetDHPrivateKey.
 func TestStore_GetDHPrivateKey(t *testing.T) {
 	s, _, _ := makeTestStore()
 
@@ -314,7 +314,7 @@ func TestStore_GetDHPrivateKey(t *testing.T) {
 	}
 }
 
-// Tests happy path of Store.GetDHPublicKey.
+// Tests happy path of Ratchet.GetDHPublicKey.
 func TestStore_GetDHPublicKey(t *testing.T) {
 	s, _, _ := makeTestStore()
 
@@ -325,7 +325,7 @@ func TestStore_GetDHPublicKey(t *testing.T) {
 	}
 }
 
-// Tests happy path of Store.GetGroup.
+// Tests happy path of Ratchet.GetGroup.
 func TestStore_GetGroup(t *testing.T) {
 	s, _, _ := makeTestStore()
 
@@ -382,7 +382,7 @@ func TestFingerprints_remove(t *testing.T) {
 	}
 }
 
-func makeTestStore() (*Store, *versioned.KV, *fastRNG.StreamGenerator) {
+func makeTestStore() (*Ratchet, *versioned.KV, *fastRNG.StreamGenerator) {
 	grp := cyclic.NewGroup(large.NewInt(107), large.NewInt(2))
 	privKey := grp.NewInt(57)
 	kv := versioned.NewKV(make(ekv.Memstore))
diff --git a/network/interface.go b/network/interface.go
index 3d45710cde447dc85adf39ecbdb798ef8ff8b403..62f2425c4c6d740fe64f09a0f6a8706a3fcdb771 100644
--- a/network/interface.go
+++ b/network/interface.go
@@ -145,6 +145,11 @@ type Manager interface {
 	//      notifications.
 	//   source - A byte buffer of related data. Generally used in notifications.
 	//     Example: Sender ID
+	// There can be multiple "default" services, the must use the "default" tag
+	// and the identifier must be the client reception ID.
+	// A service may have a nil response unless it is default. In general a
+	// nil service is used to detect notifications when pickup is done by
+	// fingerprints
 	AddService(AddService *id.ID, newService message.Service,
 		response message.Processor)
 
@@ -152,6 +157,7 @@ type Manager interface {
 	// associated with the preimage, the entire preimage is removed. If there is
 	// more than one response, only the given response is removed. If nil is
 	// passed in for response, all triggers for the preimage will be removed.
+	// The processor is only used in deletion when deleting a default service
 	DeleteService(clientID *id.ID, toDelete message.Service,
 		processor message.Processor)
 
diff --git a/network/message/handler.go b/network/message/handler.go
index 687f68544c3413f452e9deda1b77d18515995f72..26ca4d8b1e640ec5c1cba84f1ba16bd411a680a9 100644
--- a/network/message/handler.go
+++ b/network/message/handler.go
@@ -81,7 +81,8 @@ func (p *handler) handleMessage(ecrMsg format.Message, bundle Bundle) bool {
 			go t.Process(ecrMsg, identity, round)
 		}
 		if len(services) == 0 {
-			jww.ERROR.Printf("empty service list for %s", ecrMsg.GetSIH())
+			jww.WARN.Printf("empty service list for %s: %s",
+				ecrMsg.Digest(), ecrMsg.GetSIH())
 		}
 		return true
 	} else {
diff --git a/network/message/services.go b/network/message/services.go
index 3a9ca471dbb07fffddca01bd5ed2b86412a6c27c..4fd062d92f9a7d77af97fef30e89e59fa1c4c716 100644
--- a/network/message/services.go
+++ b/network/message/services.go
@@ -80,8 +80,13 @@ func (sm *ServicesManager) get(clientID *id.ID, receivedSIH,
 		// Check if the SIH matches this service
 		if s.ForMe(ecrMsgContents, receivedSIH) {
 			if s.defaultList == nil && s.Tag != sih.Default {
+				//skip if the processor is nil
+				if s.Processor != nil {
+					return []Processor{}, true
+				}
 				// Return this service directly if not the default service
 				return []Processor{s}, true
+
 			} else if s.defaultList != nil {
 				// If it is default and the default list is not empty, then
 				// return the default list
@@ -104,6 +109,9 @@ func (sm *ServicesManager) get(clientID *id.ID, receivedSIH,
 //   type - a descriptive string of the service. Generally used in notifications
 //   source - a byte buffer of related data. Generally used in notifications.
 //     Example: Sender ID
+// There can be multiple "default" services, the must use the "default" tag
+// and the identifier must be the client reception ID.
+// A service may have a nil response unless it is default.
 func (sm *ServicesManager) AddService(clientID *id.ID, newService Service,
 	response Processor) {
 	sm.Lock()