diff --git a/Makefile b/Makefile
index f1955bd0c974351c212a82888947bf58774343fa..ccae033ac35c7db20c21aab397eeef6b9d364bd0 100644
--- a/Makefile
+++ b/Makefile
@@ -2,8 +2,8 @@
 
 version:
 	go run main.go generate
-	sed -i.bak 's/package\ cmd/package\ api/g' version_vars.go
-	mv version_vars.go api/version_vars.go
+	sed -i.bak 's/package\ cmd/package\ xxdk/g' version_vars.go
+	mv version_vars.go xxdk/version_vars.go
 
 clean:
 	rm -rf vendor/
diff --git a/api/identity.go b/api/identity.go
deleted file mode 100644
index 2ef5c5bb4cb5bfc468b368ab8d5f1ff4cf25b740..0000000000000000000000000000000000000000
--- a/api/identity.go
+++ /dev/null
@@ -1,53 +0,0 @@
-package api
-
-import (
-	"gitlab.com/elixxir/crypto/cyclic"
-	"gitlab.com/elixxir/crypto/diffieHellman"
-	"gitlab.com/xx_network/crypto/csprng"
-	"gitlab.com/xx_network/crypto/signature/rsa"
-	"gitlab.com/xx_network/crypto/xx"
-	"gitlab.com/xx_network/primitives/id"
-)
-
-type Identity struct {
-	ID            *id.ID
-	RSAPrivatePem *rsa.PrivateKey
-	Salt          []byte
-	DHKeyPrivate  *cyclic.Int
-}
-
-// MakeIdentity generates a new cryptographic identity for receiving messages
-func MakeIdentity(rng csprng.Source, grp *cyclic.Group) (Identity, error) {
-	//make RSA Key
-	rsaKey, err := rsa.GenerateKey(rng,
-		rsa.DefaultRSABitLen)
-	if err != nil {
-		return Identity{}, err
-	}
-
-	//make salt
-	salt := make([]byte, 32)
-	_, err = rng.Read(salt)
-
-	//make dh private key
-	privkey := diffieHellman.GeneratePrivateKey(
-		len(grp.GetPBytes()),
-		grp, rng)
-
-	//make the ID
-	newId, err := xx.NewID(rsaKey.GetPublic(),
-		salt, id.User)
-	if err != nil {
-		return Identity{}, err
-	}
-
-	//create the identity object
-	I := Identity{
-		ID:            newId,
-		RSAPrivatePem: rsaKey,
-		Salt:          salt,
-		DHKeyPrivate:  privkey,
-	}
-
-	return I, nil
-}
diff --git a/api/messenger/precan.go b/api/messenger/precan.go
deleted file mode 100644
index 16717bbfa04bb986e9069931da62126e700c5509..0000000000000000000000000000000000000000
--- a/api/messenger/precan.go
+++ /dev/null
@@ -1,87 +0,0 @@
-package messenger
-
-import (
-	"encoding/binary"
-	"github.com/cloudflare/circl/dh/sidh"
-	"gitlab.com/elixxir/client/api"
-	"gitlab.com/elixxir/client/e2e/ratchet/partner/session"
-	util "gitlab.com/elixxir/client/storage/utility"
-	"gitlab.com/elixxir/crypto/contact"
-	"gitlab.com/elixxir/crypto/cyclic"
-	"gitlab.com/elixxir/crypto/diffieHellman"
-	"gitlab.com/elixxir/primitives/fact"
-	"math/rand"
-)
-
-func generatePrecanDHKeypair(precannedID uint, e2eGrp *cyclic.Group) *cyclic.Int {
-	// DH Keygen
-	prng := rand.New(rand.NewSource(int64(precannedID)))
-	prime := e2eGrp.GetPBytes()
-	keyLen := len(prime)
-	priv := diffieHellman.GeneratePrivateKey(keyLen, e2eGrp, prng)
-	return priv
-}
-
-// Create an insecure e2e relationship with a precanned user
-func (m *Client) MakePrecannedAuthenticatedChannel(precannedID uint) (
-	contact.Contact, error) {
-
-	precan := m.MakePrecannedContact(precannedID)
-
-	myID := binary.BigEndian.Uint64(m.GetStorage().GetReceptionID()[:])
-	// Pick a variant based on if their ID is bigger than mine.
-	myVariant := sidh.KeyVariantSidhA
-	theirVariant := sidh.KeyVariant(sidh.KeyVariantSidhB)
-	if myID > uint64(precannedID) {
-		myVariant = sidh.KeyVariantSidhB
-		theirVariant = sidh.KeyVariantSidhA
-	}
-	prng1 := rand.New(rand.NewSource(int64(precannedID)))
-	theirSIDHPrivKey := util.NewSIDHPrivateKey(theirVariant)
-	theirSIDHPubKey := util.NewSIDHPublicKey(theirVariant)
-	theirSIDHPrivKey.Generate(prng1)
-	theirSIDHPrivKey.GeneratePublicKey(theirSIDHPubKey)
-
-	prng2 := rand.New(rand.NewSource(int64(myID)))
-	mySIDHPrivKey := util.NewSIDHPrivateKey(myVariant)
-	mySIDHPubKey := util.NewSIDHPublicKey(myVariant)
-	mySIDHPrivKey.Generate(prng2)
-	mySIDHPrivKey.GeneratePublicKey(mySIDHPubKey)
-
-	// add the precanned user as a e2e contact
-	// FIXME: these params need to be threaded through...
-	sesParam := session.GetDefaultParams()
-	_, err := m.e2e.AddPartner(precan.ID, precan.DhPubKey,
-		m.e2e.GetHistoricalDHPrivkey(), theirSIDHPubKey,
-		mySIDHPrivKey, sesParam, sesParam)
-
-	// check garbled messages in case any messages arrived before creating
-	// the channel
-	m.GetCmix().CheckInProgressMessages()
-
-	return precan, err
-}
-
-// Create an insecure e2e contact object for a precanned user
-func (m *Client) MakePrecannedContact(precannedID uint) contact.Contact {
-
-	e2eGrp := m.GetStorage().GetE2EGroup()
-
-	rng := m.GetRng().GetStream()
-	precanned := api.CreatePrecannedUser(precannedID, rng)
-	rng.Close()
-
-	precanned.E2eDhPrivateKey = generatePrecanDHKeypair(precannedID,
-		m.GetStorage().GetE2EGroup())
-
-	// compute their public e2e key
-	partnerPubKey := e2eGrp.ExpG(precanned.E2eDhPrivateKey,
-		e2eGrp.NewInt(1))
-
-	return contact.Contact{
-		ID:             precanned.ReceptionID,
-		DhPubKey:       partnerPubKey,
-		OwnershipProof: nil,
-		Facts:          make([]fact.Fact, 0),
-	}
-}
diff --git a/api/precan.go b/api/precan.go
deleted file mode 100644
index 150d90fa9a806db81277fe9677a9a6ecc13e64dc..0000000000000000000000000000000000000000
--- a/api/precan.go
+++ /dev/null
@@ -1,85 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-// Copyright © 2020 xx network SEZC                                          //
-//                                                                           //
-// Use of this source code is governed by a license that can be found in the //
-// LICENSE file                                                              //
-///////////////////////////////////////////////////////////////////////////////
-
-package api
-
-import (
-	"encoding/binary"
-
-	jww "github.com/spf13/jwalterweatherman"
-	"gitlab.com/elixxir/client/storage"
-	"gitlab.com/elixxir/client/storage/user"
-	"gitlab.com/elixxir/crypto/fastRNG"
-	"gitlab.com/xx_network/crypto/csprng"
-	"gitlab.com/xx_network/crypto/signature/rsa"
-	"gitlab.com/xx_network/primitives/id"
-)
-
-// CreatePrecannedUser creates a precanned user
-func CreatePrecannedUser(precannedID uint, rng csprng.Source) user.Info {
-
-	// Salt, UID, etc gen
-	salt := make([]byte, SaltSize)
-
-	userID := id.ID{}
-	binary.BigEndian.PutUint64(userID[:], uint64(precannedID))
-	userID.SetType(id.User)
-
-	// NOTE: not used... RSA Keygen (4096 bit defaults)
-	rsaKey, err := rsa.GenerateKey(rng, rsa.DefaultRSABitLen)
-	if err != nil {
-		jww.FATAL.Panicf(err.Error())
-	}
-
-	return user.Info{
-		TransmissionID:   &userID,
-		TransmissionSalt: salt,
-		ReceptionID:      &userID,
-		ReceptionSalt:    salt,
-		Precanned:        true,
-		E2eDhPrivateKey:  nil,
-		E2eDhPublicKey:   nil,
-		TransmissionRSA:  rsaKey,
-		ReceptionRSA:     rsaKey,
-	}
-}
-
-// NewPrecannedClient creates an insecure user with predetermined keys
-// with nodes It creates client storage, generates keys, connects, and
-// registers with the network. Note that this does not register a
-// username/identity, but merely creates a new cryptographic identity
-// for adding such information at a later date.
-func NewPrecannedClient(precannedID uint, defJSON, storageDir string,
-	password []byte) error {
-	jww.INFO.Printf("NewPrecannedClient()")
-	rngStreamGen := fastRNG.NewStreamGenerator(12, 1024,
-		csprng.NewSystemRNG)
-	rngStream := rngStreamGen.GetStream()
-
-	def, err := ParseNDF(defJSON)
-	if err != nil {
-		return err
-	}
-	cmixGrp, e2eGrp := DecodeGroups(def)
-
-	protoUser := CreatePrecannedUser(precannedID, rngStream)
-
-	store, err := CheckVersionAndSetupStorage(def, storageDir, password,
-		protoUser, cmixGrp, e2eGrp, "")
-	if err != nil {
-		return err
-	}
-
-	// Mark the precanned user as finished with permissioning and registered
-	// with the network.
-	err = store.ForwardRegistrationStatus(storage.PermissioningComplete)
-	if err != nil {
-		return err
-	}
-
-	return nil
-}
diff --git a/auth/callbacks.go b/auth/callbacks.go
new file mode 100644
index 0000000000000000000000000000000000000000..781164bb89e374f166b0ace4d4fb639e7c250d10
--- /dev/null
+++ b/auth/callbacks.go
@@ -0,0 +1,68 @@
+////////////////////////////////////////////////////////////////////////////////
+// Copyright © 2022 Privategrity Corporation                                   /
+//                                                                             /
+// All rights reserved.                                                        /
+////////////////////////////////////////////////////////////////////////////////
+
+package auth
+
+import (
+	jww "github.com/spf13/jwalterweatherman"
+	"gitlab.com/elixxir/client/cmix/identity/receptionID"
+	"gitlab.com/elixxir/client/cmix/rounds"
+	"gitlab.com/elixxir/crypto/contact"
+	"gitlab.com/xx_network/primitives/id"
+	"sync"
+)
+
+// partnerCallbacks is a thread-safe wrapper for Callbacks specific to partnerIds
+// For auth operations with a specific partner, these Callbacks will be used instead
+type partnerCallbacks struct {
+	callbacks map[id.ID]Callbacks
+	sync.RWMutex
+}
+
+// AddPartnerCallback that overrides the generic auth callback for the given partnerId
+func (p *partnerCallbacks) AddPartnerCallback(partnerId *id.ID, cb Callbacks) {
+	p.Lock()
+	defer p.Unlock()
+	if _, ok := p.callbacks[*partnerId]; !ok {
+		p.callbacks[*partnerId] = cb
+	}
+}
+
+// DeletePartnerCallback that overrides the generic auth callback for the given partnerId
+func (p *partnerCallbacks) DeletePartnerCallback(partnerId *id.ID) {
+	p.Lock()
+	defer p.Unlock()
+	if _, ok := p.callbacks[*partnerId]; ok {
+		delete(p.callbacks, *partnerId)
+	}
+}
+
+// getPartnerCallback returns the Callbacks for the given partnerId
+func (p *partnerCallbacks) getPartnerCallback(partnerId *id.ID) Callbacks {
+	return p.callbacks[*partnerId]
+}
+
+// DefaultAuthCallbacks is a simple structure for providing a default Callbacks implementation
+// It should generally not be used.
+type DefaultAuthCallbacks struct{}
+
+// Confirm will be called when an auth Confirm message is processed.
+func (a DefaultAuthCallbacks) Confirm(requestor contact.Contact,
+	receptionID receptionID.EphemeralIdentity, round rounds.Round) {
+	jww.ERROR.Printf("No valid auth callback assigned!")
+}
+
+// Request will be called when an auth Request message is processed.
+func (a DefaultAuthCallbacks) Request(requestor contact.Contact,
+	receptionID receptionID.EphemeralIdentity, round rounds.Round) {
+	jww.ERROR.Printf("No valid auth callback assigned!")
+}
+
+// Reset will be called when an auth Reset operation occurs.
+func (a DefaultAuthCallbacks) Reset(requestor contact.Contact,
+	receptionID receptionID.EphemeralIdentity, round rounds.Round) {
+	jww.ERROR.Printf("No valid auth callback assigned!")
+}
diff --git a/auth/interface.go b/auth/interface.go
index e01e5576685fede4971dbcf8ccd542f08a464bb4..40f5e72e4ddefcb46bb716765cc163dca94876a6 100644
--- a/auth/interface.go
+++ b/auth/interface.go
@@ -96,11 +96,18 @@ type State interface {
 	// VerifyOwnership checks if the received ownership proof is valid
 	VerifyOwnership(received, verified contact.Contact, e2e e2e.Handler) bool
 
+	// AddPartnerCallback that overrides the generic auth callback for the given partnerId
+	AddPartnerCallback(partnerId *id.ID, cb Callbacks)
+
+	// DeletePartnerCallback that overrides the generic auth callback for the given partnerId
+	DeletePartnerCallback(partnerId *id.ID)
+
 	//Closer stops listening to auth
 	io.Closer
 }
 
 // Callbacks is the interface for auth callback methods.
+// TODO: Document this
 type Callbacks interface {
 	Request(partner contact.Contact, receptionID receptionID.EphemeralIdentity,
 		round rounds.Round)
diff --git a/auth/receivedConfirm.go b/auth/receivedConfirm.go
index 8ee24bd341ba6c03e2f00a7a5158d76558b6800e..538329e1b532a1a34d813f866dfb739319c09d3b 100644
--- a/auth/receivedConfirm.go
+++ b/auth/receivedConfirm.go
@@ -25,21 +25,21 @@ type receivedConfirmService struct {
 func (rcs *receivedConfirmService) Process(msg format.Message,
 	receptionID receptionID.EphemeralIdentity, round rounds.Round) {
 
-	state := rcs.s
+	authState := rcs.s
 
 	//parse the confirm
-	baseFmt, partnerPubKey, err := handleBaseFormat(msg, state.e2e.GetGroup())
+	baseFmt, partnerPubKey, err := handleBaseFormat(msg, authState.e2e.GetGroup())
 	if err != nil {
 		em := fmt.Sprintf("Failed to handle auth confirm: %s", err)
 		jww.WARN.Print(em)
-		state.event.Report(10, "Auth", "ConfirmError", em)
+		authState.event.Report(10, "Auth", "ConfirmError", em)
 		return
 	}
 
 	jww.TRACE.Printf("processing confirm: \n\t MYHISTORICALPUBKEY: %s\n\t"+
 		"MYPUBKEY: %s\n\t PARTNERPUBKEY: %s \n\t "+
 		"ECRPAYLOAD: %s \n\t MAC: %s",
-		state.e2e.GetHistoricalDHPubkey().TextVerbose(16, 0),
+		authState.e2e.GetHistoricalDHPubkey().TextVerbose(16, 0),
 		rcs.SentRequest.GetMyPubKey().TextVerbose(16, 0),
 		partnerPubKey.TextVerbose(16, 0),
 		base64.StdEncoding.EncodeToString(baseFmt.data),
@@ -47,13 +47,13 @@ func (rcs *receivedConfirmService) Process(msg format.Message,
 
 	// decrypt the payload
 	success, payload := cAuth.Decrypt(rcs.GetMyPrivKey(), partnerPubKey,
-		baseFmt.GetEcrPayload(), msg.GetMac(), state.e2e.GetGroup())
+		baseFmt.GetEcrPayload(), msg.GetMac(), authState.e2e.GetGroup())
 
 	if !success {
 		em := fmt.Sprintf("Received auth confirmation " +
 			"failed its mac check")
 		jww.WARN.Print(em)
-		state.event.Report(10, "Auth", "ConfirmError", em)
+		authState.event.Report(10, "Auth", "ConfirmError", em)
 		return
 	}
 
@@ -63,7 +63,7 @@ func (rcs *receivedConfirmService) Process(msg format.Message,
 		em := fmt.Sprintf("Failed to unmarshal auth confirmation's "+
 			"encrypted payload: %s", err)
 		jww.WARN.Print(em)
-		state.event.Report(10, "Auth", "ConfirmError", em)
+		authState.event.Report(10, "Auth", "ConfirmError", em)
 		return
 	}
 
@@ -72,7 +72,7 @@ func (rcs *receivedConfirmService) Process(msg format.Message,
 		em := fmt.Sprintf("Could not get auth conf SIDH Pubkey: %s",
 			err)
 		jww.WARN.Print(em)
-		state.event.Report(10, "Auth", "ConfirmError", em)
+		authState.event.Report(10, "Auth", "ConfirmError", em)
 		return
 	}
 
@@ -83,7 +83,7 @@ func (rcs *receivedConfirmService) Process(msg format.Message,
 	// initial identity
 	if !cAuth.VerifyOwnershipProof(rcs.SentRequest.GetMyPrivKey(),
 		rcs.GetPartnerHistoricalPubKey(),
-		state.e2e.GetGroup(), ecrFmt.GetOwnership()) {
+		authState.e2e.GetGroup(), ecrFmt.GetOwnership()) {
 		jww.WARN.Printf("Failed authenticate identity for auth "+
 			"confirmation of %s", rcs.GetPartner())
 		return
@@ -91,7 +91,7 @@ func (rcs *receivedConfirmService) Process(msg format.Message,
 
 	// add the partner
 	p := session.GetDefaultParams()
-	_, err = state.e2e.AddPartner(rcs.GetPartner(), partnerPubKey,
+	_, err = authState.e2e.AddPartner(rcs.GetPartner(), partnerPubKey,
 		rcs.GetMyPrivKey(), partnerSIDHPubKey, rcs.GetMySIDHPrivKey(), p, p)
 	if err != nil {
 		jww.WARN.Printf("Failed to create channel with partner %s and "+
@@ -103,7 +103,7 @@ func (rcs *receivedConfirmService) Process(msg format.Message,
 	}
 
 	// remove the service used for notifications of the confirm
-	state.net.DeleteService(receptionID.Source, rcs.notificationsService, nil)
+	authState.net.DeleteService(receptionID.Source, rcs.notificationsService, nil)
 
 	// callbacks
 	c := contact.Contact{
@@ -112,7 +112,14 @@ func (rcs *receivedConfirmService) Process(msg format.Message,
 		OwnershipProof: ecrFmt.GetOwnership(),
 		Facts:          make([]fact.Fact, 0),
 	}
-	state.callbacks.Confirm(c, receptionID, round)
+
+	authState.partnerCallbacks.RLock()
+	if cb := authState.partnerCallbacks.getPartnerCallback(c.ID); cb != nil {
+		cb.Confirm(c, receptionID, round)
+	} else {
+		authState.callbacks.Confirm(c, receptionID, round)
+	}
+	authState.partnerCallbacks.RUnlock()
 }
 
 func (rcs *receivedConfirmService) String() string {
diff --git a/auth/receivedRequest.go b/auth/receivedRequest.go
index 944c1880b3ac0a744331abbcbb44c4f8dba79949..b410b04a3e29cca95dedd8bc14d310507e8bce57 100644
--- a/auth/receivedRequest.go
+++ b/auth/receivedRequest.go
@@ -28,11 +28,11 @@ type receivedRequestService struct {
 
 func (rrs *receivedRequestService) Process(message format.Message,
 	receptionID receptionID.EphemeralIdentity, round rounds.Round) {
-	state := rrs.s
+	authState := rrs.s
 
 	// check if the timestamp is before the id was created and therefore
 	// should be ignored
-	tid, err := state.net.GetIdentity(receptionID.Source)
+	tid, err := authState.net.GetIdentity(receptionID.Source)
 	if err != nil {
 		jww.ERROR.Printf("received a request on %s which does not exist, "+
 			"this should not be possible: %+v", receptionID.Source.String(), err)
@@ -47,7 +47,7 @@ func (rrs *receivedRequestService) Process(message format.Message,
 
 	//decode the outer format
 	baseFmt, partnerPubKey, err := handleBaseFormat(
-		message, state.e2e.GetGroup())
+		message, authState.e2e.GetGroup())
 	if err != nil {
 		jww.WARN.Printf("Failed to handle auth request: %s", err)
 		return
@@ -57,15 +57,15 @@ func (rrs *receivedRequestService) Process(message format.Message,
 
 	jww.TRACE.Printf("processing requests: \n\t MYHISTORICALPUBKEY: %s "+
 		"\n\t PARTNERPUBKEY: %s \n\t ECRPAYLOAD: %s \n\t MAC: %s",
-		state.e2e.GetHistoricalDHPubkey().TextVerbose(16, 0),
+		authState.e2e.GetHistoricalDHPubkey().TextVerbose(16, 0),
 		partnerPubKey.TextVerbose(16, 0),
 		base64.StdEncoding.EncodeToString(baseFmt.data),
 		base64.StdEncoding.EncodeToString(message.GetMac()))
 
 	//Attempt to decrypt the payload
-	success, payload := cAuth.Decrypt(state.e2e.GetHistoricalDHPrivkey(),
+	success, payload := cAuth.Decrypt(authState.e2e.GetHistoricalDHPrivkey(),
 		partnerPubKey, baseFmt.GetEcrPayload(), message.GetMac(),
-		state.e2e.GetGroup())
+		authState.e2e.GetGroup())
 
 	if !success {
 		jww.WARN.Printf("Received auth request of %s failed its mac "+
@@ -97,11 +97,11 @@ func (rrs *receivedRequestService) Process(message format.Message,
 		format.DigestContents(message.GetContents()),
 		base64.StdEncoding.EncodeToString(fp))
 	jww.INFO.Print(em)
-	state.event.Report(1, "Auth", "RequestReceived", em)
+	authState.event.Report(1, "Auth", "RequestReceived", em)
 
 	// check the uniqueness of the request. Requests can be duplicated, so we
 	// must verify this is is not a duplicate, and drop if it is
-	newFP, position := state.store.CheckIfNegotiationIsNew(partnerID, fp)
+	newFP, position := authState.store.CheckIfNegotiationIsNew(partnerID, fp)
 
 	if !newFP {
 		// if its the newest, resend the confirm
@@ -113,10 +113,10 @@ func (rrs *receivedRequestService) Process(message format.Message,
 
 			// check if we already accepted, if we did, resend the confirm if
 			// we can load it
-			if _, err = state.e2e.GetPartner(partnerID); err != nil {
+			if _, err = authState.e2e.GetPartner(partnerID); err != nil {
 				//attempt to load the confirm, if we can, resend it
 				confirmPayload, mac, keyfp, err :=
-					state.store.LoadConfirmation(partnerID)
+					authState.store.LoadConfirmation(partnerID)
 				if err != nil {
 					jww.ERROR.Printf("Could not reconfirm a duplicate "+
 						"request of an accepted confirm from %s to %s because "+
@@ -125,14 +125,26 @@ func (rrs *receivedRequestService) Process(message format.Message,
 				}
 				// resend the confirm. It sends as a critical message, so errors
 				// do not need to be handled
-				_, _ = sendAuthConfirm(state.net, partnerID, keyfp,
-					confirmPayload, mac, state.event, state.params.ResetConfirmTag)
-			} else if state.params.ReplayRequests {
+				_, _ = sendAuthConfirm(authState.net, partnerID, keyfp,
+					confirmPayload, mac, authState.event, authState.params.ResetConfirmTag)
+			} else if authState.params.ReplayRequests {
 				//if we did not already accept, auto replay the request
 				if rrs.reset {
-					state.callbacks.Reset(c, receptionID, round)
+					authState.partnerCallbacks.RLock()
+					if cb := authState.partnerCallbacks.getPartnerCallback(c.ID); cb != nil {
+						cb.Reset(c, receptionID, round)
+					} else {
+						authState.callbacks.Reset(c, receptionID, round)
+					}
+					authState.partnerCallbacks.RUnlock()
 				} else {
-					state.callbacks.Request(c, receptionID, round)
+					authState.partnerCallbacks.RLock()
+					if cb := authState.partnerCallbacks.getPartnerCallback(c.ID); cb != nil {
+						cb.Request(c, receptionID, round)
+					} else {
+						authState.callbacks.Request(c, receptionID, round)
+					}
+					authState.partnerCallbacks.RUnlock()
 				}
 			}
 			//if not confirm, and params.replay requests is true, we need to replay
@@ -159,21 +171,21 @@ func (rrs *receivedRequestService) Process(message format.Message,
 		// error to see if it did or didnt exist
 		// Note: due to the newFP handling above, this can ONLY run in the event of
 		// a reset or when the partner doesnt exist, so it is safe
-		if err = state.e2e.DeletePartner(partnerID); err != nil {
+		if err = authState.e2e.DeletePartner(partnerID); err != nil {
 			if !strings.Contains(err.Error(), ratchet.NoPartnerErrorStr) {
 				jww.FATAL.Panicf("Failed to do actual partner deletion: %+v", err)
 			}
 		} else {
 			reset = true
-			_ = state.store.DeleteConfirmation(partnerID)
-			_ = state.store.DeleteSentRequest(partnerID)
+			_ = authState.store.DeleteConfirmation(partnerID)
+			_ = authState.store.DeleteSentRequest(partnerID)
 		}
 	}
 
 	// if a new, unique request is received when one already exists, delete the
 	// old one and process the new one
 	// this works because message pickup is generally time-sequential.
-	if err = state.store.DeleteReceivedRequest(partnerID); err != nil {
+	if err = authState.store.DeleteReceivedRequest(partnerID); err != nil {
 		if !strings.Contains(err.Error(), store.NoRequestFound) {
 			jww.FATAL.Panicf("Failed to delete old received request: %+v",
 				err)
@@ -187,7 +199,7 @@ func (rrs *receivedRequestService) Process(message format.Message,
 	// (SIDH keys have polarity, so both sent keys cannot be used together)
 	autoConfirm := false
 	bail := false
-	err = state.store.HandleSentRequest(partnerID,
+	err = authState.store.HandleSentRequest(partnerID,
 		func(request *store.SentRequest) error {
 
 			//if this code is running, then we know we sent a request and can
@@ -195,8 +207,8 @@ func (rrs *receivedRequestService) Process(message format.Message,
 			//This runner will auto delete the sent request if successful
 
 			//verify ownership proof
-			if !cAuth.VerifyOwnershipProof(state.e2e.GetHistoricalDHPrivkey(),
-				partnerPubKey, state.e2e.GetGroup(), ownershipProof) {
+			if !cAuth.VerifyOwnershipProof(authState.e2e.GetHistoricalDHPrivkey(),
+				partnerPubKey, authState.e2e.GetGroup(), ownershipProof) {
 				jww.WARN.Printf("Invalid ownership proof from %s to %s "+
 					"received, discarding msgDigest: %s, fp: %s",
 					partnerID, receptionID.Source,
@@ -233,25 +245,39 @@ func (rrs *receivedRequestService) Process(message format.Message,
 	// warning: the client will never be notified of the channel creation if a
 	// crash occurs after the store but before the conclusion of the callback
 	//create the auth storage
-	if err = state.store.AddReceived(c, partnerSIDHPubKey, round); err != nil {
+	if err = authState.store.AddReceived(c, partnerSIDHPubKey, round); err != nil {
 		em := fmt.Sprintf("failed to store contact Auth "+
 			"Request: %s", err)
 		jww.WARN.Print(em)
-		state.event.Report(10, "Auth", "RequestError", em)
+		authState.event.Report(10, "Auth", "RequestError", em)
 		return
 	}
 
-	//autoconfirm if we should
+	// auto-confirm if we should
+	authState.partnerCallbacks.RLock()
+	defer authState.partnerCallbacks.RUnlock()
 	if autoConfirm || reset {
-		_, _ = state.confirm(c, state.params.getConfirmTag(reset))
+		_, _ = authState.confirm(c, authState.params.getConfirmTag(reset))
 		//handle callbacks
 		if autoConfirm {
-			state.callbacks.Confirm(c, receptionID, round)
+			if cb := authState.partnerCallbacks.getPartnerCallback(c.ID); cb != nil {
+				cb.Confirm(c, receptionID, round)
+			} else {
+				authState.callbacks.Confirm(c, receptionID, round)
+			}
 		} else if reset {
-			state.callbacks.Reset(c, receptionID, round)
+			if cb := authState.partnerCallbacks.getPartnerCallback(c.ID); cb != nil {
+				cb.Reset(c, receptionID, round)
+			} else {
+				authState.callbacks.Reset(c, receptionID, round)
+			}
 		}
 	} else {
-		state.callbacks.Request(c, receptionID, round)
+		if cb := authState.partnerCallbacks.getPartnerCallback(c.ID); cb != nil {
+			cb.Request(c, receptionID, round)
+		} else {
+			authState.callbacks.Request(c, receptionID, round)
+		}
 	}
 }
 
diff --git a/auth/state.go b/auth/state.go
index 607275a3075372141b799cfab0e9a2aa73cebbdd..43e1d9735fde5bd0e5c4bbc396ec3ff74727c4b5 100644
--- a/auth/state.go
+++ b/auth/state.go
@@ -9,7 +9,6 @@ package auth
 
 import (
 	"encoding/base64"
-
 	"github.com/pkg/errors"
 	"gitlab.com/elixxir/client/auth/store"
 	"gitlab.com/elixxir/client/cmix"
@@ -24,7 +23,10 @@ import (
 
 // state is an implementation of the State interface.
 type state struct {
+	// Main Callbacks for all auth operations
 	callbacks Callbacks
+	// partner-specific Callbacks
+	partnerCallbacks partnerCallbacks
 
 	net cmixClient
 	e2e e2eHandler
@@ -70,13 +72,14 @@ func NewStateLegacy(kv *versioned.KV, net cmix.Client, e2e e2e.Handler,
 	callbacks Callbacks, backupTrigger func(reason string)) (State, error) {
 
 	s := &state{
-		callbacks:     callbacks,
-		net:           net,
-		e2e:           e2e,
-		rng:           rng,
-		event:         event,
-		params:        params,
-		backupTrigger: backupTrigger,
+		callbacks:        callbacks,
+		partnerCallbacks: partnerCallbacks{callbacks: make(map[id.ID]Callbacks)},
+		net:              net,
+		e2e:              e2e,
+		rng:              rng,
+		event:            event,
+		params:           params,
+		backupTrigger:    backupTrigger,
 	}
 
 	// create the store
@@ -112,7 +115,13 @@ func (s *state) CallAllReceivedRequests() {
 		rr := rrList[i]
 		eph := receptionID.BuildIdentityFromRound(rr.GetContact().ID,
 			rr.GetRound())
-		s.callbacks.Request(rr.GetContact(), eph, rr.GetRound())
+		s.partnerCallbacks.RLock()
+		if cb := s.partnerCallbacks.getPartnerCallback(rr.GetContact().ID); cb != nil {
+			cb.Request(rr.GetContact(), eph, rr.GetRound())
+		} else {
+			s.callbacks.Request(rr.GetContact(), eph, rr.GetRound())
+		}
+		s.partnerCallbacks.RUnlock()
 	}
 }
 
@@ -134,3 +143,13 @@ func (s *state) Close() error {
 	}, nil)
 	return nil
 }
+
+// AddPartnerCallback that overrides the generic auth callback for the given partnerId
+func (s *state) AddPartnerCallback(partnerId *id.ID, cb Callbacks) {
+	s.partnerCallbacks.AddPartnerCallback(partnerId, cb)
+}
+
+// DeletePartnerCallback that overrides the generic auth callback for the given partnerId
+func (s *state) DeletePartnerCallback(partnerId *id.ID) {
+	s.partnerCallbacks.DeletePartnerCallback(partnerId)
+}
diff --git a/backup/backup.go b/backup/backup.go
index 46f5bf73019e9c26e66b2a780f141a5b788647a4..992968668b08cce3a8d9819bbc6991f738b1ce18 100644
--- a/backup/backup.go
+++ b/backup/backup.go
@@ -8,10 +8,10 @@
 package backup
 
 import (
+	"gitlab.com/elixxir/client/xxdk"
 	"sync"
 	"time"
 
-	"gitlab.com/elixxir/client/api/messenger"
 	"gitlab.com/elixxir/client/storage/versioned"
 	"gitlab.com/elixxir/crypto/cyclic"
 	"gitlab.com/elixxir/primitives/fact"
@@ -41,11 +41,11 @@ type Backup struct {
 	// Callback that is called with the encrypted backup when triggered
 	updateBackupCb UpdateBackupFn
 
-	container *messenger.Container
+	container *xxdk.Container
 
 	jsonParams string
 
-	// Client structures
+	// E2e structures
 	e2e     E2e
 	session Session
 	ud      UserDiscovery
@@ -91,7 +91,7 @@ type UpdateBackupFn func(encryptedBackup []byte)
 // Call this to turn on backups for the first time or to replace the user's
 // password.
 func InitializeBackup(password string, updateBackupCb UpdateBackupFn,
-	container *messenger.Container, e2e E2e, session Session, ud UserDiscovery,
+	container *xxdk.Container, e2e E2e, session Session, ud UserDiscovery,
 	kv *versioned.KV, rng *fastRNG.StreamGenerator) (*Backup, error) {
 	b := &Backup{
 		updateBackupCb: updateBackupCb,
@@ -135,7 +135,7 @@ func InitializeBackup(password string, updateBackupCb UpdateBackupFn,
 // ResumeBackup resumes a backup by restoring the Backup object and registering
 // a new callback. Call this to resume backups that have already been
 // initialized. Returns an error if backups have not already been initialized.
-func ResumeBackup(updateBackupCb UpdateBackupFn, container *messenger.Container,
+func ResumeBackup(updateBackupCb UpdateBackupFn, container *xxdk.Container,
 	e2e E2e, session Session, ud UserDiscovery, kv *versioned.KV,
 	rng *fastRNG.StreamGenerator) (*Backup, error) {
 	_, _, _, err := loadBackup(kv)
diff --git a/api/messenger/backupRestore.go b/backup/backupRestore.go
similarity index 72%
rename from api/messenger/backupRestore.go
rename to backup/backupRestore.go
index d3187f7fcc4b9f4535559351bc2d2ff68c7484ac..93ba6778ea16e2a7982ee5a1c7e487b7d08bf406 100644
--- a/api/messenger/backupRestore.go
+++ b/backup/backupRestore.go
@@ -1,22 +1,28 @@
+////////////////////////////////////////////////////////////////////////////////
+// Copyright © 2022 Privategrity Corporation                                   /
+//                                                                             /
+// All rights reserved.                                                        /
+////////////////////////////////////////////////////////////////////////////////
+
 // FIXME: This is placeholder, there's got to be a better place to put
 // backup restoration than inside messenger.
 
-package messenger
+package backup
 
 import (
 	"github.com/pkg/errors"
-	"gitlab.com/elixxir/client/api"
 	"gitlab.com/elixxir/client/e2e"
 	"gitlab.com/elixxir/client/e2e/rekey"
 	"gitlab.com/elixxir/client/storage"
 	"gitlab.com/elixxir/client/storage/user"
 	"gitlab.com/elixxir/client/ud"
+	"gitlab.com/elixxir/client/xxdk"
 	cryptoBackup "gitlab.com/elixxir/crypto/backup"
 	"gitlab.com/elixxir/primitives/fact"
 	"gitlab.com/xx_network/primitives/id"
 )
 
-// NewClientFromBackup constructs a new Client from an encrypted
+// NewClientFromBackup constructs a new E2e from an encrypted
 // backup. The backup is decrypted using the backupPassphrase. On
 // success a successful client creation, the function will return a
 // JSON encoded list of the E2E partners contained in the backup and a
@@ -34,16 +40,16 @@ func NewClientFromBackup(ndfJSON, storageDir string, sessionPassword,
 
 	usr := user.NewUserFromBackup(backUp)
 
-	def, err := api.ParseNDF(ndfJSON)
+	def, err := xxdk.ParseNDF(ndfJSON)
 	if err != nil {
 		return nil, "", err
 	}
 
-	cmixGrp, e2eGrp := api.DecodeGroups(def)
+	cmixGrp, e2eGrp := xxdk.DecodeGroups(def)
 
 	// Note we do not need registration here
-	storageSess, err := api.CheckVersionAndSetupStorage(def, storageDir,
-		[]byte(sessionPassword), usr, cmixGrp, e2eGrp,
+	storageSess, err := xxdk.CheckVersionAndSetupStorage(def, storageDir,
+		sessionPassword, usr, cmixGrp, e2eGrp,
 		backUp.RegistrationCode)
 	if err != nil {
 		return nil, "", err
@@ -84,7 +90,6 @@ func NewClientFromBackup(ndfJSON, storageDir string, sessionPassword,
 			phone = f
 		}
 	}
-	ud.InitStoreFromBackup(storageSess.GetKV(), username, email, phone)
-
-	return backUp.Contacts.Identities, backUp.JSONParams, nil
+	err = ud.InitStoreFromBackup(storageSess.GetKV(), username, email, phone)
+	return backUp.Contacts.Identities, backUp.JSONParams, err
 }
diff --git a/backup/backup_test.go b/backup/backup_test.go
index f61dc0a06b02adcaa3218c909a90dda6c90c3985..bcaf8cf35bb4c7d0044cbf7e2a79e445e0d9c207 100644
--- a/backup/backup_test.go
+++ b/backup/backup_test.go
@@ -9,12 +9,12 @@ package backup
 
 import (
 	"bytes"
+	"gitlab.com/elixxir/client/xxdk"
 	"reflect"
 	"strings"
 	"testing"
 	"time"
 
-	"gitlab.com/elixxir/client/api/messenger"
 	"gitlab.com/elixxir/client/storage"
 	"gitlab.com/elixxir/client/storage/versioned"
 	"gitlab.com/elixxir/ekv"
@@ -32,7 +32,7 @@ func Test_InitializeBackup(t *testing.T) {
 	cbChan := make(chan []byte, 2)
 	cb := func(encryptedBackup []byte) { cbChan <- encryptedBackup }
 	expectedPassword := "MySuperSecurePassword"
-	b, err := InitializeBackup(expectedPassword, cb, &messenger.Container{},
+	b, err := InitializeBackup(expectedPassword, cb, &xxdk.Container{},
 		newMockE2e(t),
 		newMockSession(t), newMockUserDiscovery(), kv, rngGen)
 	if err != nil {
@@ -84,7 +84,7 @@ func Test_ResumeBackup(t *testing.T) {
 	cbChan1 := make(chan []byte)
 	cb1 := func(encryptedBackup []byte) { cbChan1 <- encryptedBackup }
 	expectedPassword := "MySuperSecurePassword"
-	b, err := InitializeBackup(expectedPassword, cb1, &messenger.Container{},
+	b, err := InitializeBackup(expectedPassword, cb1, &xxdk.Container{},
 		newMockE2e(t), newMockSession(t), newMockUserDiscovery(), kv, rngGen)
 	if err != nil {
 		t.Errorf("Failed to initialize new Backup: %+v", err)
@@ -106,7 +106,7 @@ func Test_ResumeBackup(t *testing.T) {
 	// Resume the backup with a new callback
 	cbChan2 := make(chan []byte)
 	cb2 := func(encryptedBackup []byte) { cbChan2 <- encryptedBackup }
-	b2, err := ResumeBackup(cb2, &messenger.Container{}, newMockE2e(t), newMockSession(t),
+	b2, err := ResumeBackup(cb2, &xxdk.Container{}, newMockE2e(t), newMockSession(t),
 		newMockUserDiscovery(), kv, rngGen)
 	if err != nil {
 		t.Errorf("ResumeBackup returned an error: %+v", err)
@@ -149,7 +149,7 @@ func Test_resumeBackup_NoKeyError(t *testing.T) {
 	expectedErr := "object not found"
 	s := storage.InitTestingSession(t)
 	rngGen := fastRNG.NewStreamGenerator(1000, 10, csprng.NewSystemRNG)
-	_, err := ResumeBackup(nil, &messenger.Container{}, newMockE2e(t), newMockSession(t),
+	_, err := ResumeBackup(nil, &xxdk.Container{}, newMockE2e(t), newMockSession(t),
 		newMockUserDiscovery(), s.GetKV(), rngGen)
 	if err == nil || !strings.Contains(err.Error(), expectedErr) {
 		t.Errorf("ResumeBackup did not return the expected error when no "+
@@ -392,7 +392,7 @@ func newTestBackup(password string, cb UpdateBackupFn, t *testing.T) *Backup {
 	b, err := InitializeBackup(
 		password,
 		cb,
-		&messenger.Container{},
+		&xxdk.Container{},
 		newMockE2e(t),
 		newMockSession(t),
 		newMockUserDiscovery(),
@@ -416,7 +416,7 @@ func Benchmark_InitializeBackup(t *testing.B) {
 	expectedPassword := "MySuperSecurePassword"
 	for i := 0; i < t.N; i++ {
 		_, err := InitializeBackup(expectedPassword, cb,
-			&messenger.Container{},
+			&xxdk.Container{},
 			newMockE2e(t),
 			newMockSession(t), newMockUserDiscovery(), kv, rngGen)
 		if err != nil {
diff --git a/bindings/autheticatedConnection.go b/bindings/autheticatedConnection.go
index 758b8c741972d61dd6616d9e5691db83837df3d9..5e1f78f4e08f813881f01b3695b423a4c1cd2f1e 100644
--- a/bindings/autheticatedConnection.go
+++ b/bindings/autheticatedConnection.go
@@ -23,18 +23,18 @@ func (_ *AuthenticatedConnection) IsAuthenticated() bool {
 // ConnectWithAuthentication is called by the client (i.e. the one establishing
 // connection with the server). Once a connect.Connection has been established
 // with the server and then authenticate their identity to the server.
-// accepts a marshalled Identity and contact.Contact object
-func (c *Client) ConnectWithAuthentication(recipientContact []byte, myIdentity []byte) (*AuthenticatedConnection, error) {
+// accepts a marshalled TransmissionIdentity and contact.Contact object
+func (c *Cmix) ConnectWithAuthentication(e2eId int, recipientContact []byte) (*AuthenticatedConnection, error) {
 	cont, err := contact.Unmarshal(recipientContact)
 	if err != nil {
 		return nil, err
 	}
-	myID, rsaPriv, salt, myDHPriv, err := c.unmarshalIdentity(myIdentity)
+
+	e2eClient, err := e2eTrackerSingleton.get(e2eId)
 	if err != nil {
 		return nil, err
 	}
 
-	connection, err := connect.ConnectWithAuthentication(cont, myID, salt, rsaPriv, myDHPriv, c.api.GetRng(),
-		c.api.GetStorage().GetE2EGroup(), c.api.GetCmix(), connect.GetDefaultParams())
+	connection, err := connect.ConnectWithAuthentication(cont, e2eClient.api, connect.GetDefaultParams())
 	return authenticatedConnectionTrackerSingleton.make(connection), nil
 }
diff --git a/bindings/clientTracker.go b/bindings/clientTracker.go
deleted file mode 100644
index a93bfc62a1e5b8fc35672ab2ff55701278012cc9..0000000000000000000000000000000000000000
--- a/bindings/clientTracker.go
+++ /dev/null
@@ -1,54 +0,0 @@
-package bindings
-
-import (
-	"github.com/pkg/errors"
-	"gitlab.com/elixxir/client/api"
-	"sync"
-)
-
-// clientTracker is a singleton used to keep track of extant clients, allowing
-// for race condition free passing over the bindings
-
-type clientTracker struct {
-	clients map[int]*Client
-	count   int
-	mux     sync.RWMutex
-}
-
-// make makes a client from an API client, assigning it a unique ID
-func (ct *clientTracker) make(c *api.Client) *Client {
-	ct.mux.Lock()
-	defer ct.mux.Unlock()
-
-	id := ct.count
-	ct.count++
-
-	ct.clients[id] = &Client{
-		api: c,
-		id:  id,
-	}
-
-	return ct.clients[id]
-}
-
-//get returns a client given its ID
-func (ct *clientTracker) get(id int) (*Client, error) {
-	ct.mux.RLock()
-	defer ct.mux.RUnlock()
-
-	c, exist := ct.clients[id]
-	if !exist {
-		return nil, errors.Errorf("Cannot get client for id %d, client "+
-			"does not exist", id)
-	}
-
-	return c, nil
-}
-
-//deletes a client if it exists
-func (ct *clientTracker) delete(id int) {
-	ct.mux.Lock()
-	defer ct.mux.Unlock()
-
-	delete(ct.clients, id)
-}
diff --git a/bindings/client.go b/bindings/cmix.go
similarity index 65%
rename from bindings/client.go
rename to bindings/cmix.go
index 24f69dceef7ecd992c6ebdb3543aae8dad18f209..85b847defc73caad18bbbb02de502cb093b57660 100644
--- a/bindings/client.go
+++ b/bindings/cmix.go
@@ -4,26 +4,26 @@ import (
 	"fmt"
 	"github.com/pkg/errors"
 	jww "github.com/spf13/jwalterweatherman"
-	"gitlab.com/elixxir/client/api"
+	"gitlab.com/elixxir/client/xxdk"
 )
 
-// sets the log level
+// init sets the log level
 func init() {
 	jww.SetLogThreshold(jww.LevelInfo)
 	jww.SetStdoutThreshold(jww.LevelInfo)
 }
 
-//client tracker singleton, used to track clients so they can be referenced by
-//id back over the bindings
-var clientTrackerSingleton = &clientTracker{
-	clients: make(map[int]*Client),
+// cmixTrackerSingleton is used to track Cmix objects so that
+// they can be referenced by id back over the bindings
+var cmixTrackerSingleton = &cmixTracker{
+	clients: make(map[int]*Cmix),
 	count:   0,
 }
 
-// Client BindingsClient wraps the api.Client, implementing additional functions
-// to support the gomobile Client interface
-type Client struct {
-	api *api.Client
+// Cmix BindingsClient wraps the xxdk.Cmix, implementing additional functions
+// to support the gomobile Cmix interface
+type Cmix struct {
+	api *xxdk.Cmix
 	id  int
 }
 
@@ -34,7 +34,7 @@ type Client struct {
 //
 // Users of this function should delete the storage directory on error.
 func NewClient(network, storageDir string, password []byte, regCode string) error {
-	if err := api.NewClient(network, storageDir, password, regCode); err != nil {
+	if err := xxdk.NewClient(network, storageDir, password, regCode); err != nil {
 		return errors.New(fmt.Sprintf("Failed to create new client: %+v",
 			err))
 	}
@@ -49,19 +49,15 @@ func NewClient(network, storageDir string, password []byte, regCode string) erro
 // Login does not block on network connection, and instead loads and
 // starts subprocesses to perform network operations.
 // TODO: add in custom parameters instead of the default
-func Login(storageDir string, password []byte) (*Client, error) {
-
-	client, err := api.Login(storageDir, password, api.GetDefaultParams())
+func Login(storageDir string, password []byte) (*Cmix, error) {
+	client, err := xxdk.LoadCmix(storageDir, password, xxdk.GetDefaultParams())
 	if err != nil {
 		return nil, errors.New(fmt.Sprintf("Failed to login: %+v", err))
 	}
 
-	return clientTrackerSingleton.make(client), nil
+	return cmixTrackerSingleton.make(client), nil
 }
 
-func (c *Client) GetID() int {
+func (c *Cmix) GetID() int {
 	return c.id
 }
-
-
-
diff --git a/bindings/cmixTracker.go b/bindings/cmixTracker.go
new file mode 100644
index 0000000000000000000000000000000000000000..cb7d215a0613c780cc228998c381efec8b9ad36a
--- /dev/null
+++ b/bindings/cmixTracker.go
@@ -0,0 +1,54 @@
+package bindings
+
+import (
+	"github.com/pkg/errors"
+	"gitlab.com/elixxir/client/xxdk"
+	"sync"
+)
+
+// cmixTracker is a singleton used to keep track of extant Cmix objects,
+// preventing race conditions created by passing it over the bindings
+type cmixTracker struct {
+	clients map[int]*Cmix
+	count   int
+	mux     sync.RWMutex
+}
+
+// make a Cmix from an xxdk.Cmix, assigns it a unique ID,
+// and adds it to the cmixTracker
+func (ct *cmixTracker) make(c *xxdk.Cmix) *Cmix {
+	ct.mux.Lock()
+	defer ct.mux.Unlock()
+
+	id := ct.count
+	ct.count++
+
+	ct.clients[id] = &Cmix{
+		api: c,
+		id:  id,
+	}
+
+	return ct.clients[id]
+}
+
+// get a Cmix from the cmixTracker given its ID
+func (ct *cmixTracker) get(id int) (*Cmix, error) {
+	ct.mux.RLock()
+	defer ct.mux.RUnlock()
+
+	c, exist := ct.clients[id]
+	if !exist {
+		return nil, errors.Errorf("Cannot get client for id %d, client "+
+			"does not exist", id)
+	}
+
+	return c, nil
+}
+
+// delete a Cmix if it exists in the cmixTracker
+func (ct *cmixTracker) delete(id int) {
+	ct.mux.Lock()
+	defer ct.mux.Unlock()
+
+	delete(ct.clients, id)
+}
diff --git a/bindings/connect.go b/bindings/connect.go
index 9910af952b93165e769b15e9e54d508adcf378e3..8be9e4881ec5f345fd7d80b932e22d8d693ae19f 100644
--- a/bindings/connect.go
+++ b/bindings/connect.go
@@ -31,21 +31,20 @@ func (c *Connection) GetId() int {
 // This function is to be used sender-side and will block until the
 // partner.Manager is confirmed.
 // recipientContact - marshalled contact.Contact object
-// myIdentity - marshalled Identity object
-func (c *Client) Connect(recipientContact []byte, myIdentity []byte) (
+// myIdentity - marshalled TransmissionIdentity object
+func (c *Cmix) Connect(e2eId int, recipientContact []byte) (
 	*Connection, error) {
 	cont, err := contact.Unmarshal(recipientContact)
 	if err != nil {
 		return nil, err
 	}
-	myID, _, _, myDHPriv, err := c.unmarshalIdentity(myIdentity)
+
+	e2eClient, err := e2eTrackerSingleton.get(e2eId)
 	if err != nil {
 		return nil, err
 	}
 
-	connection, err := connect.Connect(cont, myID, myDHPriv, c.api.GetRng(),
-		c.api.GetStorage().GetE2EGroup(), c.api.GetCmix(), connect.GetDefaultParams())
-
+	connection, err := connect.Connect(cont, e2eClient.api, connect.GetDefaultParams())
 	if err != nil {
 		return nil, err
 	}
diff --git a/bindings/contact.go b/bindings/contact.go
index cf5647bd1b5a93ec31390d1b9cce2b28719cc907..c07b66f8f790eb9ffb4bdf0081aad25c32c8185c 100644
--- a/bindings/contact.go
+++ b/bindings/contact.go
@@ -2,16 +2,15 @@ package bindings
 
 import (
 	"encoding/json"
-	"gitlab.com/elixxir/client/api"
+	"gitlab.com/elixxir/client/xxdk"
 	"gitlab.com/elixxir/crypto/contact"
-	"gitlab.com/elixxir/crypto/cyclic"
 	"gitlab.com/elixxir/primitives/fact"
 	"gitlab.com/xx_network/crypto/signature/rsa"
 	"gitlab.com/xx_network/primitives/id"
 )
 
-// Identity struct
-// Example marshalled Identity:
+// TransmissionIdentity struct
+// Example marshalled TransmissionIdentity:
 // {"ID":"emV6aW1hAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD",  // User ID (base64)
 //  // RSA Private key (PEM format)
 //  "RSAPrivatePem":"LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcFFJQkFBS0NBUUVBNU15dTdhYjBJOS9UL1BFUUxtd2x3ejZHV3FjMUNYemVIVXhoVEc4bmg1WWRWSXMxCmJ2THpBVjNOMDJxdXN6K2s4TVFEWjBtejMzdkswUmhPczZIY0NUSFdzTEpXRkE5WWpzWWlCRi9qTDd1bmd1ckIKL2tvK1JJSnNrWGFWaEZaazRGdERoRXhTNWY4RnR0Qmk1NmNLZmdJQlVKT3ozZi9qQllTMkxzMlJ6cWV5YXM3SApjV2RaME9TclBTT3BiYlViU1FPbS9LWnlweGZHU21yZ2oxRUZuU1dZZ2xGZTdUOTRPbHF5MG14QTV5clVXbHorCk9sK3hHbXpCNUp4WUFSMU9oMFQrQTk4RWMrTUZHNm43L1MraDdzRDgybGRnVnJmbStFTzRCdmFKeTRESGZGMWgKNnp6QnVnY25NUVFGc0dLeDFYWC9COTVMdUpPVjdyeXlDbzZGbHdJREFRQUJBb0lCQVFDaUh6OGNlcDZvQk9RTAphUzBVRitHeU5VMnlVcVRNTWtTWThoUkh1c09CMmFheXoybHZVb3RLUHBPbjZRSWRWVTJrcE4vY2dtY0lSb2x5CkhBMDRUOHJBWVNaRlVqaVlRajkzKzRFREpJYXd2Z0YyVEs1bFoyb3oxVTdreStncU82V0RMR2Z0Q0wvODVQWEIKa210aXhnUXpRV3g1RWcvemtHdm03eURBalQxeDloNytsRjJwNFlBam5kT2xTS0dmQjFZeTR1RXBQd0kwc1lWdgpKQWc0MEFxbllZUmt4emJPbmQxWGNjdEJFN2Z1VDdrWXhoeSs3WXYrUTJwVy9BYmh6NGlHOEY1MW9GMGZwV0czCmlISDhsVXZFTkp2SUZEVHZ0UEpESlFZalBRN3lUbGlGZUdrMXZUQkcyQkpQNExzVzhpbDZOeUFuRktaY1hOQ24KeHVCendiSlJBb0dCQVBUK0dGTVJGRHRHZVl6NmwzZmg3UjJ0MlhrMysvUmpvR3BDUWREWDhYNERqR1pVd1RGVQpOS2tQTTNjS29ia2RBYlBDb3FpL0tOOVBibk9QVlZ3R3JkSE9vSnNibFVHYmJGamFTUzJQMFZnNUVhTC9rT2dUCmxMMUdoVFpIUWk1VUlMM0p4M1Z3T0ZRQ3RQOU1UQlQ0UEQvcEFLbDg3VTJXN3JTY1dGV1ZGbFNkQW9HQkFPOFUKVmhHWkRpVGFKTWVtSGZIdVYrNmtzaUlsam9aUVVzeGpmTGNMZ2NjV2RmTHBqS0ZWTzJNN3NqcEJEZ0w4NmFnegorVk14ZkQzZ1l0SmNWN01aMVcwNlZ6TlNVTHh3a1dRY1hXUWdDaXc5elpyYlhCUmZRNUVjMFBlblVoWWVwVzF5CkpkTC8rSlpQeDJxSzVrQytiWU5EdmxlNWdpcjlDSGVzTlR5enVyckRBb0dCQUl0cTJnN1RaazhCSVFUUVNrZ24Kb3BkRUtzRW4wZExXcXlBdENtVTlyaWpHL2l2eHlXczMveXZDQWNpWm5VVEp0QUZISHVlbXVTeXplQ2g5QmRkegoyWkRPNUdqQVBxVHlQS3NudFlNZkY4UDczZ1NES1VSWWVFbHFDejdET0c5QzRzcitPK3FoN1B3cCtqUmFoK1ZiCkNuWllNMDlBVDQ3YStJYUJmbWRkaXpLbEFvR0JBSmo1dkRDNmJIQnNISWlhNUNJL1RZaG5YWXUzMkVCYytQM0sKMHF3VThzOCtzZTNpUHBla2Y4RjVHd3RuUU4zc2tsMk1GQWFGYldmeVFZazBpUEVTb0p1cGJzNXA1enNNRkJ1bwpncUZrVnQ0RUZhRDJweTVwM2tQbDJsZjhlZXVwWkZScGE0WmRQdVIrMjZ4eWYrNEJhdlZJeld3NFNPL1V4Q3crCnhqbTNEczRkQW9HQWREL0VOa1BjU004c1BCM3JSWW9MQ2twcUV2U0MzbVZSbjNJd3c1WFAwcDRRVndhRmR1ckMKYUhtSE1EekNrNEUvb0haQVhFdGZ2S2tRaUI4MXVYM2c1aVo4amdYUVhXUHRteTVIcVVhcWJYUTlENkxWc3B0egpKL3R4SWJLMXp5c1o2bk9IY1VoUUwyVVF6SlBBRThZNDdjYzVzTThEN3kwZjJ0QURTQUZNMmN3PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQ==",
@@ -20,7 +19,7 @@ import (
 //  // DH Private key
 //  "DHKeyPrivate":"eyJWYWx1ZSI6NDU2MDgzOTEzMjA0OTIyODA5Njg2MDI3MzQ0MzM3OTA0MzAyODYwMjM2NDk2NDM5NDI4NTcxMTMwNDMzOTQwMzgyMTIyMjY4OTQzNTMyMjIyMzc1MTkzNTEzMjU4MjA4MDA0NTczMDY4MjEwNzg2NDI5NjA1MjA0OTA3MjI2ODI5OTc3NTczMDkxODY0NTY3NDExMDExNjQxNCwiRmluZ2VycHJpbnQiOjE2ODAxNTQxNTExMjMzMDk4MzYzfQ=="
 // }
-type Identity struct {
+type TransmissionIdentity struct {
 	ID            []byte
 	RSAPrivatePem []byte
 	Salt          []byte
@@ -28,17 +27,17 @@ type Identity struct {
 }
 
 // MakeIdentity generates a new cryptographic identity for receiving messages
-func (c *Client) MakeIdentity() ([]byte, error) {
+func (c *Cmix) MakeIdentity() ([]byte, error) {
 	s := c.api.GetRng().GetStream()
 	defer s.Close()
-	ident, err := api.MakeIdentity(s, c.api.GetStorage().GetE2EGroup())
+	ident, err := xxdk.MakeTransmissionIdentity(s, c.api.GetStorage().GetE2EGroup())
 
 	dhPrivJson, err := ident.DHKeyPrivate.MarshalJSON()
 	if err != nil {
 		return nil, err
 	}
 	//create the identity object
-	I := Identity{
+	I := TransmissionIdentity{
 		ID:            ident.ID.Marshal(),
 		RSAPrivatePem: rsa.CreatePrivateKeyPem(ident.RSAPrivatePem),
 		Salt:          ident.Salt,
@@ -48,19 +47,19 @@ func (c *Client) MakeIdentity() ([]byte, error) {
 	return json.Marshal(&I)
 }
 
-// GetContactFromIdentity accepts a marshalled Identity object and returns a marshalled contact.Contact object
-func (c *Client) GetContactFromIdentity(identity []byte) ([]byte, error) {
-	uID, _, _, dhKey, err := c.unmarshalIdentity(identity)
+// GetContactFromIdentity accepts a marshalled TransmissionIdentity object and returns a marshalled contact.Contact object
+func (c *Cmix) GetContactFromIdentity(identity []byte) ([]byte, error) {
+	unmarshalledIdentity, err := c.unmarshalIdentity(identity)
 	if err != nil {
 		return nil, err
 	}
 
 	grp := c.api.GetStorage().GetE2EGroup()
 
-	dhPub := grp.ExpG(dhKey, grp.NewInt(1))
+	dhPub := grp.ExpG(unmarshalledIdentity.DHKeyPrivate, grp.NewInt(1))
 
 	ct := contact.Contact{
-		ID:             uID,
+		ID:             unmarshalledIdentity.ID,
 		DhPubKey:       dhPub,
 		OwnershipProof: nil,
 		Facts:          nil,
@@ -69,31 +68,34 @@ func (c *Client) GetContactFromIdentity(identity []byte) ([]byte, error) {
 	return ct.Marshal(), nil
 }
 
-func (c *Client) unmarshalIdentity(marshaled []byte) (*id.ID, *rsa.PrivateKey, []byte,
-	*cyclic.Int, error) {
-	I := Identity{}
-	err := json.Unmarshal(marshaled, &I)
+func (c *Cmix) unmarshalIdentity(marshaled []byte) (xxdk.TransmissionIdentity, error) {
+	newIdentity := xxdk.TransmissionIdentity{}
+
+	// Unmarshal given identity into TransmissionIdentity object
+	givenIdentity := TransmissionIdentity{}
+	err := json.Unmarshal(marshaled, &givenIdentity)
 	if err != nil {
-		return nil, nil, nil, nil, err
+		return xxdk.TransmissionIdentity{}, err
 	}
 
-	uID, err := id.Unmarshal(I.ID)
+	newIdentity.ID, err = id.Unmarshal(givenIdentity.ID)
 	if err != nil {
-		return nil, nil, nil, nil, err
+		return xxdk.TransmissionIdentity{}, err
 	}
 
-	dhkey := c.api.GetStorage().GetE2EGroup().NewInt(1)
-	err = dhkey.UnmarshalJSON([]byte(I.DHKeyPrivate))
+	newIdentity.DHKeyPrivate = c.api.GetStorage().GetE2EGroup().NewInt(1)
+	err = newIdentity.DHKeyPrivate.UnmarshalJSON(givenIdentity.DHKeyPrivate)
 	if err != nil {
-		return nil, nil, nil, nil, err
+		return xxdk.TransmissionIdentity{}, err
 	}
 
-	rsaPriv, err := rsa.LoadPrivateKeyFromPem([]byte(I.RSAPrivatePem))
+	newIdentity.RSAPrivatePem, err = rsa.LoadPrivateKeyFromPem(givenIdentity.RSAPrivatePem)
 	if err != nil {
-		return nil, nil, nil, nil, err
+		return xxdk.TransmissionIdentity{}, err
 	}
 
-	return uID, rsaPriv, I.Salt, dhkey, nil
+	newIdentity.Salt = givenIdentity.Salt
+	return newIdentity, nil
 }
 
 // GetIDFromContact accepts a marshalled contact.Contact object & returns a marshalled id.ID object
diff --git a/bindings/contact_test.go b/bindings/contact_test.go
index adbf4d9c2a5d3c48e899ee5ba7f4123f44890034..97af0264f4bd9b76c9fe83017ff09477947b7a3d 100644
--- a/bindings/contact_test.go
+++ b/bindings/contact_test.go
@@ -22,14 +22,14 @@ func TestIdentity_JSON(t *testing.T) {
 	dhpkJson, _ := dhpk.MarshalJSON()
 	op := make([]byte, 64)
 	_, _ = rng.Read(op)
-	identity := Identity{
+	identity := TransmissionIdentity{
 		ID:            uid.Marshal(),
 		RSAPrivatePem: rsa.CreatePrivateKeyPem(pk),
 		Salt:          salt,
 		DHKeyPrivate:  dhpkJson,
 	}
 	im, _ := json.Marshal(identity)
-	t.Log("Marshalled Identity object")
+	t.Log("Marshalled TransmissionIdentity object")
 	t.Log(string(im))
 }
 
diff --git a/bindings/delivery.go b/bindings/delivery.go
index 57fcbfa4d34ede1307cb628691ca5fde4210bd47..9146e838f4381661385e4769b20a95ff4f74320b 100644
--- a/bindings/delivery.go
+++ b/bindings/delivery.go
@@ -65,7 +65,7 @@ type MessageDeliveryCallback interface {
 // This function takes the marshaled send report to ensure a memory leak does
 // not occur as a result of both sides of the bindings holding a reference to
 // the same pointer.
-func (c *Client) WaitForMessageDelivery(roundList []byte,
+func (c *Cmix) WaitForMessageDelivery(roundList []byte,
 	mdc MessageDeliveryCallback, timeoutMS int) error {
 	jww.INFO.Printf("WaitForMessageDelivery(%v, _, %v)",
 		roundList, timeoutMS)
diff --git a/bindings/e2e.go b/bindings/e2e.go
new file mode 100644
index 0000000000000000000000000000000000000000..6134db25db442727b6d32873f1f11d795f8d8f2c
--- /dev/null
+++ b/bindings/e2e.go
@@ -0,0 +1,100 @@
+////////////////////////////////////////////////////////////////////////////////
+// Copyright © 2022 Privategrity Corporation                                   /
+//                                                                             /
+// All rights reserved.                                                        /
+////////////////////////////////////////////////////////////////////////////////
+
+package bindings
+
+import (
+	"gitlab.com/elixxir/client/auth"
+	"gitlab.com/elixxir/client/cmix/identity/receptionID"
+	"gitlab.com/elixxir/client/cmix/rounds"
+	"gitlab.com/elixxir/client/xxdk"
+	"gitlab.com/elixxir/crypto/contact"
+)
+
+// e2eTrackerSingleton is used to track E2e objects so that
+// they can be referenced by id back over the bindings
+var e2eTrackerSingleton = &e2eTracker{
+	clients: make(map[int]*E2e),
+	count:   0,
+}
+
+// E2e BindingsClient wraps the xxdk.E2e, implementing additional functions
+// to support the gomobile E2e interface
+type E2e struct {
+	api *xxdk.E2e
+	id  int
+}
+
+// Login creates and returns a new E2e object and adds it to the e2eTrackerSingleton
+// identity should be created via MakeIdentity() and passed in here
+// If callbacks is left nil, a default auth.Callbacks will be used
+func (e *E2e) Login(cmixId int, callbacks AuthCallbacks, identity []byte) (*E2e, error) {
+	cmix, err := cmixTrackerSingleton.get(cmixId)
+	if err != nil {
+		return nil, err
+	}
+
+	newIdentity, err := cmix.unmarshalIdentity(identity)
+	if err != nil {
+		return nil, err
+	}
+
+	var authCallbacks auth.Callbacks
+	if callbacks == nil {
+		authCallbacks = auth.DefaultAuthCallbacks{}
+	} else {
+		authCallbacks = &authCallback{bindingsCbs: callbacks}
+	}
+
+	newE2e, err := xxdk.Login(cmix.api, authCallbacks, newIdentity)
+	if err != nil {
+		return nil, err
+	}
+	return e2eTrackerSingleton.make(newE2e), nil
+}
+
+// AuthCallbacks is the bindings-specific interface for auth.Callbacks methods.
+type AuthCallbacks interface {
+	Request(contact, receptionId []byte, ephemeralId, roundId int64)
+	Confirm(contact, receptionId []byte, ephemeralId, roundId int64)
+	Reset(contact, receptionId []byte, ephemeralId, roundId int64)
+}
+
+// authCallback implements AuthCallbacks as a way of obtaining
+// an auth.Callbacks over the bindings
+type authCallback struct {
+	bindingsCbs AuthCallbacks
+}
+
+// convertAuthCallbacks turns an auth.Callbacks into an AuthCallbacks
+func convertAuthCallbacks(requestor contact.Contact,
+	receptionID receptionID.EphemeralIdentity,
+	round rounds.Round) (contact []byte, receptionId []byte, ephemeralId int64, roundId int64) {
+
+	contact = requestor.Marshal()
+	receptionId = receptionID.Source.Marshal()
+	ephemeralId = int64(receptionID.EphId.UInt64())
+	roundId = int64(round.ID)
+	return
+}
+
+// Confirm will be called when an auth Confirm message is processed.
+func (a *authCallback) Confirm(requestor contact.Contact,
+	receptionID receptionID.EphemeralIdentity, round rounds.Round) {
+	a.bindingsCbs.Confirm(convertAuthCallbacks(requestor, receptionID, round))
+}
+
+// Request will be called when an auth Request message is processed.
+func (a *authCallback) Request(requestor contact.Contact,
+	receptionID receptionID.EphemeralIdentity, round rounds.Round) {
+	a.bindingsCbs.Request(convertAuthCallbacks(requestor, receptionID, round))
+}
+
+// Reset will be called when an auth Reset operation occurs.
+func (a *authCallback) Reset(requestor contact.Contact,
+	receptionID receptionID.EphemeralIdentity, round rounds.Round) {
+	a.bindingsCbs.Reset(convertAuthCallbacks(requestor, receptionID, round))
+}
diff --git a/bindings/e2eTracker.go b/bindings/e2eTracker.go
new file mode 100644
index 0000000000000000000000000000000000000000..8f3ff5374ddb048642eeeda0a74a04a7f6bc3c44
--- /dev/null
+++ b/bindings/e2eTracker.go
@@ -0,0 +1,61 @@
+////////////////////////////////////////////////////////////////////////////////
+// Copyright © 2022 Privategrity Corporation                                   /
+//                                                                             /
+// All rights reserved.                                                        /
+////////////////////////////////////////////////////////////////////////////////
+
+package bindings
+
+import (
+	"github.com/pkg/errors"
+	"gitlab.com/elixxir/client/xxdk"
+	"sync"
+)
+
+// e2eTracker is a singleton used to keep track of extant E2e objects,
+// preventing race conditions created by passing it over the bindings
+type e2eTracker struct {
+	// TODO: Key on Identity.ID to prevent duplication
+	clients map[int]*E2e
+	count   int
+	mux     sync.RWMutex
+}
+
+// make a E2e from an xxdk.E2e, assigns it a unique ID,
+// and adds it to the e2eTracker
+func (ct *e2eTracker) make(c *xxdk.E2e) *E2e {
+	ct.mux.Lock()
+	defer ct.mux.Unlock()
+
+	id := ct.count
+	ct.count++
+
+	ct.clients[id] = &E2e{
+		api: c,
+		id:  id,
+	}
+
+	return ct.clients[id]
+}
+
+// get an E2e from the e2eTracker given its ID
+func (ct *e2eTracker) get(id int) (*E2e, error) {
+	ct.mux.RLock()
+	defer ct.mux.RUnlock()
+
+	c, exist := ct.clients[id]
+	if !exist {
+		return nil, errors.Errorf("Cannot get client for id %d, client "+
+			"does not exist", id)
+	}
+
+	return c, nil
+}
+
+// delete an E2e if it exists in the e2eTracker
+func (ct *e2eTracker) delete(id int) {
+	ct.mux.Lock()
+	defer ct.mux.Unlock()
+
+	delete(ct.clients, id)
+}
diff --git a/bindings/follow.go b/bindings/follow.go
index ae81595b23ed0bbb627f6e112b86c5af47903919..34bb4c58eabffb120a2fc1dbad6cfc57b51324d5 100644
--- a/bindings/follow.go
+++ b/bindings/follow.go
@@ -35,7 +35,7 @@ import (
 //		Responds to sent rekeys and executes them
 //   - KeyExchange Confirm (/keyExchange/confirm.go)
 //		Responds to confirmations of successful rekey operations
-func (c *Client) StartNetworkFollower(timeoutMS int) error {
+func (c *Cmix) StartNetworkFollower(timeoutMS int) error {
 	timeout := time.Duration(timeoutMS) * time.Millisecond
 	return c.api.StartNetworkFollower(timeout)
 }
@@ -45,7 +45,7 @@ func (c *Client) StartNetworkFollower(timeoutMS int) error {
 // fails to stop it.
 // if the network follower is running and this fails, the client object will
 // most likely be in an unrecoverable state and need to be trashed.
-func (c *Client) StopNetworkFollower() error {
+func (c *Cmix) StopNetworkFollower() error {
 	if err := c.api.StopNetworkFollower(); err != nil {
 		return errors.New(fmt.Sprintf("Failed to stop the "+
 			"network follower: %+v", err))
@@ -55,7 +55,7 @@ func (c *Client) StopNetworkFollower() error {
 
 // WaitForNewtwork will block until either the network is healthy or the
 // passed timeout. It will return true if the network is healthy
-func (c *Client) WaitForNetwork(timeoutMS int) bool {
+func (c *Cmix) WaitForNetwork(timeoutMS int) bool {
 	start := netTime.Now()
 	timeout := time.Duration(timeoutMS) * time.Millisecond
 	for netTime.Since(start) < timeout {
@@ -72,7 +72,7 @@ func (c *Client) WaitForNetwork(timeoutMS int) bool {
 // Starting - 1000
 // Running	- 2000
 // Stopping	- 3000
-func (c *Client) NetworkFollowerStatus() int {
+func (c *Cmix) NetworkFollowerStatus() int {
 	return int(c.api.NetworkFollowerStatus())
 }
 
@@ -82,13 +82,13 @@ func (c *Client) NetworkFollowerStatus() int {
 // Due to the handling of comms on iOS, where the OS can
 // block indefiently, it may not enter the stopped
 // state apropreatly. This can be used instead.
-func (c *Client) HasRunningProcessies() bool {
+func (c *Cmix) HasRunningProcessies() bool {
 	return c.api.HasRunningProcessies()
 }
 
 // IsNetworkHealthy returns true if the network is read to be in a healthy state where
 // messages can be sent
-func (c *Client) IsNetworkHealthy() bool {
+func (c *Cmix) IsNetworkHealthy() bool {
 	return c.api.GetCmix().IsHealthy()
 }
 
@@ -101,11 +101,11 @@ type NetworkHealthCallback interface {
 // RegisterNetworkHealthCB registers the network health callback to be called
 // any time the network health changes. Returns a unique ID that can be used to
 // unregister the network health callback.
-func (c *Client) RegisterNetworkHealthCB(nhc NetworkHealthCallback) int64 {
+func (c *Cmix) RegisterNetworkHealthCB(nhc NetworkHealthCallback) int64 {
 	return int64(c.api.GetCmix().AddHealthCallback(nhc.Callback))
 }
 
-func (c *Client) UnregisterNetworkHealthCB(funcID int64) {
+func (c *Cmix) UnregisterNetworkHealthCB(funcID int64) {
 	c.api.GetCmix().RemoveHealthCallback(uint64(funcID))
 }
 
@@ -115,7 +115,7 @@ type ClientError interface {
 
 // RegisterClientErrorCallback registers the callback to handle errors from the
 // long running threads controlled by StartNetworkFollower and StopNetworkFollower
-func (c *Client) RegisterClientErrorCallback(clientError ClientError) {
+func (c *Cmix) RegisterClientErrorCallback(clientError ClientError) {
 	errChan := c.api.GetErrorsChannel()
 	go func() {
 		for report := range errChan {
diff --git a/bindings/ndf.go b/bindings/ndf.go
index 05e7d40b364678a028b66001c5de907840d1f6a7..ed72aa1d6a98c33861d814d18f032c7396e1a099 100644
--- a/bindings/ndf.go
+++ b/bindings/ndf.go
@@ -1,11 +1,11 @@
 package bindings
 
-import "gitlab.com/elixxir/client/api"
+import "gitlab.com/elixxir/client/xxdk"
 
 // DownloadAndVerifySignedNdfWithUrl retrieves the NDF from a specified URL.
 // The NDF is processed into a protobuf containing a signature which
 // is verified using the cert string passed in. The NDF is returned as marshaled
 // byte data which may be used to start a client.
 func DownloadAndVerifySignedNdfWithUrl(url, cert string) ([]byte, error) {
-	return api.DownloadAndVerifySignedNdfWithUrl(url, cert)
+	return xxdk.DownloadAndVerifySignedNdfWithUrl(url, cert)
 }
diff --git a/bindings/restlike.go b/bindings/restlike.go
index 7d7e649310d47d8fb4b28f7091569b195e131b83..c6c31c7ae744e644747a8da6018471fd03b8680e 100644
--- a/bindings/restlike.go
+++ b/bindings/restlike.go
@@ -34,7 +34,7 @@ type RestlikeMessage struct {
 // request - marshalled RestlikeMessage
 // Returns marshalled result RestlikeMessage
 func RestlikeRequest(clientID int, connectionID int, request []byte) ([]byte, error) {
-	cl, err := clientTrackerSingleton.get(clientID)
+	cl, err := cmixTrackerSingleton.get(clientID)
 	if err != nil {
 		return nil, err
 	}
@@ -78,7 +78,7 @@ func RestlikeRequest(clientID int, connectionID int, request []byte) ([]byte, er
 // request - marshalled RestlikeMessage
 // Returns marshalled result RestlikeMessage
 func RestlikeRequestAuth(clientID int, authConnectionID int, request []byte) ([]byte, error) {
-	cl, err := clientTrackerSingleton.get(clientID)
+	cl, err := cmixTrackerSingleton.get(clientID)
 	if err != nil {
 		return nil, err
 	}
diff --git a/bindings/version.go b/bindings/version.go
index 7e84bbd2ed1a0de0825e47a24e5e62ffa2f9f78a..4d6a4b2dc2dd86b1881aa3c918062cd50052fd98 100644
--- a/bindings/version.go
+++ b/bindings/version.go
@@ -6,19 +6,19 @@
 
 package bindings
 
-import "gitlab.com/elixxir/client/api"
+import "gitlab.com/elixxir/client/xxdk"
 
 // GetVersion returns the api SEMVER
 func GetVersion() string {
-	return api.SEMVER
+	return xxdk.SEMVER
 }
 
 // GetGitVersion rturns the api GITVERSION
 func GetGitVersion() string {
-	return api.GITVERSION
+	return xxdk.GITVERSION
 }
 
 // GetDependencies returns the api DEPENDENCIES
 func GetDependencies() string {
-	return api.DEPENDENCIES
+	return xxdk.DEPENDENCIES
 }
diff --git a/broadcast/asymmetric_test.go b/broadcast/asymmetric_test.go
index 2df1c2eb3d5c46de22c0c530b01f08ab97e6cd94..88aa2219d3495beb4659b97f5aa34ca4baf9c27f 100644
--- a/broadcast/asymmetric_test.go
+++ b/broadcast/asymmetric_test.go
@@ -66,7 +66,7 @@ func Test_asymmetricClient_Smoke(t *testing.T) {
 
 		// Test that Get returns the expected channel
 		if !reflect.DeepEqual(s.Get(), channel) {
-			t.Errorf("Client %d returned wrong channel."+
+			t.Errorf("Cmix %d returned wrong channel."+
 				"\nexpected: %+v\nreceived: %+v", i, channel, s.Get())
 		}
 	}
@@ -86,12 +86,12 @@ func Test_asymmetricClient_Smoke(t *testing.T) {
 				select {
 				case r := <-cbChan:
 					if !bytes.Equal(payload, r) {
-						t.Errorf("Client %d failed to receive expected "+
+						t.Errorf("Cmix %d failed to receive expected "+
 							"payload from client %d."+
 							"\nexpected: %q\nreceived: %q", j, i, payload, r)
 					}
 				case <-time.After(time.Second):
-					t.Errorf("Client %d timed out waiting for broadcast "+
+					t.Errorf("Cmix %d timed out waiting for broadcast "+
 						"payload from client %d.", j, i)
 				}
 			}(i, j, cbChans[j])
@@ -100,7 +100,7 @@ func Test_asymmetricClient_Smoke(t *testing.T) {
 		// Broadcast payload
 		_, _, err := clients[i].BroadcastAsymmetric(pk, payload, cmix.GetDefaultCMIXParams())
 		if err != nil {
-			t.Errorf("Client %d failed to send broadcast: %+v", i, err)
+			t.Errorf("Cmix %d failed to send broadcast: %+v", i, err)
 		}
 
 		// Wait for all clients to receive payload or time out
@@ -123,7 +123,7 @@ func Test_asymmetricClient_Smoke(t *testing.T) {
 			defer wg.Done()
 			select {
 			case r := <-cbChan:
-				t.Errorf("Client %d received message: %q", i, r)
+				t.Errorf("Cmix %d received message: %q", i, r)
 			case <-time.After(25 * time.Millisecond):
 			}
 		}(i, cbChans[i])
@@ -132,7 +132,7 @@ func Test_asymmetricClient_Smoke(t *testing.T) {
 	// Broadcast payload
 	_, _, err = clients[0].BroadcastAsymmetric(pk, payload, cmix.GetDefaultCMIXParams())
 	if err != nil {
-		t.Errorf("Client 0 failed to send broadcast: %+v", err)
+		t.Errorf("Cmix 0 failed to send broadcast: %+v", err)
 	}
 
 	wg.Wait()
diff --git a/broadcast/symmetric_test.go b/broadcast/symmetric_test.go
index a35ea5ecdca77b9abb5d874b3a28c99be6f08a7a..de76da504ca02fa6b8b1aa558bbef20a865a7730 100644
--- a/broadcast/symmetric_test.go
+++ b/broadcast/symmetric_test.go
@@ -72,7 +72,7 @@ func Test_symmetricClient_Smoke(t *testing.T) {
 
 		// Test that Get returns the expected channel
 		if !reflect.DeepEqual(s.Get(), channel) {
-			t.Errorf("Client %d returned wrong channel."+
+			t.Errorf("Cmix %d returned wrong channel."+
 				"\nexpected: %+v\nreceived: %+v", i, channel, s.Get())
 		}
 	}
@@ -92,12 +92,12 @@ func Test_symmetricClient_Smoke(t *testing.T) {
 				select {
 				case r := <-cbChan:
 					if !bytes.Equal(payload, r) {
-						t.Errorf("Client %d failed to receive expected "+
+						t.Errorf("Cmix %d failed to receive expected "+
 							"payload from client %d."+
 							"\nexpected: %q\nreceived: %q", j, i, payload, r)
 					}
 				case <-time.After(25 * time.Millisecond):
-					t.Errorf("Client %d timed out waiting for broadcast "+
+					t.Errorf("Cmix %d timed out waiting for broadcast "+
 						"payload from client %d.", j, i)
 				}
 			}(i, j, cbChans[j])
@@ -106,7 +106,7 @@ func Test_symmetricClient_Smoke(t *testing.T) {
 		// Broadcast payload
 		_, _, err := clients[i].Broadcast(payload, cmix.GetDefaultCMIXParams())
 		if err != nil {
-			t.Errorf("Client %d failed to send broadcast: %+v", i, err)
+			t.Errorf("Cmix %d failed to send broadcast: %+v", i, err)
 		}
 
 		// Wait for all clients to receive payload or time out
@@ -129,7 +129,7 @@ func Test_symmetricClient_Smoke(t *testing.T) {
 			defer wg.Done()
 			select {
 			case r := <-cbChan:
-				t.Errorf("Client %d received message: %q", i, r)
+				t.Errorf("Cmix %d received message: %q", i, r)
 			case <-time.After(25 * time.Millisecond):
 			}
 		}(i, cbChans[i])
@@ -138,7 +138,7 @@ func Test_symmetricClient_Smoke(t *testing.T) {
 	// Broadcast payload
 	_, _, err = clients[0].Broadcast(payload, cmix.GetDefaultCMIXParams())
 	if err != nil {
-		t.Errorf("Client 0 failed to send broadcast: %+v", err)
+		t.Errorf("Cmix 0 failed to send broadcast: %+v", err)
 	}
 
 	wg.Wait()
diff --git a/broadcast/utils_test.go b/broadcast/utils_test.go
index 944fd3c3993dce55cfe153b8b1c29cd828b66c5c..7bd4ac341a47f98359c76c7a06a5adb70f85f05f 100644
--- a/broadcast/utils_test.go
+++ b/broadcast/utils_test.go
@@ -34,7 +34,7 @@ func newRsaPubKey(seed int64, t *testing.T) *rsa.PublicKey {
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// Mock cMix Client                                                           //
+// Mock cMix                                                           //
 ////////////////////////////////////////////////////////////////////////////////
 
 type mockCmixHandler struct {
diff --git a/cmd/callbacks.go b/cmd/callbacks.go
index 07a4c66acd68cd14601ea63d32d9a30ddce28b4f..66a6ba9f2784540811ad192334d8270ded4005d1 100644
--- a/cmd/callbacks.go
+++ b/cmd/callbacks.go
@@ -10,7 +10,7 @@ package cmd
 
 import (
 	"fmt"
-	"gitlab.com/elixxir/client/api/messenger"
+	"gitlab.com/elixxir/client/xxdk"
 
 	jww "github.com/spf13/jwalterweatherman"
 	"gitlab.com/elixxir/client/catalog"
@@ -25,10 +25,10 @@ import (
 type authCallbacks struct {
 	autoConfirm bool
 	confCh      chan *id.ID
-	client      *messenger.Client
+	client      *xxdk.E2e
 }
 
-func makeAuthCallbacks(client *messenger.Client, autoConfirm bool) *authCallbacks {
+func makeAuthCallbacks(client *xxdk.E2e, autoConfirm bool) *authCallbacks {
 	return &authCallbacks{
 		autoConfirm: autoConfirm,
 		confCh:      make(chan *id.ID, 10),
@@ -71,7 +71,7 @@ func (a *authCallbacks) Reset(requestor contact.Contact,
 	fmt.Printf(msg)
 }
 
-func registerMessageListener(client *messenger.Client) chan receive.Message {
+func registerMessageListener(client *xxdk.E2e) chan receive.Message {
 	recvCh := make(chan receive.Message, 10000)
 	listenerID := client.GetE2E().RegisterChannel("DefaultCLIReceiver",
 		receive.AnyUser(), catalog.NoType, recvCh)
diff --git a/cmd/fileTransfer.go b/cmd/fileTransfer.go
index 5122d9d526f958462e5a71f9bcfac24f6a32ec72..e11e320de7c44ae9fb164cb7b1160090df8fc80f 100644
--- a/cmd/fileTransfer.go
+++ b/cmd/fileTransfer.go
@@ -9,7 +9,7 @@ package cmd
 
 import (
 	"fmt"
-	"gitlab.com/elixxir/client/api/messenger"
+	"gitlab.com/elixxir/client/xxdk"
 	"io/ioutil"
 	"time"
 
@@ -132,7 +132,7 @@ type receivedFtResults struct {
 // initFileTransferManager creates a new file transfer manager with a new
 // reception callback. Returns the file transfer manager and the channel that
 // will be triggered when the callback is called.
-func initFileTransferManager(client *messenger.Client, maxThroughput int) (
+func initFileTransferManager(client *xxdk.E2e, maxThroughput int) (
 	*ftE2e.Wrapper, chan receivedFtResults) {
 
 	// Create interfaces.ReceiveCallback that returns the results on a channel
diff --git a/cmd/getndf.go b/cmd/getndf.go
index 7b54755091ee841590d0b0fe1b5daf52c7d503b9..429f2238df30350497c1d0dd178fae7079847761 100644
--- a/cmd/getndf.go
+++ b/cmd/getndf.go
@@ -18,7 +18,7 @@ import (
 	// "gitlab.com/elixxir/client/switchboard"
 	// "gitlab.com/elixxir/client/ud"
 	// "gitlab.com/elixxir/primitives/fact"
-	"gitlab.com/elixxir/client/api"
+	"gitlab.com/elixxir/client/xxdk"
 	"gitlab.com/elixxir/comms/client"
 	"gitlab.com/xx_network/comms/connect"
 	//"time"
@@ -47,23 +47,23 @@ var getNDFCmd = &cobra.Command{
 			var err error
 			switch viper.GetString("env") {
 			case mainnet:
-				ndfJSON, err = api.DownloadAndVerifySignedNdfWithUrl(mainNetUrl, mainNetCert)
+				ndfJSON, err = xxdk.DownloadAndVerifySignedNdfWithUrl(mainNetUrl, mainNetCert)
 				if err != nil {
 					jww.FATAL.Panicf(err.Error())
 				}
 			case release:
-				ndfJSON, err = api.DownloadAndVerifySignedNdfWithUrl(releaseUrl, releaseCert)
+				ndfJSON, err = xxdk.DownloadAndVerifySignedNdfWithUrl(releaseUrl, releaseCert)
 				if err != nil {
 					jww.FATAL.Panicf(err.Error())
 				}
 
 			case dev:
-				ndfJSON, err = api.DownloadAndVerifySignedNdfWithUrl(devUrl, devCert)
+				ndfJSON, err = xxdk.DownloadAndVerifySignedNdfWithUrl(devUrl, devCert)
 				if err != nil {
 					jww.FATAL.Panicf(err.Error())
 				}
 			case testnet:
-				ndfJSON, err = api.DownloadAndVerifySignedNdfWithUrl(testNetUrl, testNetCert)
+				ndfJSON, err = xxdk.DownloadAndVerifySignedNdfWithUrl(testNetUrl, testNetCert)
 				if err != nil {
 					jww.FATAL.Panicf(err.Error())
 				}
@@ -113,7 +113,7 @@ var getNDFCmd = &cobra.Command{
 					},
 					LastUpdate:    uint64(0),
 					ReceptionID:   dummyID[:],
-					ClientVersion: []byte(api.SEMVER),
+					ClientVersion: []byte(xxdk.SEMVER),
 				}
 				resp, err := comms.SendPoll(host, pollMsg)
 				if err != nil {
diff --git a/cmd/group.go b/cmd/group.go
index fce4f5989c733a0fe2b7fa3f72ab625d29797698..8ea7fd73870ec504605674be1f3c2817412abe75 100644
--- a/cmd/group.go
+++ b/cmd/group.go
@@ -12,9 +12,9 @@ package cmd
 import (
 	"bufio"
 	"fmt"
-	"gitlab.com/elixxir/client/api/messenger"
 	"gitlab.com/elixxir/client/cmix/identity/receptionID"
 	"gitlab.com/elixxir/client/cmix/rounds"
+	"gitlab.com/elixxir/client/xxdk"
 	"gitlab.com/elixxir/primitives/format"
 	"os"
 	"time"
@@ -115,7 +115,7 @@ var groupCmd = &cobra.Command{
 
 // initGroupManager creates a new group chat manager and starts the process
 // service.
-func initGroupManager(client *messenger.Client) (groupChat.GroupChat,
+func initGroupManager(client *xxdk.E2e) (groupChat.GroupChat,
 	chan groupChat.MessageReceive, chan groupStore.Group) {
 	recChan := make(chan groupChat.MessageReceive, 10)
 
diff --git a/cmd/init.go b/cmd/init.go
index ad48ca4850e5046c89b6e7b73ea212cad77856d9..6c42b9cfc6a887d5f1dd3aacec85eb36ab47fb9e 100644
--- a/cmd/init.go
+++ b/cmd/init.go
@@ -10,21 +10,21 @@ package cmd
 
 import (
 	"fmt"
+	"gitlab.com/elixxir/client/xxdk"
 
 	"github.com/spf13/cobra"
 	jww "github.com/spf13/jwalterweatherman"
 	"github.com/spf13/viper"
-	"gitlab.com/elixxir/client/api/messenger"
 )
 
 // initCmd creates a new user object with the given NDF
 var initCmd = &cobra.Command{
 	Use:   "init",
-	Short: ("Initialize a user ID but do not connect to the network"),
+	Short: "Initialize a user ID but do not connect to the network",
 	Args:  cobra.NoArgs,
 	Run: func(cmd *cobra.Command, args []string) {
 		client := createClient()
-		e2e, err := messenger.LoadOrInitE2e(client)
+		e2e, err := xxdk.LoadOrInitE2e(client)
 		if err != nil {
 			jww.FATAL.Panicf("%+v", err)
 		}
diff --git a/cmd/precan.go b/cmd/precan.go
index 4a4050efe99237135d5dfb3c9aaf028f3d77974f..64a558ee167f0d3ad9bdb5e1e04326947f510d3d 100644
--- a/cmd/precan.go
+++ b/cmd/precan.go
@@ -11,7 +11,7 @@ package cmd
 
 import (
 	"encoding/binary"
-	"gitlab.com/elixxir/client/api/messenger"
+	"gitlab.com/elixxir/client/xxdk"
 	"strconv"
 
 	jww "github.com/spf13/jwalterweatherman"
@@ -67,7 +67,7 @@ func getPrecanID(recipientID *id.ID) uint {
 	return uint(recipientID.Bytes()[7])
 }
 
-func addPrecanAuthenticatedChannel(client *messenger.Client, recipientID *id.ID,
+func addPrecanAuthenticatedChannel(client *xxdk.E2e, recipientID *id.ID,
 	recipient contact.Contact) {
 	jww.WARN.Printf("Precanned user id detected: %s", recipientID)
 	preUsr, err := client.MakePrecannedAuthenticatedChannel(
diff --git a/cmd/root.go b/cmd/root.go
index 2cb00cb226da464c30039c07cd125e79f37b90b9..f4f26ef17080c2caded6f8ade4a240658658cd14 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -25,9 +25,9 @@ import (
 	"sync"
 	"time"
 
-	"gitlab.com/elixxir/client/api/messenger"
 	"gitlab.com/elixxir/client/backup"
 	"gitlab.com/elixxir/client/e2e"
+	"gitlab.com/elixxir/client/xxdk"
 
 	"gitlab.com/elixxir/client/catalog"
 	"gitlab.com/elixxir/client/cmix"
@@ -36,7 +36,6 @@ import (
 	"github.com/spf13/cobra"
 	jww "github.com/spf13/jwalterweatherman"
 	"github.com/spf13/viper"
-	"gitlab.com/elixxir/client/api"
 	backupCrypto "gitlab.com/elixxir/crypto/backup"
 	"gitlab.com/elixxir/crypto/contact"
 	"gitlab.com/elixxir/primitives/excludedRounds"
@@ -516,7 +515,7 @@ var rootCmd = &cobra.Command{
 	},
 }
 
-func createClient() *api.Client {
+func createClient() *xxdk.Cmix {
 	logLevel := viper.GetUint("logLevel")
 	initLog(logLevel, viper.GetString("log"))
 	jww.INFO.Printf(Version())
@@ -539,17 +538,17 @@ func createClient() *api.Client {
 		}
 
 		if precannedID != 0 {
-			err = api.NewPrecannedClient(precannedID,
+			err = xxdk.NewPrecannedClient(precannedID,
 				string(ndfJSON), storeDir, pass)
 		} else if protoUserPath != "" {
 			protoUserJson, err := utils.ReadFile(protoUserPath)
 			if err != nil {
 				jww.FATAL.Panicf("%v", err)
 			}
-			err = api.NewProtoClient_Unsafe(string(ndfJSON), storeDir,
+			err = xxdk.NewProtoClient_Unsafe(string(ndfJSON), storeDir,
 				pass, protoUserJson)
 		} else if userIDprefix != "" {
-			err = api.NewVanityClient(string(ndfJSON), storeDir,
+			err = xxdk.NewVanityClient(string(ndfJSON), storeDir,
 				pass, regCode, userIDprefix)
 		} else if backupPath != "" {
 
@@ -568,7 +567,7 @@ func createClient() *api.Client {
 			}
 
 			// Construct client from backup data
-			backupIdList, _, err := messenger.NewClientFromBackup(string(ndfJSON), storeDir,
+			backupIdList, _, err := backup.NewClientFromBackup(string(ndfJSON), storeDir,
 				pass, backupPass, backupFile)
 			if err != nil {
 				jww.FATAL.Panicf("%+v", err)
@@ -591,7 +590,7 @@ func createClient() *api.Client {
 			}
 
 		} else {
-			err = api.NewClient(string(ndfJSON), storeDir,
+			err = xxdk.NewClient(string(ndfJSON), storeDir,
 				pass, regCode)
 		}
 
@@ -602,15 +601,15 @@ func createClient() *api.Client {
 
 	params := initParams()
 
-	client, err := api.OpenClient(storeDir, pass, params)
+	client, err := xxdk.OpenCmix(storeDir, pass, params)
 	if err != nil {
 		jww.FATAL.Panicf("%+v", err)
 	}
 	return client
 }
 
-func initParams() api.Params {
-	p := api.GetDefaultParams()
+func initParams() xxdk.Params {
+	p := xxdk.GetDefaultParams()
 	p.Session.MinKeys = uint16(viper.GetUint("e2eMinKeys"))
 	p.Session.MaxKeys = uint16(viper.GetUint("e2eMaxKeys"))
 	p.Session.NumRekeys = uint16(viper.GetUint("e2eNumReKeys"))
@@ -630,7 +629,7 @@ func initParams() api.Params {
 	return p
 }
 
-func initClient() *messenger.Client {
+func initClient() *xxdk.E2e {
 	createClient()
 
 	pass := parsePassword(viper.GetString("password"))
@@ -640,7 +639,7 @@ func initClient() *messenger.Client {
 	params := initParams()
 
 	// load the client
-	baseclient, err := api.Login(storeDir, pass, params)
+	baseclient, err := xxdk.LoadCmix(storeDir, pass, params)
 
 	if err != nil {
 		jww.FATAL.Panicf("%+v", err)
@@ -649,7 +648,7 @@ func initClient() *messenger.Client {
 	authCbs = makeAuthCallbacks(nil,
 		viper.GetBool("unsafe-channel-creation"))
 
-	client, err := messenger.Login(baseclient, authCbs)
+	client, err := xxdk.LoginLegacy(baseclient, authCbs)
 	if err != nil {
 		jww.FATAL.Panicf("%+v", err)
 	}
@@ -716,7 +715,7 @@ func initClient() *messenger.Client {
 	return client
 }
 
-func acceptChannel(client *messenger.Client, recipientID *id.ID) id.Round {
+func acceptChannel(client *xxdk.E2e, recipientID *id.ID) id.Round {
 	recipientContact, err := client.GetAuth().GetReceivedRequest(
 		recipientID)
 	if err != nil {
@@ -731,14 +730,14 @@ func acceptChannel(client *messenger.Client, recipientID *id.ID) id.Round {
 	return rid
 }
 
-func deleteChannel(client *messenger.Client, partnerId *id.ID) {
+func deleteChannel(client *xxdk.E2e, partnerId *id.ID) {
 	err := client.DeleteContact(partnerId)
 	if err != nil {
 		jww.FATAL.Panicf("%+v", err)
 	}
 }
 
-func addAuthenticatedChannel(client *messenger.Client, recipientID *id.ID,
+func addAuthenticatedChannel(client *xxdk.E2e, recipientID *id.ID,
 	recipient contact.Contact) {
 	var allowed bool
 	if viper.GetBool("unsafe-channel-creation") {
@@ -784,7 +783,7 @@ func addAuthenticatedChannel(client *messenger.Client, recipientID *id.ID,
 	}
 }
 
-func resetAuthenticatedChannel(client *messenger.Client, recipientID *id.ID,
+func resetAuthenticatedChannel(client *xxdk.E2e, recipientID *id.ID,
 	recipient contact.Contact) {
 	var allowed bool
 	if viper.GetBool("unsafe-channel-creation") {
@@ -825,7 +824,7 @@ func resetAuthenticatedChannel(client *messenger.Client, recipientID *id.ID,
 	}
 }
 
-func acceptChannelVerified(client *messenger.Client, recipientID *id.ID,
+func acceptChannelVerified(client *xxdk.E2e, recipientID *id.ID,
 	roundTimeout time.Duration) {
 	done := make(chan struct{}, 1)
 	retryChan := make(chan struct{}, 1)
@@ -859,7 +858,7 @@ func acceptChannelVerified(client *messenger.Client, recipientID *id.ID,
 	}
 }
 
-func requestChannelVerified(client *messenger.Client,
+func requestChannelVerified(client *xxdk.E2e,
 	recipientContact, me contact.Contact) {
 	paramsE2E := e2e.GetDefaultParams()
 	roundTimeout := paramsE2E.CMIXParams.SendTimeout
@@ -899,7 +898,7 @@ func requestChannelVerified(client *messenger.Client,
 	}
 }
 
-func resetChannelVerified(client *messenger.Client, recipientContact contact.Contact) {
+func resetChannelVerified(client *xxdk.E2e, recipientContact contact.Contact) {
 	paramsE2E := e2e.GetDefaultParams()
 	roundTimeout := paramsE2E.CMIXParams.SendTimeout
 
@@ -1177,7 +1176,7 @@ func init() {
 	viper.BindPFlag("log", rootCmd.PersistentFlags().Lookup("log"))
 
 	rootCmd.Flags().StringP("regcode", "", "",
-		"Identity code (optional)")
+		"TransmissionIdentity code (optional)")
 	viper.BindPFlag("regcode", rootCmd.Flags().Lookup("regcode"))
 
 	rootCmd.PersistentFlags().StringP("message", "m", "",
diff --git a/cmd/single.go b/cmd/single.go
index 558ad39ebe3700900732d7e10379138acd04a4ab..2ce03e5c35162a909d3c502410ed35bede436c13 100644
--- a/cmd/single.go
+++ b/cmd/single.go
@@ -16,11 +16,11 @@ import (
 	"github.com/spf13/cobra"
 	jww "github.com/spf13/jwalterweatherman"
 	"github.com/spf13/viper"
-	"gitlab.com/elixxir/client/api"
 	"gitlab.com/elixxir/client/cmix"
 	"gitlab.com/elixxir/client/cmix/identity/receptionID"
 	"gitlab.com/elixxir/client/cmix/rounds"
 	"gitlab.com/elixxir/client/single"
+	"gitlab.com/elixxir/client/xxdk"
 	"gitlab.com/elixxir/crypto/contact"
 	"gitlab.com/xx_network/primitives/utils"
 )
@@ -92,7 +92,7 @@ var singleCmd = &cobra.Command{
 			partner := readSingleUseContact("contact")
 			maxMessages := uint8(viper.GetUint("maxMessages"))
 
-			sendSingleUse(client.Client, partner, payload,
+			sendSingleUse(client.Cmix, partner, payload,
 				maxMessages, timeout, tag)
 		}
 
@@ -152,7 +152,7 @@ func (r *Response) Callback(payload []byte, receptionID receptionID.EphemeralIde
 }
 
 // sendSingleUse sends a single use message.
-func sendSingleUse(m *api.Client, partner contact.Contact, payload []byte,
+func sendSingleUse(m *xxdk.Cmix, partner contact.Contact, payload []byte,
 	maxMessages uint8, timeout time.Duration, tag string) {
 	// Construct callback
 	callback := &Response{
diff --git a/cmd/version.go b/cmd/version.go
index f657df9a85100c56590cdbe93873a13f0da75678..41055fef35186085ee0747b89bc17332b13a95df 100644
--- a/cmd/version.go
+++ b/cmd/version.go
@@ -13,7 +13,7 @@ import (
 	"fmt"
 
 	"github.com/spf13/cobra"
-	"gitlab.com/elixxir/client/api"
+	"gitlab.com/elixxir/client/xxdk"
 	"gitlab.com/xx_network/primitives/utils"
 )
 
@@ -21,9 +21,9 @@ import (
 const currentVersion = "4.2.0"
 
 func Version() string {
-	out := fmt.Sprintf("Elixxir Client v%s -- %s\n\n", api.SEMVER,
-		api.GITVERSION)
-	out += fmt.Sprintf("Dependencies:\n\n%s\n", api.DEPENDENCIES)
+	out := fmt.Sprintf("Elixxir Cmix v%s -- %s\n\n", xxdk.SEMVER,
+		xxdk.GITVERSION)
+	out += fmt.Sprintf("Dependencies:\n\n%s\n", xxdk.DEPENDENCIES)
 	return out
 }
 
diff --git a/cmix/client.go b/cmix/client.go
index 15318e5f7cd4cdad302547f09bef96a3d09f8655..92c2d1a1486f1a68c2e2d7672bab34e126cd4a16 100644
--- a/cmix/client.go
+++ b/cmix/client.go
@@ -140,7 +140,7 @@ func (c *client) Connect(ndf *ndf.NetworkDefinition) error {
 	// Set up gateway.Sender
 	poolParams := gateway.DefaultPoolParams()
 
-	// Client will not send KeepAlive packets
+	// Disable KeepAlive packets
 	poolParams.HostParams.KaClientOpts.Time = time.Duration(math.MaxInt64)
 
 	// Enable optimized HostPool initialization
diff --git a/cmix/follow.go b/cmix/follow.go
index 58c693d09d31642af19fd8a8115b35037bce96ae..29eb9035a252a00b3af8cc80a0768b54d8e528b1 100644
--- a/cmix/follow.go
+++ b/cmix/follow.go
@@ -224,7 +224,7 @@ func (c *client) follow(report ClientErrorReport, rng csprng.Source,
 
 			marshaledTid := c.session.GetTransmissionID().Marshal()
 			for _, clientErr := range update.ClientErrors {
-				// If this Client appears in the ClientError
+				// If this ClientId appears in the ClientError
 				if bytes.Equal(clientErr.ClientId, marshaledTid) {
 
 					// Obtain relevant NodeGateway information
diff --git a/cmix/gateway/hostPool.go b/cmix/gateway/hostPool.go
index 52b29d45f1661cb025799d993e401e2dd9108cc3..33bf7e9837fd51a9fa059cd3ddef7ae11158ced1 100644
--- a/cmix/gateway/hostPool.go
+++ b/cmix/gateway/hostPool.go
@@ -66,7 +66,7 @@ type HostManager interface {
 // accepted.
 type Filter func(map[id.ID]int, *ndf.NetworkDefinition) map[id.ID]int
 
-// HostPool Handles providing hosts to the Client
+// HostPool Handles providing hosts to the client
 type HostPool struct {
 	hostMap  map[id.ID]uint32 // Map key to its index in the slice
 	hostList []*connect.Host  // Each index in the slice contains the value
diff --git a/cmix/identity/tracker.go b/cmix/identity/tracker.go
index 18e68d2f7bc34eab98affbf202e88c1a1efef296..7d9b7aaae3cbae55e8a7b5d83ed06b59649807c5 100644
--- a/cmix/identity/tracker.go
+++ b/cmix/identity/tracker.go
@@ -103,21 +103,8 @@ func NewOrLoadTracker(session storage.Session, addrSpace address.Space) *manager
 			})
 		} else {
 			jww.WARN.Printf("No tracked identities found and no legacy " +
-				"stored timestamp found; creating a new tracked identity " +
-				"from scratch.")
-
-			t.tracked = append(t.tracked, TrackedID{
-				// Make the next generation now so a generation triggers on
-				// first run
-				NextGeneration: netTime.Now(),
-				// Start generation 24 hours ago to make sure all resent
-				// ephemeral do pickups
-				// TODO: Should we go back farther?
-				LastGeneration: netTime.Now().Add(-time.Duration(ephemeral.Period)),
-				Source:         t.session.GetReceptionID(),
-				ValidUntil:     Forever,
-				Persistent:     true,
-			})
+				"stored timestamp found; no messages can be picked up until an " +
+				"identity is added.")
 		}
 	} else if err != nil {
 		jww.FATAL.Panicf("Unable to create new Tracker: %+v", err)
diff --git a/cmix/interface.go b/cmix/interface.go
index c03dc1296249a8174916e87f7de2836bd1c7d39f..41e15dd3e981daf718f53f2198d0d708aa525e48 100644
--- a/cmix/interface.go
+++ b/cmix/interface.go
@@ -212,7 +212,7 @@ type Client interface {
 	/* === Nodes ============================================================ */
 	/* Keys must be registered with nodes in order to send messages through
 	   them. This process is, in general, automatically handled by the Network
-	   Client. */
+	   client. */
 
 	// HasNode can be used to determine if a keying relationship exists with a
 	// node.
@@ -229,7 +229,7 @@ type Client interface {
 	/* === Rounds =========================================================== */
 	/* A complete set of round info is not kept on the client, and sometimes
 	   the network will need to be queried to get round info. Historical rounds
-	   is the system internal to the Network Client to do this. It can be used
+	   is the system internal to the Network client to do this. It can be used
 	   externally as well. */
 
 	// GetRoundResults adjudicates on the rounds requested. Checks if they are
diff --git a/cmix/nodes/request.go b/cmix/nodes/request.go
index f41b6b88e2cf476c59f8b00344cfff7101537673..4a99c358427314446ccd557afe9596f15ffd7440 100644
--- a/cmix/nodes/request.go
+++ b/cmix/nodes/request.go
@@ -218,6 +218,6 @@ func processRequestResponse(signedKeyResponse *pb.SignedKeyResponse,
 	// Construct the transmission key from the client key
 	transmissionKey := grp.NewIntFromBytes(clientKey)
 
-	// Use Client keypair to sign Server nonce
+	// Use Cmix keypair to sign Server nonce
 	return transmissionKey, keyResponse.KeyID, keyResponse.ValidUntil, nil
 }
diff --git a/cmix/nodes/utils_test.go b/cmix/nodes/utils_test.go
index 5c97dadf3c77bd1309251a23850d3eb252389c93..5370705a4a72e11638a98b5f54d7aaa15800f9d5 100644
--- a/cmix/nodes/utils_test.go
+++ b/cmix/nodes/utils_test.go
@@ -234,7 +234,7 @@ func (m *MockClientComms) SendRequestClientKeyMessage(_ *connect.Host,
 
 	// Extract RSA pubkey
 	clientRsaPub := clientTransmissionConfirmation.RSAPubKey
-	// Assemble Client public key into rsa.PublicKey
+	// Assemble client public key into rsa.PublicKey
 	userPublicKey, err := rsa.LoadPublicKeyFromPem([]byte(clientRsaPub))
 	if err != nil {
 		m.t.Fatalf("Failed to load public key: %+v", err)
diff --git a/connect/authenticated.go b/connect/authenticated.go
index 518bbc2eb482f12c23005071e4e81f42c47caf38..0638c292c02f7f1fff154013a4bebba6f3e339bb 100644
--- a/connect/authenticated.go
+++ b/connect/authenticated.go
@@ -13,6 +13,7 @@ import (
 	"gitlab.com/elixxir/client/catalog"
 	"gitlab.com/elixxir/client/cmix"
 	clientE2e "gitlab.com/elixxir/client/e2e"
+	"gitlab.com/elixxir/client/xxdk"
 	"gitlab.com/elixxir/crypto/contact"
 	"gitlab.com/elixxir/crypto/cyclic"
 	"gitlab.com/elixxir/crypto/fastRNG"
@@ -51,24 +52,23 @@ type AuthenticatedCallback func(connection AuthenticatedConnection)
 // ConnectWithAuthentication is called by the client, ie the one establishing
 // connection with the server. Once a connect.Connection has been established
 // with the server and then authenticate their identity to the server.
-func ConnectWithAuthentication(recipient contact.Contact, myId *id.ID,
-	salt []byte, myRsaPrivKey *rsa.PrivateKey, myDhPrivKey *cyclic.Int,
-	rng *fastRNG.StreamGenerator, grp *cyclic.Group, net cmix.Client,
+func ConnectWithAuthentication(recipient contact.Contact, e2eClient *xxdk.E2e,
 	p Params) (AuthenticatedConnection, error) {
 
 	// Track the time since we started to attempt to establish a connection
 	timeStart := netTime.Now()
 
 	// Establish a connection with the server
-	conn, err := Connect(recipient, myId, myDhPrivKey, rng, grp, net, p)
+	conn, err := Connect(recipient, e2eClient, p)
 	if err != nil {
 		return nil, errors.Errorf("failed to establish connection "+
 			"with recipient %s: %+v", recipient.ID, err)
 	}
 
 	// Build the authenticated connection and return
-	return connectWithAuthentication(conn, timeStart, recipient, salt, myRsaPrivKey,
-		rng, net, p)
+	identity := e2eClient.GetTransmissionIdentity()
+	return connectWithAuthentication(conn, timeStart, recipient, identity.Salt, identity.RSAPrivatePem,
+		e2eClient.GetRng(), e2eClient.GetCmix(), p)
 }
 
 // connectWithAuthentication builds and sends an IdentityAuthentication to
diff --git a/connect/connect.go b/connect/connect.go
index 0de11c560d74c6e085fe5fc3276cedb69a81490c..6ebb2b7c4893d3cc0891cd43ad73c8e36b3f8498 100644
--- a/connect/connect.go
+++ b/connect/connect.go
@@ -8,6 +8,12 @@ package connect
 
 import (
 	"encoding/json"
+	"gitlab.com/elixxir/client/cmix"
+	"gitlab.com/elixxir/client/storage/versioned"
+	"gitlab.com/elixxir/client/xxdk"
+	"gitlab.com/elixxir/crypto/cyclic"
+	"gitlab.com/elixxir/crypto/fastRNG"
+	"gitlab.com/elixxir/ekv"
 	"io"
 	"time"
 
@@ -15,7 +21,6 @@ import (
 	jww "github.com/spf13/jwalterweatherman"
 	"gitlab.com/elixxir/client/auth"
 	"gitlab.com/elixxir/client/catalog"
-	"gitlab.com/elixxir/client/cmix"
 	"gitlab.com/elixxir/client/cmix/identity/receptionID"
 	"gitlab.com/elixxir/client/cmix/rounds"
 	clientE2e "gitlab.com/elixxir/client/e2e"
@@ -23,12 +28,8 @@ import (
 	"gitlab.com/elixxir/client/e2e/receive"
 	"gitlab.com/elixxir/client/e2e/rekey"
 	"gitlab.com/elixxir/client/event"
-	"gitlab.com/elixxir/client/storage/versioned"
 	"gitlab.com/elixxir/crypto/contact"
-	"gitlab.com/elixxir/crypto/cyclic"
 	"gitlab.com/elixxir/crypto/e2e"
-	"gitlab.com/elixxir/crypto/fastRNG"
-	"gitlab.com/elixxir/ekv"
 	"gitlab.com/xx_network/primitives/id"
 )
 
@@ -118,41 +119,19 @@ func GetParameters(params string) (Params, error) {
 // and returns a Connection object for the newly-created partner.Manager
 // This function is to be used sender-side and will block until the
 // partner.Manager is confirmed.
-func Connect(recipient contact.Contact, myId *id.ID, privKey *cyclic.Int,
-	rng *fastRNG.StreamGenerator, grp *cyclic.Group, net cmix.Client,
+func Connect(recipient contact.Contact, e2eClient *xxdk.E2e,
 	p Params) (Connection, error) {
-	//add the identity
-	net.AddIdentity(myId, time.Time{}, false)
-
-	// Build an ephemeral KV
-	kv := versioned.NewKV(ekv.MakeMemstore())
-
-	// Build E2e handler
-	err := clientE2e.Init(kv, myId, privKey, grp, p.Rekey)
-	if err != nil {
-		return nil, err
-	}
-	e2eHandler, err := clientE2e.Load(kv, net, myId, grp, rng, p.Event)
-	if err != nil {
-		return nil, err
-	}
 
 	// Build callback for E2E negotiation
 	signalChannel := make(chan Connection, 1)
 	cb := func(connection Connection) {
 		signalChannel <- connection
 	}
-	callback := getAuthCallback(cb, nil, e2eHandler, p)
-
-	// Build auth object for E2E negotiation
-	authState, err := auth.NewState(kv, net, e2eHandler,
-		rng, p.Event, p.Auth, callback, nil)
-	if err != nil {
-		return nil, err
-	}
+	callback := getAuthCallback(cb, nil, e2eClient.GetE2E(), e2eClient.GetAuth(), p)
+	e2eClient.GetAuth().AddPartnerCallback(recipient.ID, callback)
 
 	// Perform the auth request
-	_, err = authState.Request(recipient, nil)
+	_, err := e2eClient.GetAuth().Request(recipient, nil)
 	if err != nil {
 		return nil, err
 	}
@@ -199,7 +178,7 @@ func StartServer(cb Callback, myId *id.ID, privKey *cyclic.Int,
 	}
 
 	// Build callback for E2E negotiation
-	callback := getAuthCallback(nil, cb, e2eHandler, p)
+	callback := getAuthCallback(nil, cb, e2eHandler, nil, p)
 
 	// Build auth object for E2E negotiation
 	authState, err := auth.NewState(kv, net, e2eHandler,
@@ -269,7 +248,7 @@ func (h *handler) Unregister(listenerID receive.ListenerID) {
 // building new Connection objects when an auth Request is received.
 type authCallback struct {
 	// Used for signaling confirmation of E2E partnership
-	confrimCallback Callback
+	confirmCallback Callback
 	requestCallback Callback
 
 	// Used for building new Connection objects
@@ -282,12 +261,13 @@ type authCallback struct {
 // of an auth.State object.
 // it will accept requests only if a request callback is passed in
 func getAuthCallback(confirm, request Callback, e2e clientE2e.Handler,
-	params Params) *authCallback {
+	auth auth.State, params Params) *authCallback {
 	return &authCallback{
-		confrimCallback:  confirm,
+		confirmCallback:  confirm,
 		requestCallback:  request,
 		connectionE2e:    e2e,
 		connectionParams: params,
+		authState:        auth,
 	}
 }
 
@@ -296,6 +276,7 @@ func (a authCallback) Confirm(requestor contact.Contact,
 	receptionID receptionID.EphemeralIdentity, round rounds.Round) {
 	jww.DEBUG.Printf("Connection auth request for %s confirmed",
 		requestor.ID.String())
+	defer a.authState.DeletePartnerCallback(requestor.ID)
 
 	// After confirmation, get the new partner
 	newPartner, err := a.connectionE2e.GetPartner(requestor.ID)
@@ -303,26 +284,24 @@ func (a authCallback) Confirm(requestor contact.Contact,
 		jww.ERROR.Printf("Unable to build connection with "+
 			"partner %s: %+v", requestor.ID, err)
 		// Send a nil connection to avoid hold-ups down the line
-		if a.confrimCallback != nil {
-			a.confrimCallback(nil)
+		if a.confirmCallback != nil {
+			a.confirmCallback(nil)
 		}
-
 		return
 	}
 
 	// Return the new Connection object
-	if a.confrimCallback != nil {
-		a.confrimCallback(BuildConnection(newPartner, a.connectionE2e,
+	if a.confirmCallback != nil {
+		a.confirmCallback(BuildConnection(newPartner, a.connectionE2e,
 			a.authState, a.connectionParams))
 	}
-
 }
 
 // Request will be called when an auth Request message is processed.
 func (a authCallback) Request(requestor contact.Contact,
 	receptionID receptionID.EphemeralIdentity, round rounds.Round) {
 	if a.requestCallback == nil {
-		jww.ERROR.Printf("Recieved a request when requests are" +
+		jww.ERROR.Printf("Received a request when requests are" +
 			"not enable, will not accept")
 	}
 	_, err := a.authState.Confirm(requestor)
@@ -371,7 +350,7 @@ func (h *handler) PartitionSize(payloadIndex uint) uint {
 	return h.e2e.PartitionSize(payloadIndex)
 }
 
-// PayloadSize Returns the max payload size for a partitionable E2E
+// PayloadSize Returns the max payload size for a partition-able E2E
 // message
 func (h *handler) PayloadSize() uint {
 	return h.e2e.PayloadSize()
diff --git a/connect/utils_test.go b/connect/utils_test.go
index 2d5bb68cfacf229904ce521590c175c035b0f538..45038764f61017d7caf2403cd629f8c3e821ca39 100644
--- a/connect/utils_test.go
+++ b/connect/utils_test.go
@@ -187,7 +187,7 @@ func (m mockConnection) Unregister(listenerID receive.ListenerID) {
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// Mock cMix Client                                                           //
+// Mock cMix                                                           //
 ////////////////////////////////////////////////////////////////////////////////
 
 type mockCmix struct {
diff --git a/dummy/manager.go b/dummy/manager.go
index b7c94096101b293e5ee5f7b9ca42a4e9f89b4276..28ddd25e69c7e40bd2ee8a31a4b84d16ac9a7f5a 100644
--- a/dummy/manager.go
+++ b/dummy/manager.go
@@ -12,10 +12,10 @@ package dummy
 
 import (
 	"github.com/pkg/errors"
-	"gitlab.com/elixxir/client/api"
 	"gitlab.com/elixxir/client/interfaces"
 	"gitlab.com/elixxir/client/stoppable"
 	"gitlab.com/elixxir/client/storage"
+	"gitlab.com/elixxir/client/xxdk"
 	"gitlab.com/elixxir/crypto/fastRNG"
 	"sync/atomic"
 	"time"
@@ -56,8 +56,8 @@ type Manager struct {
 	// Pauses/Resumes the dummy send thread when triggered
 	statusChan chan bool
 
-	// Client interfaces
-	client *api.Client
+	// Cmix interfaces
+	client *xxdk.Cmix
 	store  *storage.Session
 	net    interfaces.NetworkManager
 	rng    *fastRNG.StreamGenerator
@@ -66,7 +66,7 @@ type Manager struct {
 // NewManager creates a new dummy Manager with the specified average send delta
 // and the range used for generating random durations.
 func NewManager(maxNumMessages int, avgSendDelta, randomRange time.Duration,
-	client *api.Client, manager interfaces.NetworkManager) *Manager {
+	client *xxdk.Cmix, manager interfaces.NetworkManager) *Manager {
 	clientStorage := client.GetStorage()
 	return newManager(maxNumMessages, avgSendDelta, randomRange, client,
 		&clientStorage, manager, client.GetRng())
@@ -75,7 +75,7 @@ func NewManager(maxNumMessages int, avgSendDelta, randomRange time.Duration,
 // newManager builds a new dummy Manager from fields explicitly passed in. This
 // function is a helper function for NewManager to make it easier to test.
 func newManager(maxNumMessages int, avgSendDelta, randomRange time.Duration,
-	client *api.Client, store *storage.Session, net interfaces.NetworkManager,
+	client *xxdk.Cmix, store *storage.Session, net interfaces.NetworkManager,
 	rng *fastRNG.StreamGenerator) *Manager {
 	return &Manager{
 		maxNumMessages: maxNumMessages,
@@ -91,7 +91,7 @@ func newManager(maxNumMessages int, avgSendDelta, randomRange time.Duration,
 }
 
 // StartDummyTraffic starts the process of sending dummy traffic. This function
-// matches the api.Service type.
+// matches the xxdk.Service type.
 func (m *Manager) StartDummyTraffic() (stoppable.Stoppable, error) {
 	stop := stoppable.NewSingle(dummyTrafficStoppableName)
 	go m.sendThread(stop)
diff --git a/e2e/fpGenerator_test.go b/e2e/fpGenerator_test.go
index ada64460a28221276304055f21056b3be92ae3dd..daf82b417700983987618f9c1a1df171ecd1436c 100644
--- a/e2e/fpGenerator_test.go
+++ b/e2e/fpGenerator_test.go
@@ -98,7 +98,7 @@ func (m mockSessionCypher) Decrypt(format.Message) ([]byte, error)   { return ni
 func (m mockSessionCypher) Use()                                     {}
 
 ////////////////////////////////////////////////////////////////////////////////
-// Mock cMix Client                                                           //
+// Mock cMix                                                           //
 ////////////////////////////////////////////////////////////////////////////////
 
 type mockFpgCmix struct {
diff --git a/e2e/utils_test.go b/e2e/utils_test.go
index 0f84f037f132416f8ad0eb75d7faa9414cbde869..36bccbe729f8d9f72b650f960d85a81e110575f2 100644
--- a/e2e/utils_test.go
+++ b/e2e/utils_test.go
@@ -121,7 +121,7 @@ func (m *mockServices) DeleteService(
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// Mock cMix Client                                                           //
+// Mock cMix                                                           //
 ////////////////////////////////////////////////////////////////////////////////
 
 type mockCmixHandler struct {
diff --git a/fileTransfer/manager.go b/fileTransfer/manager.go
index 246923be543a5404ac8b3249559ec370f6b75d73..03701de6adccc62944952c695a3126b7b26ef830 100644
--- a/fileTransfer/manager.go
+++ b/fileTransfer/manager.go
@@ -197,7 +197,7 @@ func NewManager(receiveCB ReceiveCallback, params Params, myID *id.ID,
 	return m, nil
 }
 
-// StartProcesses starts the sending threads. Adheres to the api.Service type.
+// StartProcesses starts the sending threads. Adheres to the xxdk.Service type.
 func (m *manager) StartProcesses() (stoppable.Stoppable, error) {
 	// Register listener to receive new file transfers
 	m.e2e.RegisterListener(
diff --git a/fileTransfer/send.go b/fileTransfer/send.go
index ca66ae68118f6b11f6f433b5ee15658d9ce89432..f605f7ef03aa247384830b2cb57ed81ebe4d621d 100644
--- a/fileTransfer/send.go
+++ b/fileTransfer/send.go
@@ -85,7 +85,7 @@ func (m *manager) sendingThread(cMixParams cmix.CMIXParams, stop *stoppable.Sing
 	}
 }
 
-// sendCmix sends the parts in the packet via Client.SendMany.
+// sendCmix sends the parts in the packet via Cmix.SendMany.
 func (m *manager) sendCmix(packet []store.Part, cMixParams cmix.CMIXParams) {
 	// validParts will contain all parts in the original packet excluding those
 	// that return an error from GetEncryptedPart
diff --git a/fileTransfer/utils_test.go b/fileTransfer/utils_test.go
index d54a1257f57b6c4625eaa2c819202bc8e35d49ff..0fe87093612f4229ebe8f276c82be74f7a212caf 100644
--- a/fileTransfer/utils_test.go
+++ b/fileTransfer/utils_test.go
@@ -80,7 +80,7 @@ func RandStringBytes(n int, prng *rand.Rand) string {
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// Mock cMix Client                                                           //
+// Mock cMix                                                           //
 ////////////////////////////////////////////////////////////////////////////////
 
 type mockCmixHandler struct {
diff --git a/fileTransfer2/connect/utils_test.go b/fileTransfer2/connect/utils_test.go
index 43eaaa09400b2e0d3feeafd96a46a8809011e6cb..bd155a4825642ec6cf629241b10e3a4e1e561523 100644
--- a/fileTransfer2/connect/utils_test.go
+++ b/fileTransfer2/connect/utils_test.go
@@ -32,7 +32,7 @@ import (
 )
 
 ////////////////////////////////////////////////////////////////////////////////
-// Mock cMix Client                                                           //
+// Mock cMix                                                           //
 ////////////////////////////////////////////////////////////////////////////////
 
 type mockCmixHandler struct {
diff --git a/fileTransfer2/e2e/utils_test.go b/fileTransfer2/e2e/utils_test.go
index 30b9edd67c1daccf35854efe661f9a174b5f64f8..b5c57bcc2ed01ba1a8e9d07aa3401569bf23a579 100644
--- a/fileTransfer2/e2e/utils_test.go
+++ b/fileTransfer2/e2e/utils_test.go
@@ -32,7 +32,7 @@ import (
 )
 
 ////////////////////////////////////////////////////////////////////////////////
-// Mock cMix Client                                                           //
+// Mock cMix                                                           //
 ////////////////////////////////////////////////////////////////////////////////
 
 type mockCmixHandler struct {
diff --git a/fileTransfer2/groupChat/utils_test.go b/fileTransfer2/groupChat/utils_test.go
index 0c0b21bffae44be1b49a0c18892e33cc6c18ed8d..087f095dd60b07648840e3c7d38424837be1a8ba 100644
--- a/fileTransfer2/groupChat/utils_test.go
+++ b/fileTransfer2/groupChat/utils_test.go
@@ -29,7 +29,7 @@ import (
 )
 
 ////////////////////////////////////////////////////////////////////////////////
-// Mock cMix Client                                                           //
+// Mock cMix                                                           //
 ////////////////////////////////////////////////////////////////////////////////
 
 type mockCmixHandler struct {
diff --git a/fileTransfer2/interface.go b/fileTransfer2/interface.go
index b8e2f8ba08f66692b6bb45ae3f9afafcd5bca88f..b0fe8d5ac7137e08c72466865a68d1073f792c06 100644
--- a/fileTransfer2/interface.go
+++ b/fileTransfer2/interface.go
@@ -42,7 +42,7 @@ type SendNew func(transferInfo []byte) error
 type FileTransfer interface {
 
 	// StartProcesses starts the sending threads that wait for file transfers to
-	// send. Adheres to the api.Service type.
+	// send. Adheres to the xxdk.Service type.
 	StartProcesses() (stoppable.Stoppable, error)
 
 	// MaxFileNameLen returns the max number of bytes allowed for a file name.
diff --git a/fileTransfer2/manager.go b/fileTransfer2/manager.go
index f2dfd75e4d0fae4a3ea36557d58fbbe9de12eb61..76cd42ffbce8eec07a2b274b1bfa54a4d2703ba8 100644
--- a/fileTransfer2/manager.go
+++ b/fileTransfer2/manager.go
@@ -199,7 +199,7 @@ func NewManager(params Params, myID *id.ID, cmix Cmix, storage Storage,
 	return m, nil
 }
 
-// StartProcesses starts the sending threads. Adheres to the api.Service type.
+// StartProcesses starts the sending threads. Adheres to the xxdk.Service type.
 func (m *manager) StartProcesses() (stoppable.Stoppable, error) {
 	// Construct stoppables
 	multiStop := stoppable.NewMulti(workerPoolStoppable)
diff --git a/fileTransfer2/send.go b/fileTransfer2/send.go
index 5c0d2074a66e56a6f64a63f5db4704ee2c5ea9d0..1d06dcc80ea2815f1434fbeef61f37dfa64f2938 100644
--- a/fileTransfer2/send.go
+++ b/fileTransfer2/send.go
@@ -89,7 +89,7 @@ func (m *manager) sendingThread(stop *stoppable.Single) {
 	}
 }
 
-// sendCmix sends the parts in the packet via Client.SendMany.
+// sendCmix sends the parts in the packet via Cmix.SendMany.
 func (m *manager) sendCmix(packet []store.Part) {
 	// validParts will contain all parts in the original packet excluding those
 	// that return an error from GetEncryptedPart
diff --git a/fileTransfer2/utils_test.go b/fileTransfer2/utils_test.go
index ef5722da07aa7e107c5272c5f998340129dafa20..7f2de0eb05a1bf0086cd2050c7794e02386033c7 100644
--- a/fileTransfer2/utils_test.go
+++ b/fileTransfer2/utils_test.go
@@ -81,7 +81,7 @@ func RandStringBytes(n int, prng *rand.Rand) string {
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// Mock cMix Client                                                           //
+// Mock cMix                                                           //
 ////////////////////////////////////////////////////////////////////////////////
 
 type mockCmixHandler struct {
diff --git a/groupChat/interface.go b/groupChat/interface.go
index e9c71c51b0727167f97a63f05b8ab2a9f3d35d2a..9604b5d8b39726460f374d3531715be7697510f7 100644
--- a/groupChat/interface.go
+++ b/groupChat/interface.go
@@ -50,7 +50,7 @@ type GroupChat interface {
 	// LeaveGroup removes a group from a list of groups the user is a part of.
 	LeaveGroup(groupID *id.ID) error
 
-	// Send sends a message to all GroupChat members using Client.SendManyCMIX.
+	// Send sends a message to all GroupChat members using Cmix.SendManyCMIX.
 	// The send fails if the message is too long. Returns the ID of the round
 	// sent on and the timestamp of the message send.
 	Send(groupID *id.ID, tag string, message []byte) (
diff --git a/groupChat/send.go b/groupChat/send.go
index 9bed53b763ba45278ca9bd3abc37877fb155acd1..71624079ad5d42f1adce834249f8bdc9965edd4b 100644
--- a/groupChat/send.go
+++ b/groupChat/send.go
@@ -43,7 +43,7 @@ const (
 	saltReadLengthErr = "length of generated salt %d != %d required"
 )
 
-// Send sends a message to all group members using Client.SendMany.
+// Send sends a message to all group members using Cmix.SendMany.
 // The send fails if the message is too long.
 func (m *manager) Send(groupID *id.ID, tag string, message []byte) (
 	id.Round, time.Time, group.MessageID, error) {
diff --git a/registration/permissioning.go b/registration/permissioning.go
index 917692eefc0e53c21220665c78494a0d0c7eb3b2..cab953a8472df368a6bc7dd72218a5e49796c2c8 100644
--- a/registration/permissioning.go
+++ b/registration/permissioning.go
@@ -33,7 +33,7 @@ func Init(comms *client.Comms, def *ndf.NetworkDefinition) (*Registration, error
 	//add the registration host to comms
 	hParam := connect.GetDefaultHostParams()
 	hParam.AuthEnabled = false
-	// Client will not send KeepAlive packets
+	// Do not send KeepAlive packets
 	hParam.KaClientOpts.Time = time.Duration(math.MaxInt64)
 	hParam.MaxRetries = 3
 	perm.host, err = comms.AddHost(&id.ClientRegistration, def.Registration.ClientRegistrationAddress,
diff --git a/single/listener_test.go b/single/listener_test.go
index f6f6bed68b4c5f1fe9f1a3e5849e73df2579e0ee..b7125f217866dbbefdd9e57757944a828da6f2ab 100644
--- a/single/listener_test.go
+++ b/single/listener_test.go
@@ -222,7 +222,7 @@ func Test_listener_Stop(t *testing.T) {
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// Mock cMix Client                                                           //
+// Mock cMix                                                           //
 ////////////////////////////////////////////////////////////////////////////////
 
 type mockListenCmixHandler struct {
diff --git a/single/receivedRequest_test.go b/single/receivedRequest_test.go
index d5d8b15fb500270160f657ad82db712094a61e88..fc7f64f4fc398a5ad3407690d40a269410e1d8c0 100644
--- a/single/receivedRequest_test.go
+++ b/single/receivedRequest_test.go
@@ -154,7 +154,7 @@ func Test_splitPayload(t *testing.T) {
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// Mock cMix Client                                                           //
+// Mock cMix                                                           //
 ////////////////////////////////////////////////////////////////////////////////
 
 type mockRequestCmix struct {
diff --git a/single/utils_test.go b/single/utils_test.go
index 473bb2dfa4025c02cee6bbca4d25e7e7506da3ef..66e7f0e6d670bfc0e19e8ef237d4e2277abb43ec 100644
--- a/single/utils_test.go
+++ b/single/utils_test.go
@@ -23,7 +23,7 @@ import (
 )
 
 ////////////////////////////////////////////////////////////////////////////////
-// Mock cMix Client                                                           //
+// Mock cMix                                                           //
 ////////////////////////////////////////////////////////////////////////////////
 
 // Tests that mockCmix adheres to the Cmix interface.
diff --git a/storage/user/info.go b/storage/user/info.go
index 11d9381ef07cbad22a91dc49db8cff48d551fed8..62603c2225f0921f54684299f140fb33bfb6d182 100644
--- a/storage/user/info.go
+++ b/storage/user/info.go
@@ -105,7 +105,7 @@ func (u *User) PortableUserInfo() Info {
 		ReceptionRSA:          ci.GetReceptionRSA(),
 		Precanned:             ci.IsPrecanned(),
 		//fixme: set these in the e2e layer, the command line layer
-		//needs more logical seperation so this can be removed
+		//needs more logical separation so this can be removed
 		E2eDhPrivateKey: nil,
 		E2eDhPublicKey:  nil,
 	}
diff --git a/ud/interfaces.go b/ud/interfaces.go
index ba5bff8b7eb20cd55da1a1f9c7cf91d3478d8df1..db7f0b60333ddbc559520aa5ee9a12eb51594eea 100644
--- a/ud/interfaces.go
+++ b/ud/interfaces.go
@@ -1,9 +1,9 @@
 package ud
 
 import (
-	"gitlab.com/elixxir/client/api"
 	"gitlab.com/elixxir/client/single"
 	"gitlab.com/elixxir/client/storage/user"
+	"gitlab.com/elixxir/client/xxdk"
 	"gitlab.com/elixxir/crypto/cyclic"
 	"gitlab.com/xx_network/primitives/id"
 )
@@ -37,6 +37,6 @@ type UserInfo interface {
 	GetReceptionRegistrationValidationSignature() []byte
 }
 
-// NetworkStatus is an interface for the api.Client's
+// NetworkStatus is an interface for the xxdk.Cmix's
 // NetworkFollowerStatus method.
-type NetworkStatus func() api.Status
+type NetworkStatus func() xxdk.Status
diff --git a/ud/manager.go b/ud/manager.go
index 3cd1b679a3586248c14f8608eb31cddb2e1f43e7..1ce22eac8d6c24812c381fdc60753e07ba5e5e66 100644
--- a/ud/manager.go
+++ b/ud/manager.go
@@ -7,10 +7,10 @@ import (
 
 	"github.com/pkg/errors"
 	jww "github.com/spf13/jwalterweatherman"
-	"gitlab.com/elixxir/client/api"
 	"gitlab.com/elixxir/client/event"
 	"gitlab.com/elixxir/client/storage/versioned"
 	store "gitlab.com/elixxir/client/ud/store"
+	"gitlab.com/elixxir/client/xxdk"
 	"gitlab.com/elixxir/crypto/contact"
 	"gitlab.com/elixxir/primitives/fact"
 	"gitlab.com/xx_network/comms/connect"
@@ -77,7 +77,7 @@ func NewManager(services CMix, e2e E2E,
 	kv *versioned.KV) (*Manager, error) {
 	jww.INFO.Println("ud.NewManager()")
 
-	if follower() != api.Running {
+	if follower() != xxdk.Running {
 		return nil, errors.New(
 			"cannot start UD Manager when network follower is not running.")
 	}
@@ -134,7 +134,7 @@ func NewManagerFromBackup(services CMix,
 	events event.Reporter, comms Comms, userStore UserInfo,
 	email, phone fact.Fact, kv *versioned.KV) (*Manager, error) {
 	jww.INFO.Println("ud.NewManagerFromBackup()")
-	if follower() != api.Running {
+	if follower() != xxdk.Running {
 		return nil, errors.New(
 			"cannot start UD Manager when " +
 				"network follower is not running.")
diff --git a/api/messenger/backup.go b/xxdk/backup.go
similarity index 80%
rename from api/messenger/backup.go
rename to xxdk/backup.go
index a5e73eaaf743030acacea195229e13e409f091e8..6b02e9ad5635a3984c485487a6c714eacc003f62 100644
--- a/api/messenger/backup.go
+++ b/xxdk/backup.go
@@ -1,11 +1,10 @@
 ////////////////////////////////////////////////////////////////////////////////
-// Copyright © 2020 xx network SEZC                                           //
-//                                                                            //
-// Use of this source code is governed by a license that can be found in the  //
-// LICENSE file                                                               //
+// Copyright © 2022 Privategrity Corporation                                   /
+//                                                                             /
+// All rights reserved.                                                        /
 ////////////////////////////////////////////////////////////////////////////////
 
-package messenger
+package xxdk
 
 import "sync"
 
diff --git a/api/client.go b/xxdk/cmix.go
similarity index 89%
rename from api/client.go
rename to xxdk/cmix.go
index 002542157ea6a8e49924aa0d44e4419566d1d450..6b5444bef2b5d2fad83e5bbe7cdad4b835dbb3d0 100644
--- a/api/client.go
+++ b/xxdk/cmix.go
@@ -5,7 +5,7 @@
 // LICENSE file                                                              //
 ///////////////////////////////////////////////////////////////////////////////
 
-package api
+package xxdk
 
 import (
 	"encoding/json"
@@ -16,7 +16,6 @@ import (
 
 	"github.com/pkg/errors"
 	jww "github.com/spf13/jwalterweatherman"
-	"gitlab.com/elixxir/client/auth"
 	"gitlab.com/elixxir/client/cmix"
 	"gitlab.com/elixxir/client/event"
 	"gitlab.com/elixxir/client/interfaces"
@@ -39,7 +38,7 @@ import (
 
 const followerStoppableName = "client"
 
-type Client struct {
+type Cmix struct {
 	//generic RNG for client
 	rng *fastRNG.StreamGenerator
 	// the storage session securely stores data to disk and memoizes as is
@@ -120,10 +119,10 @@ func NewVanityClient(ndfJSON, storageDir string, password []byte,
 	return nil
 }
 
-// OpenClient session, but don't connect to the network or log in
-func OpenClient(storageDir string, password []byte,
-	parameters Params) (*Client, error) {
-	jww.INFO.Printf("OpenClient()")
+// OpenCmix session, but don't connect to the network or log in
+func OpenCmix(storageDir string, password []byte,
+	parameters Params) (*Cmix, error) {
+	jww.INFO.Printf("OpenCmix()")
 
 	rngStreamGen := fastRNG.NewStreamGenerator(12, 1024,
 		csprng.NewSystemRNG)
@@ -141,7 +140,7 @@ func OpenClient(storageDir string, password []byte,
 		return nil, err
 	}
 
-	c := &Client{
+	c := &Cmix{
 		storage:            storageSess,
 		rng:                rngStreamGen,
 		comms:              nil,
@@ -210,16 +209,16 @@ func NewProtoClient_Unsafe(ndfJSON, storageDir string, password,
 	return nil
 }
 
-// Login initializes a client object from existing storage.
-func Login(storageDir string, password []byte, parameters Params) (*Client, error) {
+// LoadCmix initializes a Cmix object from existing storage
+func LoadCmix(storageDir string, password []byte, parameters Params) (*Cmix, error) {
 	jww.INFO.Printf("Login()")
 
-	c, err := OpenClient(storageDir, password, parameters)
+	c, err := OpenCmix(storageDir, password, parameters)
 	if err != nil {
 		return nil, err
 	}
 
-	jww.INFO.Printf("Client Logged in: \n\tTransmissionID: %s "+
+	jww.INFO.Printf("Cmix Logged in: \n\tTransmissionID: %s "+
 		"\n\tReceptionID: %s", c.storage.GetTransmissionID(), c.storage.GetReceptionID())
 
 	def := c.storage.GetNDF()
@@ -232,13 +231,13 @@ func Login(storageDir string, password []byte, parameters Params) (*Client, erro
 		}
 	} else {
 		jww.WARN.Printf("Registration with permissioning skipped due " +
-			"to blank permissioning address. Client will not be " +
+			"to blank permissioning address. Cmix will not be " +
 			"able to register or track network.")
 	}
 
 	if def.Notification.Address != "" {
 		hp := connect.GetDefaultHostParams()
-		// Client will not send KeepAlive packets
+		// Do not send KeepAlive packets
 		hp.KaClientOpts.Time = time.Duration(math.MaxInt64)
 		hp.AuthEnabled = false
 		hp.MaxRetries = 5
@@ -268,8 +267,7 @@ func Login(storageDir string, password []byte, parameters Params) (*Client, erro
 // while replacing the base NDF.  This is designed for some specific deployment
 // procedures and is generally unsafe.
 func LoginWithNewBaseNDF_UNSAFE(storageDir string, password []byte,
-	newBaseNdf string, authCallbacks auth.Callbacks,
-	params Params) (*Client, error) {
+	newBaseNdf string, params Params) (*Cmix, error) {
 	jww.INFO.Printf("LoginWithNewBaseNDF_UNSAFE()")
 
 	def, err := ParseNDF(newBaseNdf)
@@ -277,7 +275,7 @@ func LoginWithNewBaseNDF_UNSAFE(storageDir string, password []byte,
 		return nil, err
 	}
 
-	c, err := OpenClient(storageDir, password, params)
+	c, err := OpenCmix(storageDir, password, params)
 	if err != nil {
 		return nil, err
 	}
@@ -292,7 +290,7 @@ func LoginWithNewBaseNDF_UNSAFE(storageDir string, password []byte,
 		}
 	} else {
 		jww.WARN.Printf("Registration with permissioning skipped due " +
-			"to blank permissionign address. Client will not be " +
+			"to blank permissionign address. Cmix will not be " +
 			"able to register or track network.")
 	}
 
@@ -314,7 +312,7 @@ func LoginWithNewBaseNDF_UNSAFE(storageDir string, password []byte,
 // some specific deployment procedures and is generally unsafe.
 func LoginWithProtoClient(storageDir string, password []byte,
 	protoClientJSON []byte, newBaseNdf string,
-	params Params) (*Client, error) {
+	params Params) (*Cmix, error) {
 	jww.INFO.Printf("LoginWithProtoClient()")
 
 	def, err := ParseNDF(newBaseNdf)
@@ -328,7 +326,7 @@ func LoginWithProtoClient(storageDir string, password []byte,
 		return nil, err
 	}
 
-	c, err := OpenClient(storageDir, password, params)
+	c, err := OpenCmix(storageDir, password, params)
 	if err != nil {
 		return nil, err
 	}
@@ -359,7 +357,7 @@ func LoginWithProtoClient(storageDir string, password []byte,
 	return c, nil
 }
 
-func (c *Client) initComms() error {
+func (c *Cmix) initComms() error {
 	var err error
 
 	//get the user from session
@@ -376,7 +374,7 @@ func (c *Client) initComms() error {
 	return nil
 }
 
-func (c *Client) initPermissioning(def *ndf.NetworkDefinition) error {
+func (c *Cmix) initPermissioning(def *ndf.NetworkDefinition) error {
 	var err error
 	//initialize registration
 	c.permissioning, err = registration.Init(c.comms, def)
@@ -387,15 +385,15 @@ func (c *Client) initPermissioning(def *ndf.NetworkDefinition) error {
 
 	//register with registration if necessary
 	if c.storage.GetRegistrationStatus() == storage.KeyGenComplete {
-		jww.INFO.Printf("Client has not registered yet, " +
+		jww.INFO.Printf("Cmix has not registered yet, " +
 			"attempting registration")
 		err = c.registerWithPermissioning()
 		if err != nil {
-			jww.ERROR.Printf("Client has failed registration: %s",
+			jww.ERROR.Printf("Cmix has failed registration: %s",
 				err)
 			return errors.WithMessage(err, "failed to load client")
 		}
-		jww.INFO.Printf("Client successfully registered " +
+		jww.INFO.Printf("Cmix successfully registered " +
 			"with the network")
 	}
 	return nil
@@ -404,7 +402,7 @@ func (c *Client) initPermissioning(def *ndf.NetworkDefinition) error {
 // registerFollower adds the follower processes to the client's
 // follower service list.
 // This should only ever be called once
-func (c *Client) registerFollower() error {
+func (c *Cmix) registerFollower() error {
 	//build the error callback
 	cer := func(source, message, trace string) {
 		select {
@@ -436,12 +434,12 @@ func (c *Client) registerFollower() error {
 	return nil
 }
 
-// ----- Client Functions -----
+// ----- Cmix Functions -----
 
 // GetErrorsChannel returns a channel which passes errors from the
 // long-running threads controlled by StartNetworkFollower and
 // StopNetworkFollower
-func (c *Client) GetErrorsChannel() <-chan interfaces.ClientError {
+func (c *Cmix) GetErrorsChannel() <-chan interfaces.ClientError {
 	return c.clientErrorChannel
 }
 
@@ -479,7 +477,7 @@ func (c *Client) GetErrorsChannel() <-chan interfaces.ClientError {
 //		Responds to confirmations of successful rekey operations
 //   - Auth Callback (/auth/callback.go)
 //      Handles both auth confirm and requests
-func (c *Client) StartNetworkFollower(timeout time.Duration) error {
+func (c *Cmix) StartNetworkFollower(timeout time.Duration) error {
 	jww.INFO.Printf("StartNetworkFollower() \n\tTransmissionID: %s "+
 		"\n\tReceptionID: %s", c.storage.GetTransmissionID(), c.storage.GetReceptionID())
 
@@ -491,7 +489,7 @@ func (c *Client) StartNetworkFollower(timeout time.Duration) error {
 // fails to stop it.
 // if the network follower is running and this fails, the client object will
 // most likely be in an unrecoverable state and need to be trashed.
-func (c *Client) StopNetworkFollower() error {
+func (c *Cmix) StopNetworkFollower() error {
 	jww.INFO.Printf("StopNetworkFollower()")
 	return c.followerServices.stop()
 }
@@ -501,62 +499,62 @@ func (c *Client) StopNetworkFollower() error {
 // Starting - 1000
 // Running	- 2000
 // Stopping	- 3000
-func (c *Client) NetworkFollowerStatus() Status {
+func (c *Cmix) NetworkFollowerStatus() Status {
 	jww.INFO.Printf("NetworkFollowerStatus()")
 	return c.followerServices.status()
 }
 
 // HasRunningProcessies checks if any background threads are running
 // and returns true if one or more are
-func (c *Client) HasRunningProcessies() bool {
+func (c *Cmix) HasRunningProcessies() bool {
 	return !c.followerServices.stoppable.IsStopped()
 }
 
 // RegisterRoundEventsCb registers a callback for round
 // events.
-func (c *Client) GetRoundEvents() interfaces.RoundEvents {
+func (c *Cmix) GetRoundEvents() interfaces.RoundEvents {
 	jww.INFO.Printf("GetRoundEvents()")
-	jww.WARN.Printf("GetRoundEvents does not handle Client Errors " +
+	jww.WARN.Printf("GetRoundEvents does not handle Cmix Errors " +
 		"edge case!")
 	return c.network.GetInstance().GetRoundEvents()
 }
 
 // AddService adds a service ot be controlled by the client thread control,
 // these will be started and stopped with the network follower
-func (c *Client) AddService(sp Service) error {
+func (c *Cmix) AddService(sp Service) error {
 	return c.followerServices.add(sp)
 }
 
 // GetUser returns the current user Identity for this client. This
 // can be serialized into a byte stream for out-of-band sharing.
-func (c *Client) GetUser() user.Info {
+func (c *Cmix) GetUser() user.Info {
 	jww.INFO.Printf("GetUser()")
 	cMixUser := c.storage.PortableUserInfo()
 	return cMixUser
 }
 
 // GetComms returns the client comms object
-func (c *Client) GetComms() *client.Comms {
+func (c *Cmix) GetComms() *client.Comms {
 	return c.comms
 }
 
 // GetRng returns the client rng object
-func (c *Client) GetRng() *fastRNG.StreamGenerator {
+func (c *Cmix) GetRng() *fastRNG.StreamGenerator {
 	return c.rng
 }
 
 // GetStorage returns the client storage object
-func (c *Client) GetStorage() storage.Session {
+func (c *Cmix) GetStorage() storage.Session {
 	return c.storage
 }
 
 // GetCmix returns the client Network Interface
-func (c *Client) GetCmix() cmix.Client {
+func (c *Cmix) GetCmix() cmix.Client {
 	return c.network
 }
 
 // GetEventReporter returns the event reporter
-func (c *Client) GetEventReporter() event.Reporter {
+func (c *Cmix) GetEventReporter() event.Reporter {
 	return c.events
 }
 
@@ -564,7 +562,7 @@ func (c *Client) GetEventReporter() event.Reporter {
 // returns the total number of nodes in the NDF and the number of those which
 // are currently registers with. An error is returned if the network is not
 // healthy.
-func (c *Client) GetNodeRegistrationStatus() (int, int, error) {
+func (c *Cmix) GetNodeRegistrationStatus() (int, int, error) {
 	// Return an error if the network is not healthy
 	if !c.GetCmix().IsHealthy() {
 		return 0, 0, errors.New("Cannot get number of nodes " +
@@ -596,7 +594,7 @@ func (c *Client) GetNodeRegistrationStatus() (int, int, error) {
 
 // GetPreferredBins returns the geographic bin or bins that the provided two
 // character country code is a part of.
-func (c *Client) GetPreferredBins(countryCode string) ([]string, error) {
+func (c *Cmix) GetPreferredBins(countryCode string) ([]string, error) {
 	// get the bin that the country is in
 	bin, exists := region.GetCountryBin(countryCode)
 	if !exists {
diff --git a/api/messenger/compress_test.go b/xxdk/compress_test.go
similarity index 99%
rename from api/messenger/compress_test.go
rename to xxdk/compress_test.go
index 19a4bcc414c112b9168b5da43b80f8e3d78721bf..75d020eebdd4efb15be25326c248e4f6b17834da 100644
--- a/api/messenger/compress_test.go
+++ b/xxdk/compress_test.go
@@ -1,11 +1,10 @@
-///////////////////////////////////////////////////////////////////////////////
-// Copyright © 2020 xx network SEZC                                          //
-//                                                                           //
-// Use of this source code is governed by a license that can be found in the //
-// LICENSE file                                                              //
-///////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+// Copyright © 2022 Privategrity Corporation                                   /
+//                                                                             /
+// All rights reserved.                                                        /
+////////////////////////////////////////////////////////////////////////////////
 
-package messenger
+package xxdk
 
 import (
 	"bytes"
diff --git a/api/messenger/messenger.go b/xxdk/e2e.go
similarity index 53%
rename from api/messenger/messenger.go
rename to xxdk/e2e.go
index 2677e6fbaf23270e7eb6fc6009266da1638eaade..c3536ec8eb316f61bfc49643ab903ee393b1a99b 100644
--- a/api/messenger/messenger.go
+++ b/xxdk/e2e.go
@@ -1,12 +1,21 @@
-package messenger
+////////////////////////////////////////////////////////////////////////////////
+// Copyright © 2022 Privategrity Corporation                                   /
+//                                                                             /
+// All rights reserved.                                                        /
+////////////////////////////////////////////////////////////////////////////////
+
+package xxdk
 
 import (
 	"encoding/binary"
 	"encoding/json"
+	"gitlab.com/elixxir/client/storage/versioned"
+	"gitlab.com/elixxir/ekv"
+	"gitlab.com/xx_network/crypto/xx"
+	"time"
 
 	"github.com/pkg/errors"
 	jww "github.com/spf13/jwalterweatherman"
-	"gitlab.com/elixxir/client/api"
 	"gitlab.com/elixxir/client/auth"
 	"gitlab.com/elixxir/client/e2e"
 	"gitlab.com/elixxir/client/e2e/rekey"
@@ -16,16 +25,37 @@ import (
 	"gitlab.com/xx_network/primitives/id"
 )
 
-type Client struct {
-	*api.Client
-	auth   auth.State
-	e2e    e2e.Handler
-	backup *Container
+// E2e object bundles a TransmissionIdentity with a Cmix
+// and can be used for high level operations such as connections
+type E2e struct {
+	*Cmix
+	auth        auth.State
+	e2e         e2e.Handler
+	backup      *Container
+	e2eIdentity TransmissionIdentity
+}
+
+// Login creates a new E2e backed by the xxdk.Cmix persistent versioned.KV
+// If identity == nil, a new TransmissionIdentity will be generated automagically
+func Login(client *Cmix, callbacks auth.Callbacks,
+	identity TransmissionIdentity) (m *E2e, err error) {
+	return login(client, callbacks, identity, client.GetStorage().GetKV())
+}
+
+// LoginEphemeral creates a new E2e backed by a totally ephemeral versioned.KV
+// If identity == nil, a new TransmissionIdentity will be generated automagically
+func LoginEphemeral(client *Cmix, callbacks auth.Callbacks,
+	identity TransmissionIdentity) (m *E2e, err error) {
+	return login(client, callbacks, identity, versioned.NewKV(ekv.MakeMemstore()))
 }
 
-func Login(client *api.Client, callbacks auth.Callbacks) (m *Client, err error) {
-	m = &Client{
-		Client: client,
+// LoginLegacy creates a new E2e backed by the xxdk.Cmix persistent versioned.KV
+// Uses the pre-generated transmission ID used by xxdk.Cmix
+// This function is designed to maintain backwards compatibility with previous xx messenger designs
+// and should not be used for other purposes
+func LoginLegacy(client *Cmix, callbacks auth.Callbacks) (m *E2e, err error) {
+	m = &E2e{
+		Cmix:   client,
 		backup: &Container{},
 	}
 
@@ -41,18 +71,73 @@ func Login(client *api.Client, callbacks auth.Callbacks) (m *Client, err error)
 		return nil, err
 	}
 
+	u := m.Cmix.GetUser()
+	m.e2eIdentity = TransmissionIdentity{
+		ID:            u.TransmissionID,
+		RSAPrivatePem: u.TransmissionRSA,
+		Salt:          u.TransmissionSalt,
+		DHKeyPrivate:  u.E2eDhPrivateKey,
+	}
+
+	return m, err
+}
+
+// login creates a new e2eApi.E2e backed by the given versioned.KV
+func login(client *Cmix, callbacks auth.Callbacks,
+	identity TransmissionIdentity, kv *versioned.KV) (m *E2e, err error) {
+
+	// Verify the passed-in TransmissionIdentity matches its properties
+	generatedId, err := xx.NewID(identity.RSAPrivatePem.GetPublic(), identity.Salt, id.User)
+	if err != nil {
+		return nil, err
+	}
+	if !generatedId.Cmp(identity.ID) {
+		return nil, errors.Errorf("Given identity %s is invalid, generated ID does not match",
+			identity.ID.String())
+	}
+
+	e2eGrp := client.GetStorage().GetE2EGroup()
+	m = &E2e{
+		Cmix:        client,
+		backup:      &Container{},
+		e2eIdentity: identity,
+	}
+
+	//initialize the e2e storage
+	err = e2e.Init(kv, identity.ID, identity.DHKeyPrivate, e2eGrp,
+		rekey.GetDefaultEphemeralParams())
+	if err != nil {
+		return nil, err
+	}
+
+	//load the new e2e storage
+	m.e2e, err = e2e.Load(kv,
+		client.GetCmix(), identity.ID, e2eGrp, client.GetRng(),
+		client.GetEventReporter())
+	if err != nil {
+		return nil, errors.WithMessage(err, "Failed to load a "+
+			"newly created e2e store")
+	}
+
+	m.auth, err = auth.NewState(kv, client.GetCmix(),
+		m.e2e, client.GetRng(), client.GetEventReporter(),
+		auth.GetDefaultTemporaryParams(), callbacks, m.backup.TriggerBackup)
+	if err != nil {
+		return nil, err
+	}
+
 	return m, err
 }
 
 // LoadOrInitE2e loads the e2e handler or makes a new one, generating a new
 // e2e private key. It attempts to load via a legacy construction, then tries
 // to load the modern one, creating a new modern ID if neither can be found
-func LoadOrInitE2e(client *api.Client) (e2e.Handler, error) {
+func LoadOrInitE2e(client *Cmix) (e2e.Handler, error) {
 	usr := client.GetUser()
 	e2eGrp := client.GetStorage().GetE2EGroup()
 	kv := client.GetStorage().GetKV()
 
-	//try to load a legacy e2e hander
+	//try to load a legacy e2e handler
 	e2eHandler, err := e2e.LoadLegacy(kv,
 		client.GetCmix(), usr.ReceptionID, e2eGrp, client.GetRng(),
 		client.GetEventReporter(), rekey.GetDefaultParams())
@@ -61,7 +146,7 @@ func LoadOrInitE2e(client *api.Client) (e2e.Handler, error) {
 		e2eHandler, err = e2e.Load(kv,
 			client.GetCmix(), usr.ReceptionID, e2eGrp, client.GetRng(),
 			client.GetEventReporter())
-		//if no new e2e handler exists, initilize an e2e user
+		//if no new e2e handler exists, initialize an e2e user
 		if err != nil {
 			jww.WARN.Printf("Failed to load e2e instance for %s, "+
 				"creating a new one", usr.ReceptionID)
@@ -102,6 +187,8 @@ func LoadOrInitE2e(client *api.Client) (e2e.Handler, error) {
 				return nil, errors.WithMessage(err, "Failed to load a "+
 					"newly created e2e store")
 			}
+
+			client.GetCmix().AddIdentity(usr.ReceptionID, time.Time{}, true)
 		} else {
 			jww.INFO.Printf("Loaded a modern e2e instance for %s",
 				usr.ReceptionID)
@@ -113,18 +200,23 @@ func LoadOrInitE2e(client *api.Client) (e2e.Handler, error) {
 	return e2eHandler, nil
 }
 
-// GetUser replaces api.Client's GetUser with one which includes the e2e dh
+// GetUser replaces xxdk.Cmix's GetUser with one which includes the e2e dh
 // private keys
-func (m *Client) GetUser() user.Info {
-	u := m.Client.GetUser()
+func (m *E2e) GetUser() user.Info {
+	u := m.Cmix.GetUser()
 	u.E2eDhPrivateKey = m.e2e.GetHistoricalDHPrivkey()
 	u.E2eDhPublicKey = m.e2e.GetHistoricalDHPubkey()
 	return u
 }
 
+// GetTransmissionIdentity returns a safe copy of the E2e TransmissionIdentity
+func (m *E2e) GetTransmissionIdentity() TransmissionIdentity {
+	return m.e2eIdentity.DeepCopy()
+}
+
 // ConstructProtoUserFile is a helper function which is used for proto
 // client testing.  This is used for development testing.
-func (m *Client) ConstructProtoUserFile() ([]byte, error) {
+func (m *E2e) ConstructProtoUserFile() ([]byte, error) {
 
 	//load the registration code
 	regCode, err := m.GetStorage().GetRegCode()
@@ -158,20 +250,20 @@ func (m *Client) ConstructProtoUserFile() ([]byte, error) {
 	return jsonBytes, nil
 }
 
-func (m *Client) GetAuth() auth.State {
+func (m *E2e) GetAuth() auth.State {
 	return m.auth
 }
 
-func (m *Client) GetE2E() e2e.Handler {
+func (m *E2e) GetE2E() e2e.Handler {
 	return m.e2e
 }
 
-func (m *Client) GetBackupContainer() *Container {
+func (m *E2e) GetBackupContainer() *Container {
 	return m.backup
 }
 
-// DeleteContact is a function which removes a partner from Client's storage
-func (m *Client) DeleteContact(partnerId *id.ID) error {
+// DeleteContact is a function which removes a partner from E2e's storage
+func (m *E2e) DeleteContact(partnerId *id.ID) error {
 	jww.DEBUG.Printf("Deleting contact with ID %s", partnerId)
 
 	_, err := m.e2e.GetPartner(partnerId)
@@ -190,7 +282,7 @@ func (m *Client) DeleteContact(partnerId *id.ID) error {
 	// c.e2e.Conversations().Delete(partnerId)
 
 	// call delete requests to make sure nothing is lingering.
-	// this is for saftey to ensure the contact can be readded
+	// this is for safety to ensure the contact can be re-added
 	// in the future
 	_ = m.auth.DeleteRequest(partnerId)
 
diff --git a/api/event.go b/xxdk/event.go
similarity index 76%
rename from api/event.go
rename to xxdk/event.go
index 52fa3c1708dce3a5cd074d1a4030859219be7760..cd1897454b70731c4371de68804d5de154aff40d 100644
--- a/api/event.go
+++ b/xxdk/event.go
@@ -1,4 +1,4 @@
-package api
+package xxdk
 
 import (
 	"gitlab.com/elixxir/client/event"
@@ -6,20 +6,20 @@ import (
 
 // ReportEvent reports an event from the client to api users, providing a
 // priority, category, eventType, and details
-func (c *Client) ReportEvent(priority int, category, evtType, details string) {
+func (c *Cmix) ReportEvent(priority int, category, evtType, details string) {
 	c.events.Report(priority, category, evtType, details)
 }
 
 // RegisterEventCallback records the given function to receive
 // ReportableEvent objects. It returns the internal index
 // of the callback so that it can be deleted later.
-func (c *Client) RegisterEventCallback(name string,
+func (c *Cmix) RegisterEventCallback(name string,
 	myFunc event.Callback) error {
 	return c.events.RegisterEventCallback(name, myFunc)
 }
 
 // UnregisterEventCallback deletes the callback identified by the
 // index. It returns an error if it fails.
-func (c *Client) UnregisterEventCallback(name string) {
+func (c *Cmix) UnregisterEventCallback(name string) {
 	c.events.UnregisterEventCallback(name)
 }
diff --git a/xxdk/identity.go b/xxdk/identity.go
new file mode 100644
index 0000000000000000000000000000000000000000..daef4c673bbf1668ae1a11dc294adfeaaa945e1c
--- /dev/null
+++ b/xxdk/identity.go
@@ -0,0 +1,71 @@
+////////////////////////////////////////////////////////////////////////////////
+// Copyright © 2022 Privategrity Corporation                                   /
+//                                                                             /
+// All rights reserved.                                                        /
+////////////////////////////////////////////////////////////////////////////////
+
+package xxdk
+
+import (
+	"gitlab.com/elixxir/crypto/cyclic"
+	"gitlab.com/elixxir/crypto/diffieHellman"
+	"gitlab.com/xx_network/crypto/csprng"
+	"gitlab.com/xx_network/crypto/signature/rsa"
+	"gitlab.com/xx_network/crypto/xx"
+	"gitlab.com/xx_network/primitives/id"
+)
+
+type TransmissionIdentity struct {
+	ID            *id.ID
+	RSAPrivatePem *rsa.PrivateKey
+	Salt          []byte
+	DHKeyPrivate  *cyclic.Int
+}
+
+// MakeTransmissionIdentity generates a new cryptographic identity for receiving messages
+func MakeTransmissionIdentity(rng csprng.Source, grp *cyclic.Group) (TransmissionIdentity, error) {
+	//make RSA Key
+	rsaKey, err := rsa.GenerateKey(rng,
+		rsa.DefaultRSABitLen)
+	if err != nil {
+		return TransmissionIdentity{}, err
+	}
+
+	//make salt
+	salt := make([]byte, 32)
+	_, err = rng.Read(salt)
+
+	//make dh private key
+	privKey := diffieHellman.GeneratePrivateKey(
+		len(grp.GetPBytes()),
+		grp, rng)
+
+	//make the ID
+	newId, err := xx.NewID(rsaKey.GetPublic(),
+		salt, id.User)
+	if err != nil {
+		return TransmissionIdentity{}, err
+	}
+
+	//create the identity object
+	I := TransmissionIdentity{
+		ID:            newId,
+		RSAPrivatePem: rsaKey,
+		Salt:          salt,
+		DHKeyPrivate:  privKey,
+	}
+
+	return I, nil
+}
+
+// DeepCopy produces a safe copy of a TransmissionIdentity
+func (t TransmissionIdentity) DeepCopy() TransmissionIdentity {
+	saltCopy := make([]byte, len(t.Salt))
+	copy(saltCopy, t.Salt)
+	return TransmissionIdentity{
+		ID:            t.ID.DeepCopy(),
+		RSAPrivatePem: t.RSAPrivatePem,
+		Salt:          saltCopy,
+		DHKeyPrivate:  t.DHKeyPrivate.DeepCopy(),
+	}
+}
diff --git a/api/mnemonic.go b/xxdk/mnemonic.go
similarity index 99%
rename from api/mnemonic.go
rename to xxdk/mnemonic.go
index 9b262da82c81bebcc01fd185adbc5d60a196cb6b..3a2e2051b9485d225704c2896caa6da6319b5dc0 100644
--- a/api/mnemonic.go
+++ b/xxdk/mnemonic.go
@@ -5,7 +5,7 @@
 // LICENSE file                                                              //
 ///////////////////////////////////////////////////////////////////////////////
 
-package api
+package xxdk
 
 import (
 	"github.com/pkg/errors"
diff --git a/api/mnemonic_test.go b/xxdk/mnemonic_test.go
similarity index 99%
rename from api/mnemonic_test.go
rename to xxdk/mnemonic_test.go
index a56a73b1f524018f686af392478f89b7dc2d1dc9..326e16dc22f36ee6b6d9e91ba189fba19cb5e5cd 100644
--- a/api/mnemonic_test.go
+++ b/xxdk/mnemonic_test.go
@@ -5,7 +5,7 @@
 // LICENSE file                                                              //
 ///////////////////////////////////////////////////////////////////////////////
 
-package api
+package xxdk
 
 import (
 	"bytes"
diff --git a/api/ndf.go b/xxdk/ndf.go
similarity index 99%
rename from api/ndf.go
rename to xxdk/ndf.go
index efe7e86ae0c6b0f38c3be734c7623e99a6e92823..d67edc0d93ec8a0e1928e5cf07fb851d4f4942f7 100644
--- a/api/ndf.go
+++ b/xxdk/ndf.go
@@ -5,7 +5,7 @@
 // LICENSE file                                                              //
 ///////////////////////////////////////////////////////////////////////////////
 
-package api
+package xxdk
 
 import (
 	"encoding/base64"
diff --git a/api/messenger/notifications.go b/xxdk/notifications.go
similarity index 88%
rename from api/messenger/notifications.go
rename to xxdk/notifications.go
index 380029ebfaf68cdbe9b7310a731f6614b641d136..32fe156d9318985d964b95717126b701ece0865d 100644
--- a/api/messenger/notifications.go
+++ b/xxdk/notifications.go
@@ -1,11 +1,10 @@
-///////////////////////////////////////////////////////////////////////////////
-// Copyright © 2020 xx network SEZC                                          //
-//                                                                           //
-// Use of this source code is governed by a license that can be found in the //
-// LICENSE file                                                              //
-///////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+// Copyright © 2022 Privategrity Corporation                                   /
+//                                                                             /
+// All rights reserved.                                                        /
+////////////////////////////////////////////////////////////////////////////////
 
-package messenger
+package xxdk
 
 import (
 	"github.com/pkg/errors"
@@ -23,7 +22,7 @@ import (
 // especially as these rely on third parties (i.e., Firebase *cough*
 // *cough* google's palantir *cough*) that may represent a security
 // risk to the user.
-func (m *Client) RegisterForNotifications(token string) error {
+func (m *E2e) RegisterForNotifications(token string) error {
 	jww.INFO.Printf("RegisterForNotifications(%s)", token)
 	// Pull the host from the manage
 	notificationBotHost, ok := m.GetComms().GetHost(&id.NotificationBot)
@@ -61,7 +60,7 @@ func (m *Client) RegisterForNotifications(token string) error {
 }
 
 // UnregisterForNotifications turns of notifications for this client
-func (m *Client) UnregisterForNotifications() error {
+func (m *E2e) UnregisterForNotifications() error {
 	jww.INFO.Printf("UnregisterForNotifications()")
 	// Pull the host from the manage
 	notificationBotHost, ok := m.GetComms().GetHost(&id.NotificationBot)
@@ -86,7 +85,7 @@ func (m *Client) UnregisterForNotifications() error {
 	return nil
 }
 
-func (m *Client) getIidAndSig() ([]byte, []byte, error) {
+func (m *E2e) getIidAndSig() ([]byte, []byte, error) {
 	intermediaryReceptionID, err := ephemeral.GetIntermediaryId(m.GetStorage().GetReceptionID())
 	if err != nil {
 		return nil, nil, errors.WithMessage(err, "RegisterForNotifications: Failed to form intermediary ID")
diff --git a/api/params.go b/xxdk/params.go
similarity index 98%
rename from api/params.go
rename to xxdk/params.go
index 39f9d8db3768ac00c454bf89d2ba8b5326c9fb4e..c5768a2a0512560367f9e0cb5ad3d7f9221ab3c9 100644
--- a/api/params.go
+++ b/xxdk/params.go
@@ -5,7 +5,7 @@
 // LICENSE file                                                              //
 ///////////////////////////////////////////////////////////////////////////////
 
-package api
+package xxdk
 
 import (
 	"encoding/json"
diff --git a/api/params_test.go b/xxdk/params_test.go
similarity index 99%
rename from api/params_test.go
rename to xxdk/params_test.go
index 35bf61d8f10e5b494a8459f64d239d1569df36b4..13868e1fb03e192a9a94cc916960d4121a871b08 100644
--- a/api/params_test.go
+++ b/xxdk/params_test.go
@@ -5,7 +5,7 @@
 // LICENSE file                                                              //
 ///////////////////////////////////////////////////////////////////////////////
 
-package api
+package xxdk
 
 import (
 	"bytes"
diff --git a/api/permissioning.go b/xxdk/permissioning.go
similarity index 96%
rename from api/permissioning.go
rename to xxdk/permissioning.go
index ee25a57e0ccf6adcf5820d432f49519a1493c4a5..2e1d735e1236c410bfb473e7d02bad87b6f73536 100644
--- a/api/permissioning.go
+++ b/xxdk/permissioning.go
@@ -5,7 +5,7 @@
 // LICENSE file                                                              //
 ///////////////////////////////////////////////////////////////////////////////
 
-package api
+package xxdk
 
 import (
 	"encoding/json"
@@ -15,7 +15,7 @@ import (
 )
 
 // Returns an error if registration fails.
-func (c *Client) registerWithPermissioning() error {
+func (c *Cmix) registerWithPermissioning() error {
 	//get the users public key
 	transmissionPubKey := c.storage.GetTransmissionRSA().GetPublic()
 	receptionPubKey := c.storage.GetReceptionRSA().GetPublic()
@@ -54,7 +54,7 @@ func (c *Client) registerWithPermissioning() error {
 
 // ConstructProtoUserFile is a helper function which is used for proto
 // client testing.  This is used for development testing.
-func (c *Client) ConstructProtoUserFile() ([]byte, error) {
+func (c *Cmix) ConstructProtoUserFile() ([]byte, error) {
 
 	//load the registration code
 	regCode, err := c.storage.GetRegCode()
diff --git a/xxdk/precan.go b/xxdk/precan.go
new file mode 100644
index 0000000000000000000000000000000000000000..b710954cc27f6901d5f4b0226a3b5aa920bb8f4a
--- /dev/null
+++ b/xxdk/precan.go
@@ -0,0 +1,166 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright © 2020 xx network SEZC                                          //
+//                                                                           //
+// Use of this source code is governed by a license that can be found in the //
+// LICENSE file                                                              //
+///////////////////////////////////////////////////////////////////////////////
+
+package xxdk
+
+import (
+	"encoding/binary"
+	"github.com/cloudflare/circl/dh/sidh"
+	"gitlab.com/elixxir/client/e2e/ratchet/partner/session"
+	util "gitlab.com/elixxir/client/storage/utility"
+	"gitlab.com/elixxir/crypto/contact"
+	"gitlab.com/elixxir/crypto/cyclic"
+	"gitlab.com/elixxir/crypto/diffieHellman"
+	"gitlab.com/elixxir/primitives/fact"
+	"math/rand"
+
+	jww "github.com/spf13/jwalterweatherman"
+	"gitlab.com/elixxir/client/storage"
+	"gitlab.com/elixxir/client/storage/user"
+	"gitlab.com/elixxir/crypto/fastRNG"
+	"gitlab.com/xx_network/crypto/csprng"
+	"gitlab.com/xx_network/crypto/signature/rsa"
+	"gitlab.com/xx_network/primitives/id"
+)
+
+// CreatePrecannedUser creates a precanned user
+func CreatePrecannedUser(precannedID uint, rng csprng.Source) user.Info {
+
+	// Salt, UID, etc gen
+	salt := make([]byte, SaltSize)
+
+	userID := id.ID{}
+	binary.BigEndian.PutUint64(userID[:], uint64(precannedID))
+	userID.SetType(id.User)
+
+	// NOTE: not used... RSA Keygen (4096 bit defaults)
+	rsaKey, err := rsa.GenerateKey(rng, rsa.DefaultRSABitLen)
+	if err != nil {
+		jww.FATAL.Panicf(err.Error())
+	}
+
+	return user.Info{
+		TransmissionID:   &userID,
+		TransmissionSalt: salt,
+		ReceptionID:      &userID,
+		ReceptionSalt:    salt,
+		Precanned:        true,
+		E2eDhPrivateKey:  nil,
+		E2eDhPublicKey:   nil,
+		TransmissionRSA:  rsaKey,
+		ReceptionRSA:     rsaKey,
+	}
+}
+
+// NewPrecannedClient creates an insecure user with predetermined keys
+// with nodes It creates client storage, generates keys, connects, and
+// registers with the network. Note that this does not register a
+// username/identity, but merely creates a new cryptographic identity
+// for adding such information at a later date.
+func NewPrecannedClient(precannedID uint, defJSON, storageDir string,
+	password []byte) error {
+	jww.INFO.Printf("NewPrecannedClient()")
+	rngStreamGen := fastRNG.NewStreamGenerator(12, 1024,
+		csprng.NewSystemRNG)
+	rngStream := rngStreamGen.GetStream()
+
+	def, err := ParseNDF(defJSON)
+	if err != nil {
+		return err
+	}
+	cmixGrp, e2eGrp := DecodeGroups(def)
+
+	protoUser := CreatePrecannedUser(precannedID, rngStream)
+
+	store, err := CheckVersionAndSetupStorage(def, storageDir, password,
+		protoUser, cmixGrp, e2eGrp, "")
+	if err != nil {
+		return err
+	}
+
+	// Mark the precanned user as finished with permissioning and registered
+	// with the network.
+	err = store.ForwardRegistrationStatus(storage.PermissioningComplete)
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
+
+func generatePrecanDHKeypair(precannedID uint, e2eGrp *cyclic.Group) *cyclic.Int {
+	// DH Keygen
+	prng := rand.New(rand.NewSource(int64(precannedID)))
+	prime := e2eGrp.GetPBytes()
+	keyLen := len(prime)
+	priv := diffieHellman.GeneratePrivateKey(keyLen, e2eGrp, prng)
+	return priv
+}
+
+// Create an insecure e2e relationship with a precanned user
+func (m *E2e) MakePrecannedAuthenticatedChannel(precannedID uint) (
+	contact.Contact, error) {
+
+	precan := m.MakePrecannedContact(precannedID)
+
+	myID := binary.BigEndian.Uint64(m.GetStorage().GetReceptionID()[:])
+	// Pick a variant based on if their ID is bigger than mine.
+	myVariant := sidh.KeyVariantSidhA
+	theirVariant := sidh.KeyVariant(sidh.KeyVariantSidhB)
+	if myID > uint64(precannedID) {
+		myVariant = sidh.KeyVariantSidhB
+		theirVariant = sidh.KeyVariantSidhA
+	}
+	prng1 := rand.New(rand.NewSource(int64(precannedID)))
+	theirSIDHPrivKey := util.NewSIDHPrivateKey(theirVariant)
+	theirSIDHPubKey := util.NewSIDHPublicKey(theirVariant)
+	theirSIDHPrivKey.Generate(prng1)
+	theirSIDHPrivKey.GeneratePublicKey(theirSIDHPubKey)
+
+	prng2 := rand.New(rand.NewSource(int64(myID)))
+	mySIDHPrivKey := util.NewSIDHPrivateKey(myVariant)
+	mySIDHPubKey := util.NewSIDHPublicKey(myVariant)
+	mySIDHPrivKey.Generate(prng2)
+	mySIDHPrivKey.GeneratePublicKey(mySIDHPubKey)
+
+	// add the precanned user as a e2e contact
+	// FIXME: these params need to be threaded through...
+	sesParam := session.GetDefaultParams()
+	_, err := m.e2e.AddPartner(precan.ID, precan.DhPubKey,
+		m.e2e.GetHistoricalDHPrivkey(), theirSIDHPubKey,
+		mySIDHPrivKey, sesParam, sesParam)
+
+	// check garbled messages in case any messages arrived before creating
+	// the channel
+	m.GetCmix().CheckInProgressMessages()
+
+	return precan, err
+}
+
+// Create an insecure e2e contact object for a precanned user
+func (m *E2e) MakePrecannedContact(precannedID uint) contact.Contact {
+
+	e2eGrp := m.GetStorage().GetE2EGroup()
+
+	rng := m.GetRng().GetStream()
+	precanned := CreatePrecannedUser(precannedID, rng)
+	rng.Close()
+
+	precanned.E2eDhPrivateKey = generatePrecanDHKeypair(precannedID,
+		m.GetStorage().GetE2EGroup())
+
+	// compute their public e2e key
+	partnerPubKey := e2eGrp.ExpG(precanned.E2eDhPrivateKey,
+		e2eGrp.NewInt(1))
+
+	return contact.Contact{
+		ID:             precanned.ReceptionID,
+		DhPubKey:       partnerPubKey,
+		OwnershipProof: nil,
+		Facts:          make([]fact.Fact, 0),
+	}
+}
diff --git a/api/services.go b/xxdk/services.go
similarity index 99%
rename from api/services.go
rename to xxdk/services.go
index 3acfddbfe32bc8cfb08ad3431b4932e9f3438922..b44149ec16fdf8ff5b01bd4dbc5f3c5bb5cd78c2 100644
--- a/api/services.go
+++ b/xxdk/services.go
@@ -1,4 +1,4 @@
-package api
+package xxdk
 
 import (
 	"github.com/pkg/errors"
diff --git a/api/services_test.go b/xxdk/services_test.go
similarity index 99%
rename from api/services_test.go
rename to xxdk/services_test.go
index be65c1a5faeec4964eeac8a8568b60aacda7a2d1..c87f3bcecb79775214992747eaad06cf826b159b 100644
--- a/api/services_test.go
+++ b/xxdk/services_test.go
@@ -5,7 +5,7 @@
 // LICENSE file                                                              //
 ///////////////////////////////////////////////////////////////////////////////
 
-package api
+package xxdk
 
 import (
 	"errors"
diff --git a/api/status.go b/xxdk/status.go
similarity index 98%
rename from api/status.go
rename to xxdk/status.go
index 33e567725a16b457e936270a3f43acaf7c671129..f613f87d454032d05f2114999d95728b4e2670a9 100644
--- a/api/status.go
+++ b/xxdk/status.go
@@ -5,7 +5,7 @@
 // LICENSE file                                                              //
 ///////////////////////////////////////////////////////////////////////////////
 
-package api
+package xxdk
 
 import (
 	"fmt"
diff --git a/api/user.go b/xxdk/user.go
similarity index 99%
rename from api/user.go
rename to xxdk/user.go
index cbe2b92a38041877a368291122016c9907ff9f12..4eb421050ed68c242dff2b1f509d01b41c05cdc8 100644
--- a/api/user.go
+++ b/xxdk/user.go
@@ -5,7 +5,7 @@
 // LICENSE file                                                              //
 ///////////////////////////////////////////////////////////////////////////////
 
-package api
+package xxdk
 
 import (
 	"regexp"
diff --git a/api/messenger/utils.go b/xxdk/utils.go
similarity index 98%
rename from api/messenger/utils.go
rename to xxdk/utils.go
index 6e1ff51fd9be792124e30ee2a4e0487d3598efdc..d4ade6ce9f6d87f423da4b95e91a3aa5cfeb1019 100644
--- a/api/messenger/utils.go
+++ b/xxdk/utils.go
@@ -1,12 +1,12 @@
 ////////////////////////////////////////////////////////////////////////////////
-// Copyright © 2021 Privategrity Corporation                                   /
+// Copyright © 2022 Privategrity Corporation                                   /
 //                                                                             /
 // All rights reserved.                                                        /
 ////////////////////////////////////////////////////////////////////////////////
 
 // Provides various utility functions for access over the bindings
 
-package messenger
+package xxdk
 
 import (
 	"bytes"
diff --git a/api/utilsInterfaces_test.go b/xxdk/utilsInterfaces_test.go
similarity index 99%
rename from api/utilsInterfaces_test.go
rename to xxdk/utilsInterfaces_test.go
index 72e141698805b029a799d19ccd4ca7e5f4a82e3e..107fb06778868bdf829e537c51d3cd1ae6cb9571 100644
--- a/api/utilsInterfaces_test.go
+++ b/xxdk/utilsInterfaces_test.go
@@ -4,7 +4,7 @@
 // Use of this source code is governed by a license that can be found in the //
 // LICENSE file                                                              //
 ///////////////////////////////////////////////////////////////////////////////
-package api
+package xxdk
 
 import (
 	"gitlab.com/xx_network/primitives/ndf"
diff --git a/api/utils_test.go b/xxdk/utils_test.go
similarity index 97%
rename from api/utils_test.go
rename to xxdk/utils_test.go
index b2f59f90739fa8bff71292d35d5bac9f09cdcbae..2f6afc7196c3f2e554482ab848f290a83084ec7c 100644
--- a/api/utils_test.go
+++ b/xxdk/utils_test.go
@@ -5,7 +5,7 @@
 // LICENSE file                                                              //
 ///////////////////////////////////////////////////////////////////////////////
 
-package api
+package xxdk
 
 import (
 	"testing"
@@ -26,7 +26,7 @@ import (
 	"gitlab.com/xx_network/primitives/utils"
 )
 
-func newTestingClient(face interface{}) (*Client, error) {
+func newTestingClient(face interface{}) (*Cmix, error) {
 	switch face.(type) {
 	case *testing.T, *testing.M, *testing.B, *testing.PB:
 		break
@@ -45,7 +45,7 @@ func newTestingClient(face interface{}) (*Client, error) {
 			"Could not construct a mock client: %v", err)
 	}
 
-	c, err := OpenClient(storageDir, password, GetDefaultParams())
+	c, err := OpenCmix(storageDir, password, GetDefaultParams())
 	if err != nil {
 		return nil, errors.Errorf("Could not open a mock client: %v",
 			err)
diff --git a/api/version_vars.go b/xxdk/version_vars.go
similarity index 93%
rename from api/version_vars.go
rename to xxdk/version_vars.go
index dd52d6cf364f5fc60d6c08891c72b556e773498b..c7e51f9da6c60b59f90315518d4b4d80e1b4e09d 100644
--- a/api/version_vars.go
+++ b/xxdk/version_vars.go
@@ -1,9 +1,9 @@
 // Code generated by go generate; DO NOT EDIT.
 // This file was generated by robots at
-// 2022-06-06 16:30:34.245821 -0500 CDT m=+0.030165276
-package api
+// 2022-06-16 12:41:25.706495 -0500 CDT m=+0.027317522
+package xxdk
 
-const GITVERSION = `48285297 Merge branch 'restructure' into 'release'`
+const GITVERSION = `1e874329 fix Makefile`
 const SEMVER = "4.2.0"
 const DEPENDENCIES = `module gitlab.com/elixxir/client
 
@@ -58,7 +58,6 @@ require (
 	gitlab.com/xx_network/ring v0.0.3-0.20220222211904-da613960ad93 // indirect
 	golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac // indirect
 	golang.org/x/text v0.3.6 // indirect
-	golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 // indirect
 	google.golang.org/genproto v0.0.0-20210105202744-fe13368bc0e1 // indirect
 	gopkg.in/ini.v1 v1.62.0 // indirect
 	gopkg.in/yaml.v2 v2.4.0 // indirect
diff --git a/xxmutils/restoreContacts.go b/xxmutils/restoreContacts.go
index 96e9c2b1b8d4fd26680bef805f27bbdb712d71b4..0f8b6a565b0903fd8ea98b279610a0e307902383 100644
--- a/xxmutils/restoreContacts.go
+++ b/xxmutils/restoreContacts.go
@@ -11,8 +11,8 @@ import (
 	"encoding/json"
 	"errors"
 	"fmt"
-	"gitlab.com/elixxir/client/api/messenger"
 	"gitlab.com/elixxir/client/single"
+	"gitlab.com/elixxir/client/xxdk"
 	"gitlab.com/xx_network/primitives/netTime"
 	"math"
 	"strings"
@@ -37,7 +37,7 @@ import (
 // xxDK users should not use this function. This function is used by
 // the mobile phone apps and are not intended to be part of the xxDK. It
 // should be treated as internal functions specific to the phone apps.
-func RestoreContactsFromBackup(backupPartnerIDs []byte, client *messenger.Client,
+func RestoreContactsFromBackup(backupPartnerIDs []byte, client *xxdk.E2e,
 	udManager *ud.Manager,
 	updatesCb interfaces.RestoreContactsUpdater) ([]*id.ID, []*id.ID,
 	[]error, error) {
@@ -178,7 +178,7 @@ func RestoreContactsFromBackup(backupPartnerIDs []byte, client *messenger.Client
 // the mobile phone apps and are not intended to be part of the xxDK. It
 // should be treated as internal functions specific to the phone apps.
 func LookupContacts(in chan *id.ID, out chan *contact.Contact,
-	failCh chan failure, client *messenger.Client, udContact contact.Contact,
+	failCh chan failure, client *xxdk.E2e, udContact contact.Contact,
 	wg *sync.WaitGroup) {
 	defer wg.Done()
 	// Start looking up contacts with user discovery and feed this
@@ -205,7 +205,7 @@ func LookupContacts(in chan *id.ID, out chan *contact.Contact,
 // the mobile phone apps and are not intended to be part of the xxDK. It
 // should be treated as internal functions specific to the phone apps.
 func ResetSessions(in, out chan *contact.Contact, failCh chan failure,
-	client *messenger.Client, wg *sync.WaitGroup) {
+	client *xxdk.E2e, wg *sync.WaitGroup) {
 	defer wg.Done()
 	for c := range in {
 		_, err := client.GetAuth().Reset(*c)
@@ -224,7 +224,7 @@ func ResetSessions(in, out chan *contact.Contact, failCh chan failure,
 // xxDK users should not use this function. This function is used by
 // the mobile phone apps and are not intended to be part of the xxDK. It
 // should be treated as internal functions specific to the phone apps.
-func LookupContact(userID *id.ID, client *messenger.Client, udContact contact.Contact) (
+func LookupContact(userID *id.ID, client *xxdk.E2e, udContact contact.Contact) (
 	*contact.Contact, error) {
 	// This is a little wonky, but wait until we get called then
 	// set the result to the contact objects details if there is