diff --git a/api/authenticatedChannel.go b/api/authenticatedChannel.go
index 7194f0429c7bc38268bb418a26138c5ce58308e9..1152d2739cccacf884b32349be4f65bd047e5fb6 100644
--- a/api/authenticatedChannel.go
+++ b/api/authenticatedChannel.go
@@ -59,8 +59,7 @@ func (c *Client) RegisterAuthCallbacks(request auth.RequestCallback,
 // An error will be returned if a channel already exists, if a request doest
 // exist, or if the passed in contact does not exactly match the received
 // request
-func (c *Client) ConfirmAuthenticatedChannel(recipient, me contact.Contact,
-	message string) error {
+func (c *Client) ConfirmAuthenticatedChannel(recipient contact.Contact) error {
 	jww.INFO.Printf("RequestAuthenticatedChannel(%s)", recipient.ID)
 
 	if !c.network.GetHealthTracker().IsHealthy() {
diff --git a/auth/callback.go b/auth/callback.go
index 5817bd39886b5130e24c954c74769ad3813fdabf..a8eed00f1c5b30b51634a6bfb826ca183606d368 100644
--- a/auth/callback.go
+++ b/auth/callback.go
@@ -153,7 +153,7 @@ func handleRequest(cmixMsg format.Message, myHistoricalPrivKey *cyclic.Int,
 	}
 
 	//process the inner payload
-	facts, msg, err := contact.UnstringifyFacts(
+	facts, msg, err := contact.UnstringifyFactList(
 		string(requestFmt.msgPayload))
 	if err != nil {
 		jww.WARN.Printf("failed to parse facts and message "+
diff --git a/auth/request.go b/auth/request.go
index fe0b621f2e9f55b71b6a245f8a64e6b6ff2e17fc..ba231d297821e97f3e06c819bb109867cd585078 100644
--- a/auth/request.go
+++ b/auth/request.go
@@ -75,7 +75,7 @@ func RequestAuth(partner, me contact.Contact, message string, rng io.Reader,
 	}
 
 	//check the payload fits
-	facts := me.StringifyFacts()
+	facts := me.Facts.Stringify()
 	msgPayload := facts + message + eol
 	msgPayloadBytes := []byte(msgPayload)
 
diff --git a/bindings/authenticatedChannels.go b/bindings/authenticatedChannels.go
index 7acd5d39962f29b5cf7ed0f2f127891bd3587550..623a452503f5655c9d79bb52d7d9d49e4e3eb253 100644
--- a/bindings/authenticatedChannels.go
+++ b/bindings/authenticatedChannels.go
@@ -1,8 +1,105 @@
 package bindings
 
-import "gitlab.com/elixxir/client/interfaces/bind"
+import (
+	"errors"
+	"fmt"
+	"gitlab.com/elixxir/client/interfaces/contact"
+)
 
 // Create an insecure e2e relationship with a precanned user
-func (c *Client) MakePrecannedAuthenticatedChannel(precannedID int) bind.Contact {
-	return c.api.MakePrecannedContact(uint(precannedID))
+func (c *Client) MakePrecannedAuthenticatedChannel(precannedID int) (*Contact, error) {
+	precannedContact, err := c.api.MakePrecannedAuthenticatedChannel(uint(precannedID))
+	if err != nil {
+		return nil, errors.New(fmt.Sprintf("Failed to "+
+			"MakePrecannedAuthenticatedChannel: %+v", err))
+	}
+	return &Contact{c: &precannedContact}, nil
 }
+
+// RequestAuthenticatedChannel sends a request to another party to establish an
+// authenticated channel
+// It will not run if the network status is not healthy
+// An error will be returned if a channel already exists, if a request was
+// already received, or if a request was already sent
+// When a confirmation occurs, the channel will be created and the callback
+// will be called
+//
+// 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 refrence to
+// the same pointer.
+func (c *Client) RequestAuthenticatedChannel(recipientMarshaled,
+	meMarshaled []byte, message string) error {
+	recipent, err := contact.Unmarshal(recipientMarshaled)
+
+	if err != nil {
+		return errors.New(fmt.Sprintf("Failed to "+
+			"RequestAuthenticatedChannel: Failed to Unmarshal Recipent: "+
+			"%+v", err))
+	}
+
+	me, err := contact.Unmarshal(meMarshaled)
+
+	if err != nil {
+		return errors.New(fmt.Sprintf("Failed to "+
+			"RequestAuthenticatedChannel: Failed to Unmarshal Me: %+v", err))
+	}
+
+	return c.api.RequestAuthenticatedChannel(recipent, me, message)
+}
+
+// RegisterAuthCallbacks registers both callbacks for authenticated channels.
+// This can only be called once
+func (c *Client) RegisterAuthCallbacks(request AuthRequestCallback,
+	confirm AuthConfirmCallback) error {
+
+	requestFunc := func(requestor contact.Contact, message string) {
+		requestorBind := &Contact{c: &requestor}
+		request.Callback(requestorBind, message)
+	}
+
+	confirmFunc := func(partner contact.Contact) {
+		partnerBind := &Contact{c: &partner}
+		confirm.Callback(partnerBind)
+	}
+
+	return c.api.RegisterAuthCallbacks(requestFunc, confirmFunc)
+}
+
+// ConfirmAuthenticatedChannel creates an authenticated channel out of a valid
+// received request and sends a message to the requestor that the request has
+// been confirmed
+// It will not run if the network status is not healthy
+// An error will be returned if a channel already exists, if a request doest
+// exist, or if the passed in contact does not exactly match the received
+// request
+func (c *Client) ConfirmAuthenticatedChannel(recipientMarshaled []byte) error {
+	recipent, err := contact.Unmarshal(recipientMarshaled)
+
+	if err != nil {
+		return errors.New(fmt.Sprintf("Failed to "+
+			"ConfirmAuthenticatedChannel: Failed to Unmarshal Recipient: "+
+			"%+v", err))
+	}
+
+	return c.api.ConfirmAuthenticatedChannel(recipent)
+}
+
+// VerifyOwnership checks if the ownership proof on a passed contact matches the
+// identity in a verified contact
+func (c *Client) VerifyOwnership(receivedMarshaled, verifiedMarshaled []byte) (bool, error) {
+	received, err := contact.Unmarshal(receivedMarshaled)
+
+	if err != nil {
+		return false, errors.New(fmt.Sprintf("Failed to "+
+			"VerifyOwnership: Failed to Unmarshal Received: %+v", err))
+	}
+
+	verified, err := contact.Unmarshal(verifiedMarshaled)
+
+	if err != nil {
+		return false, errors.New(fmt.Sprintf("Failed to "+
+			"VerifyOwnership: Failed to Unmarshal Verified: %+v", err))
+	}
+
+	return c.api.VerifyOwnership(received, verified), nil
+}
\ No newline at end of file
diff --git a/bindings/callback.go b/bindings/callback.go
index a3d9e2b8e19af71d26cf62a2f2251e7349b8220e..0dd0fbbc9112968e71a6dca1008454454e5c5713 100644
--- a/bindings/callback.go
+++ b/bindings/callback.go
@@ -30,6 +30,23 @@ type RoundEventCallback interface {
 	EventCallback(rid, state int, timedOut bool)
 }
 
+// RoundEventHandler handles round events happening on the cMix network.
+type MessageDeliveryCallback interface {
+	EventCallback(msgID []byte, delivered, timedOut bool)
+}
+
+// AuthRequestCallback notifies the register whenever they receive an auth
+// request
+type AuthRequestCallback interface {
+	Callback(requestor *Contact, message string)
+}
+
+// AuthConfirmCallback notifies the register whenever they receive an auth
+// request confirmation
+type AuthConfirmCallback interface {
+	Callback(partner *Contact)
+}
+
 // Generic Unregister - a generic return used for all callbacks which can be
 // unregistered
 // Interface which allows the un-registration of a listener
@@ -38,23 +55,34 @@ type Unregister struct {
 }
 
 //Call unregisters a callback
-func (u Unregister) Unregister() {
+func (u *Unregister) Unregister() {
 	u.f()
 }
 
 //creates an unregister interface for listeners
-func newListenerUnregister(lid switchboard.ListenerID, sw interfaces.Switchboard) Unregister {
+func newListenerUnregister(lid switchboard.ListenerID, sw interfaces.Switchboard) *Unregister {
 	f := func() {
 		sw.Unregister(lid)
 	}
-	return Unregister{f: f}
+	return &Unregister{f: f}
 }
 
 //creates an unregister interface for round events
 func newRoundUnregister(rid id.Round, ec *dataStructures.EventCallback,
-	re interfaces.RoundEvents) Unregister {
+	re interfaces.RoundEvents) *Unregister {
 	f := func() {
 		re.Remove(rid, ec)
 	}
-	return Unregister{f: f}
+	return &Unregister{f: f}
+}
+
+//creates an unregister interface for round events
+func newRoundListUnregister(rounds []id.Round, ec []*dataStructures.EventCallback,
+	re interfaces.RoundEvents) *Unregister {
+	f := func() {
+		for i, r := range rounds {
+			re.Remove(r, ec[i])
+		}
+	}
+	return &Unregister{f: f}
 }
diff --git a/bindings/client.go b/bindings/client.go
index 2d71a5af7621c1095b107c603d37f053832685d6..11f00973408be5f973936408e79c7ed2833cd0f5 100644
--- a/bindings/client.go
+++ b/bindings/client.go
@@ -7,17 +7,22 @@
 package bindings
 
 import (
+	"encoding/json"
 	"errors"
+	"fmt"
 	"github.com/spf13/jwalterweatherman"
 	jww "github.com/spf13/jwalterweatherman"
 	"gitlab.com/elixxir/client/api"
-	"gitlab.com/elixxir/client/interfaces/bind"
 	"gitlab.com/elixxir/client/interfaces/contact"
 	"gitlab.com/elixxir/client/interfaces/message"
+	"gitlab.com/elixxir/client/interfaces/utility"
+	"gitlab.com/elixxir/client/storage"
 	"gitlab.com/elixxir/comms/mixmessages"
 	"gitlab.com/elixxir/primitives/states"
 	"gitlab.com/xx_network/primitives/id"
 	"time"
+	ds "gitlab.com/elixxir/comms/network/dataStructures"
+
 )
 
 // BindingsClient wraps the api.Client, implementing additional functions
@@ -34,7 +39,12 @@ type Client struct {
 // Users of this function should delete the storage directory on error.
 func NewClient(network, storageDir string, password []byte, regCode string) error {
 	jwalterweatherman.SetLogThreshold(jwalterweatherman.LevelInfo)
-	return api.NewClient(network, storageDir, password, regCode)
+
+	if err := api.NewClient(network, storageDir, password, regCode); err != nil {
+		return errors.New(fmt.Sprintf("Failed to create new client: %+v",
+			err))
+	}
+	return nil
 }
 
 // NewPrecannedClient creates an insecure user with predetermined keys with nodes
@@ -50,7 +60,11 @@ func NewPrecannedClient(precannedID int, network, storageDir string, password []
 		return errors.New("Cannot create precanned client with negative ID")
 	}
 
-	return api.NewPrecannedClient(uint(precannedID), network, storageDir, password)
+	if err := api.NewPrecannedClient(uint(precannedID), network, storageDir, password); err != nil {
+		return errors.New(fmt.Sprintf("Failed to create new precanned "+
+			"client: %+v", err))
+	}
+	return nil
 }
 
 // Login will load an existing client from the storageDir
@@ -67,14 +81,29 @@ func Login(storageDir string, password []byte) (*Client, error) {
 
 	client, err := api.Login(storageDir, password)
 	if err != nil {
-		return nil, err
+		return nil, errors.New(fmt.Sprintf("Failed to login: %+v", err))
 	}
 	return &Client{*client}, nil
 }
 
-//Unmarshals a marshaled contact object
-func UnmarshalContact(b []byte) (bind.Contact, error) {
-	return contact.Unmarshal(b)
+//Unmarshals a marshaled contact object, returns an error if it fails
+func UnmarshalContact(b []byte) (*Contact, error) {
+	c, err := contact.Unmarshal(b)
+	if err != nil {
+		return nil, errors.New(fmt.Sprintf("Failed to Unmarshal "+
+			"Contact: %+v", err))
+	}
+	return &Contact{c: &c}, nil
+}
+
+//Unmarshals a marshaled send report object, returns an error if it fails
+func UnmarshalSendReport(b []byte) (*SendReport, error) {
+	sr := &SendReport{}
+	if err := json.Unmarshal(b, sr); err != nil {
+		return nil, errors.New(fmt.Sprintf("Failed to Unmarshal "+
+			"Send Report: %+v", err))
+	}
+	return sr, nil
 }
 
 // StartNetworkFollower kicks off the tracking of the network. It starts
@@ -106,7 +135,11 @@ func UnmarshalContact(b []byte) (bind.Contact, error) {
 //   - KeyExchange Confirm (/keyExchange/confirm.go)
 //		Responds to confirmations of successful rekey operations
 func (c *Client) StartNetworkFollower() error {
-	return c.api.StartNetworkFollower()
+	if err := c.api.StartNetworkFollower(); err != nil {
+		return errors.New(fmt.Sprintf("Failed to start the "+
+			"network follower: %+v", err))
+	}
+	return nil
 }
 
 // StopNetworkFollower stops the network follower if it is running.
@@ -116,7 +149,11 @@ func (c *Client) StartNetworkFollower() error {
 // most likely be in an unrecoverable state and need to be trashed.
 func (c *Client) StopNetworkFollower(timeoutMS int) error {
 	timeout := time.Duration(timeoutMS) * time.Millisecond
-	return c.api.StopNetworkFollower(timeout)
+	if err := c.api.StopNetworkFollower(timeout); err != nil {
+		return errors.New(fmt.Sprintf("Failed to stop the "+
+			"network follower: %+v", err))
+	}
+	return nil
 }
 
 // Gets the state of the network follower. Returns:
@@ -144,25 +181,39 @@ func (c *Client) RegisterNetworkHealthCB(nhc NetworkHealthCallback) {
 // matching specific uid, msgType, and/or username
 // Returns a ListenerUnregister interface which can be
 //
+// to register for any userID, pass in an id with length 0 or an id with
+// all zeroes
+//
+// to register for any message type, pass in a message type of 0
+//
 // Message Types can be found in client/interfaces/message/type.go
 // Make sure to not conflict with ANY default message types
 func (c *Client) RegisterListener(uid []byte, msgType int,
-	listener Listener) error {
+	listener Listener) (*Unregister, error) {
 
 	name := listener.Name()
-	u, err := id.Unmarshal(uid)
-	if err != nil {
-		return err
+
+	var u *id.ID
+	if len(uid) == 0 {
+		u = &id.ID{}
+	} else {
+		var err error
+		u, err = id.Unmarshal(uid)
+		if err != nil {
+			return nil, errors.New(fmt.Sprintf("Failed to "+
+				"ResgisterListener: %+v", err))
+		}
 	}
+
 	mt := message.Type(msgType)
 
 	f := func(item message.Receive) {
 		listener.Hear(item)
 	}
 
-	c.api.GetSwitchboard().RegisterFunc(name, u, mt, f)
+	lid := c.api.GetSwitchboard().RegisterFunc(name, u, mt, f)
 
-	return nil
+	return newListenerUnregister(lid, c.api.GetSwitchboard()), nil
 }
 
 // RegisterRoundEventsHandler registers a callback interface for round
@@ -181,7 +232,7 @@ func (c *Client) RegisterListener(uid []byte, msgType int,
 //  0x06 - FAILED
 // These states are defined in elixxir/primitives/states/state.go
 func (c *Client) RegisterRoundEventsHandler(rid int, cb RoundEventCallback,
-	timeoutMS int, il *IntList) Unregister {
+	timeoutMS int, il *IntList) *Unregister {
 
 	rcb := func(ri *mixmessages.RoundInfo, timedOut bool) {
 		cb.EventCallback(int(ri.ID), int(ri.State), timedOut)
@@ -201,11 +252,55 @@ func (c *Client) RegisterRoundEventsHandler(rid int, cb RoundEventCallback,
 	return newRoundUnregister(roundID, ec, c.api.GetRoundEvents())
 }
 
+// RegisterMessageDeliveryCB allows the caller to get notified if the rounds a
+// message was sent in sucesfully completed. Under the hood, this uses the same
+// interface as RegisterRoundEventsHandler, but provides a convienet way to use
+// the interface in its most common form, looking up the result of message
+// retreval
+//
+// The callbacks will return at timeoutMS if no state update occurs
+//
+// 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 refrence to
+// the same pointer.
+func (c *Client) RegisterMessageDeliveryCB(marshaledSendReport []byte,
+	mdc MessageDeliveryCallback, timeoutMS int) (*Unregister, error) {
+
+	sr, err := UnmarshalSendReport(marshaledSendReport)
+	if err != nil {
+		return nil, errors.New(fmt.Sprintf("Failed to "+
+			"RegisterMessageDeliveryCB: %+v", err))
+	}
+
+	/*check message delivery*/
+	sendResults := make(chan ds.EventReturn, len(sr.rl.list))
+	roundEvents := c.api.GetRoundEvents()
+
+	reventObjs := make([]*ds.EventCallback, len(sr.rl.list))
+
+	for i, r := range sr.rl.list {
+		reventObjs[i] = roundEvents.AddRoundEventChan(r, sendResults,
+			time.Duration(timeoutMS)*time.Millisecond, states.COMPLETED,
+			states.FAILED)
+	}
+
+	go func() {
+		success, _, numTmeout := utility.TrackResults(sendResults, len(sr.rl.list))
+		if !success {
+			mdc.EventCallback(sr.mid[:], false, numTmeout > 0)
+		} else {
+			mdc.EventCallback(sr.mid[:], true, false)
+		}
+	}()
+
+	return newRoundListUnregister(sr.rl.list, reventObjs, roundEvents), nil
+}
+
 // Returns a user object from which all information about the current user
 // can be gleaned
-func (c *Client) GetUser() User {
+func (c *Client) GetUser() *User {
 	u := c.api.GetUser()
-	return &u
+	return &User{u: &u}
 }
 
 /*
diff --git a/bindings/contact.go b/bindings/contact.go
index 0c96fc41685a56257544a3cd107986fb3357295e..012eada71c84fc1a196cfc95acb24268b6a2f8f9 100644
--- a/bindings/contact.go
+++ b/bindings/contact.go
@@ -1,7 +1,6 @@
 package bindings
 
 import (
-	"encoding/json"
 	"errors"
 	"gitlab.com/elixxir/client/interfaces/contact"
 )
@@ -19,6 +18,7 @@ func (f *Fact) Type() int {
 	return int(f.f.T)
 }
 
+
 /* contact object*/
 type Contact struct {
 	c *contact.Contact
@@ -44,6 +44,11 @@ func (c *Contact) GetFactList() *FactList {
 	return &FactList{c: c.c}
 }
 
+func (c *Contact) Marshal() ([]byte, error) {
+	return c.c.Marshal()
+}
+
+/* FactList object*/
 type FactList struct {
 	c *contact.Contact
 }
@@ -69,7 +74,5 @@ func (fl *FactList) Add(fact string, factType int) error {
 }
 
 func (fl *FactList) Marshal() ([]byte, error) {
-	return json.Marshal(&fl.c.Facts)
+	return []byte(fl.c.Facts.Stringify()), nil
 }
-
-func unmarshalFactList
diff --git a/bindings/interfaces.go b/bindings/interfaces.go
index ac882f2756a0e5879a8e4e4cfa239a4381bd885b..cee69db76dfe49479868a97e69da58796c2cb8ab 100644
--- a/bindings/interfaces.go
+++ b/bindings/interfaces.go
@@ -198,16 +198,4 @@ type Message interface {
 	GetTimestampMS() int
 	// Returns the message's timestamp in ns since unix epoc
 	GetTimestampNano() int
-}
-
-type User interface {
-	GetID() []byte
-	GetSalt() []byte
-	GetRSAPrivateKeyPem() []byte
-	GetRSAPublicKeyPem() []byte
-	//IsPrecanned() int
-	GetCmixDhPrivateKey() []byte
-	GetCmixDhPublicKey() []byte
-	GetE2EDhPrivateKey() []byte
-	GetE2EDhPublicKey() []byte
 }
\ No newline at end of file
diff --git a/bindings/list.go b/bindings/list.go
index f47c4ea01b1aa6c4cb2e992a13fc74a2a02a6c02..0edfb41be5402cba75e7123d1445b159bfa399ba 100644
--- a/bindings/list.go
+++ b/bindings/list.go
@@ -28,25 +28,17 @@ func (il *IntList) Get(i int) (int, error) {
 	return il.lst[i], nil
 }
 
-type roundList struct {
+type RoundList struct {
 	list []id.Round
 }
 
-// RoundList contains a list of contacts
-type RoundList interface {
-	// Len returns the number of contacts in the list
-	Len() int
-	// Get returns the round ID at index i
-	Get(i int) (int, error)
-}
-
 // Gets the number of round IDs stored
-func (rl *roundList) Len() int {
+func (rl *RoundList) Len() int {
 	return len(rl.list)
 }
 
 // Gets a stored round ID at the given index
-func (rl *roundList) Get(i int) (int, error) {
+func (rl *RoundList) Get(i int) (int, error) {
 	if i < 0 || i > len(rl.list) {
 		return -1, errors.New("round ID cannot be under 0 or over" +
 			" list len")
diff --git a/bindings/send.go b/bindings/send.go
index 9da5afb93bb5afa521b8cd3c9cdbd22909d982c2..a554017877b666eab5b9126a700c516b5852a7af 100644
--- a/bindings/send.go
+++ b/bindings/send.go
@@ -1,6 +1,7 @@
 package bindings
 
 import (
+	"encoding/json"
 	"errors"
 	"fmt"
 	"gitlab.com/elixxir/client/interfaces/message"
@@ -25,19 +26,22 @@ import (
 func (c *Client) SendCmix(recipient, contents []byte) (int, error) {
 	u, err := id.Unmarshal(recipient)
 	if err != nil {
-		return -1, err
+		return -1, errors.New(fmt.Sprintf("Failed to sendCmix: %+v",
+			err))
 	}
 
 	msg, err := c.api.NewCMIXMessage(u, contents)
 	if err != nil {
-		return -1, err
+		return -1, errors.New(fmt.Sprintf("Failed to sendCmix: %+v",
+			err))
 	}
 
 	rid, err := c.api.SendCMIX(msg, params.GetDefaultCMIX())
 	if err != nil {
-		return -1, err
+		return -1, errors.New(fmt.Sprintf("Failed to sendCmix: %+v",
+			err))
 	}
-	return int(rid), err
+	return int(rid), nil
 }
 
 // SendUnsafe sends an unencrypted payload to the provided recipient
@@ -49,10 +53,10 @@ func (c *Client) SendCmix(recipient, contents []byte) (int, error) {
 // Message Types can be found in client/interfaces/message/type.go
 // Make sure to not conflict with ANY default message types with custom types
 func (c *Client) SendUnsafe(recipient, payload []byte,
-	messageType int) (RoundList, error) {
+	messageType int) (*RoundList, error) {
 	u, err := id.Unmarshal(recipient)
 	if err != nil {
-		return nil, errors.New(fmt.Sprintf("Failed to sendUnsafew: %+v",
+		return nil, errors.New(fmt.Sprintf("Failed to sendUnsafe: %+v",
 			err))
 	}
 
@@ -64,11 +68,11 @@ func (c *Client) SendUnsafe(recipient, payload []byte,
 
 	rids, err := c.api.SendUnsafe(m, params.GetDefaultUnsafe())
 	if err != nil {
-		return nil, errors.New(fmt.Sprintf("Failed to sendUnsafew: %+v",
+		return nil, errors.New(fmt.Sprintf("Failed to sendUnsafe: %+v",
 			err))
 	}
 
-	return &roundList{list: rids}, nil
+	return &RoundList{list: rids}, nil
 }
 
 
@@ -78,11 +82,10 @@ func (c *Client) SendUnsafe(recipient, payload []byte,
 //
 // Message Types can be found in client/interfaces/message/type.go
 // Make sure to not conflict with ANY default message types
-func (c *Client) SendE2E(recipient, payload []byte,
-	messageType int) (*SendReport, error) {
+func (c *Client) SendE2E(recipient, payload []byte, messageType int) (*SendReport, error) {
 	u, err := id.Unmarshal(recipient)
 	if err != nil {
-		return nil, err
+		return nil, errors.New(fmt.Sprintf("Failed SendE2E: %+v", err))
 	}
 
 	m := message.Send{
@@ -93,26 +96,31 @@ func (c *Client) SendE2E(recipient, payload []byte,
 
 	rids, mid, err := c.api.SendE2E(m, params.GetDefaultE2E())
 	if err != nil {
-		return nil, err
+		return nil, errors.New(fmt.Sprintf("Failed SendE2E: %+v", err))
 	}
 
 	sr := SendReport{
-		rl:  &roundList{list: rids},
+		rl:  &RoundList{list: rids},
 		mid: mid,
 	}
 
 	return &sr, nil
 }
 
+// the send report is the mechanisim by which sendE2E returns a single
 type SendReport struct {
-	rl  RoundList
+	rl  *RoundList
 	mid e2e.MessageID
 }
 
-func (sr *SendReport) GetRoundList() RoundList {
+func (sr *SendReport) GetRoundList() *RoundList {
 	return sr.rl
 }
 
 func (sr *SendReport) GetMessageID() []byte {
 	return sr.mid[:]
+}
+
+func (sr *SendReport) Marshal() ([]byte, error) {
+	return json.Marshal(sr)
 }
\ No newline at end of file
diff --git a/bindings/user.go b/bindings/user.go
new file mode 100644
index 0000000000000000000000000000000000000000..e006f0c1e20d7f0a6055cd0d5612ee57e719a3a8
--- /dev/null
+++ b/bindings/user.go
@@ -0,0 +1,51 @@
+package bindings
+
+import (
+	"gitlab.com/elixxir/client/interfaces/user"
+	"gitlab.com/xx_network/crypto/signature/rsa"
+)
+
+type User struct {
+	u *user.User
+}
+
+func (u *User) GetID() []byte {
+	return u.u.ID.Marshal()
+}
+
+func (u *User) GetSalt() []byte {
+	return u.u.Salt
+}
+
+func (u *User) GetRSAPrivateKeyPem() []byte {
+	return rsa.CreatePrivateKeyPem(u.u.RSA)
+}
+
+func (u *User) GetRSAPublicKeyPem() []byte {
+	return rsa.CreatePublicKeyPem(u.u.RSA.GetPublic())
+}
+
+func (u *User) IsPrecanned() bool {
+	return u.u.Precanned
+}
+
+func (u *User) GetCmixDhPrivateKey() []byte {
+	return u.u.CmixDhPrivateKey.Bytes()
+}
+
+func (u *User) GetCmixDhPublicKey() []byte {
+	return u.u.CmixDhPublicKey.Bytes()
+}
+
+func (u *User) GetE2EDhPrivateKey() []byte {
+	return u.u.E2eDhPrivateKey.Bytes()
+}
+
+func (u *User) GetE2EDhPublicKey() []byte {
+	return u.u.E2eDhPublicKey.Bytes()
+}
+
+func (u *User) GetContact() *Contact {
+	c := u.u.GetContact()
+	return &Contact{c: &c}
+}
diff --git a/interfaces/bind/contact.go b/interfaces/bind/contact.go
deleted file mode 100644
index e02edc37e4eb25e5dc8990ef25db13931e0c5742..0000000000000000000000000000000000000000
--- a/interfaces/bind/contact.go
+++ /dev/null
@@ -1,20 +0,0 @@
-package bind
-
-type Contact interface {
-	GetID() []byte
-	GetDHPublicKey() []byte
-	GetOwnershipProof() []byte
-	GetFactList() FactList
-	Marshal() ([]byte, error)
-}
-
-type FactList interface {
-	Num() int
-	Get(int) Fact
-	Add(string, int) error
-}
-
-type Fact interface {
-	Get() string
-	Type() int
-}
diff --git a/interfaces/contact/contact.go b/interfaces/contact/contact.go
index 1d6d84b304a80a1733ddb37857ec67dd4d71581b..2579f7a0501c1e6633c81fe2a8f147b6ab73b024 100644
--- a/interfaces/contact/contact.go
+++ b/interfaces/contact/contact.go
@@ -3,11 +3,8 @@ package contact
 import (
 	"encoding/json"
 	"github.com/pkg/errors"
-	"gitlab.com/elixxir/client/interfaces/bind"
 	"gitlab.com/elixxir/crypto/cyclic"
 	"gitlab.com/xx_network/primitives/id"
-	"strings"
-	jww "github.com/spf13/jwalterweatherman"
 )
 
 const factDelimiter = ","
@@ -21,45 +18,13 @@ type Contact struct {
 	ID             *id.ID
 	DhPubKey       *cyclic.Int
 	OwnershipProof []byte
-	Facts          []Fact
+	Facts          FactList
 }
 
-// GetID returns the user ID for this user.
-func (c Contact) GetID() []byte {
-	return c.ID.Bytes()
-}
-
-// GetDHPublicKey returns the public key associated with the Contact.
-func (c Contact) GetDHPublicKey() []byte {
-	return c.DhPubKey.Bytes()
-}
-
-// GetDHPublicKey returns hash of a DH proof of key ownership.
-func (c Contact) GetOwnershipProof() []byte {
-	return c.OwnershipProof
-}
-
-// Returns a fact list for adding and getting facts to and from the contact
-func (c Contact) GetFactList() bind.FactList {
-	return factList{source: &c}
-}
-
-// json marshals the contact
 func (c Contact) Marshal() ([]byte, error) {
 	return json.Marshal(&c)
 }
 
-// converts facts to a delineated string with an ending character for transfer
-// over the network
-func (c Contact) StringifyFacts() string {
-	stringList := make([]string, len(c.Facts))
-	for index, f := range c.Facts {
-		stringList[index] = f.Stringify()
-	}
-
-	return strings.Join(stringList, factDelimiter) + factBreak
-}
-
 func Unmarshal(b []byte) (Contact, error) {
 	c := Contact{}
 	err := json.Unmarshal(b, &c)
@@ -73,27 +38,4 @@ func Unmarshal(b []byte) (Contact, error) {
 		}
 	}
 	return c, nil
-}
-
-// splits the "facts" portion of the payload from the rest and returns them as
-// facts
-func UnstringifyFacts(s string) ([]Fact, string, error) {
-	parts := strings.SplitN(s, factBreak, 1)
-	if len(parts) != 2 {
-		return nil, "", errors.New("Invalid fact string passed")
-	}
-	factStrings := strings.Split(parts[0], factDelimiter)
-
-	var factList []Fact
-	for _, fString := range factStrings {
-		fact, err := UnstringifyFact(fString)
-		if err != nil {
-			jww.WARN.Printf("Fact failed to unstringify, dropped: %s",
-				err)
-		} else {
-			factList = append(factList, fact)
-		}
-
-	}
-	return factList, parts[1], nil
-}
+}
\ No newline at end of file
diff --git a/interfaces/contact/fact.go b/interfaces/contact/fact.go
index 298b80b2ac68036374feb33a0b65e192a62574f4..bc838160dc33f6952d9b21ab6de8af2fb5c03cad 100644
--- a/interfaces/contact/fact.go
+++ b/interfaces/contact/fact.go
@@ -13,14 +13,6 @@ func NewFact(ft FactType, fact string) (Fact, error) {
 	}, nil
 }
 
-func (f Fact) Get() string {
-	return f.Fact
-}
-
-func (f Fact) Type() int {
-	return int(f.T)
-}
-
 // marshal is for transmission for UDB, not a part of the fact interface
 func (f Fact) Stringify() string {
 	return f.T.Stringify() + f.Fact
diff --git a/interfaces/contact/factList.go b/interfaces/contact/factList.go
index 6df341c1f96ad637d10303f6835a2e698a3b3464..7db95d0c51eb2ed6a5b46fdef3aba85b9f1d7ede 100644
--- a/interfaces/contact/factList.go
+++ b/interfaces/contact/factList.go
@@ -2,31 +2,40 @@ package contact
 
 import (
 	"github.com/pkg/errors"
-	"gitlab.com/elixxir/client/interfaces/bind"
+	"strings"
+	jww "github.com/spf13/jwalterweatherman"
 )
 
-type factList struct {
-	source *Contact
-}
+type FactList []Fact
 
-func (fl factList) Num() int {
-	return len(fl.source.Facts)
-}
+func (fl FactList) Stringify() string {
+	stringList := make([]string, len(fl))
+	for index, f := range fl {
+		stringList[index] = f.Stringify()
+	}
 
-func (fl factList) Get(i int) bind.Fact {
-	return fl.source.Facts[i]
+	return strings.Join(stringList, factDelimiter) + factBreak
 }
 
-func (fl factList) Add(fact string, factType int) error {
-	ft := FactType(factType)
-	if !ft.IsValid() {
-		return errors.New("Invalid fact type")
-	}
-	f, err := NewFact(ft, fact)
-	if err != nil {
-		return err
+// unstrignifys facts followed by a facts break and with arbatrary data
+// atttached at the end
+func UnstringifyFactList(s string) ([]Fact, string, error) {
+	parts := strings.SplitN(s, factBreak, 1)
+	if len(parts) != 2 {
+		return nil, "", errors.New("Invalid fact string passed")
 	}
+	factStrings := strings.Split(parts[0], factDelimiter)
 
-	fl.source.Facts = append(fl.source.Facts, f)
-	return nil
-}
+	var factList []Fact
+	for _, fString := range factStrings {
+		fact, err := UnstringifyFact(fString)
+		if err != nil {
+			jww.WARN.Printf("Fact failed to unstringify, dropped: %s",
+				err)
+		} else {
+			factList = append(factList, fact)
+		}
+
+	}
+	return factList, parts[1], nil
+}
\ No newline at end of file
diff --git a/interfaces/user/user.go b/interfaces/user/user.go
index c5d2018567f68ad795c053fdac554f3411563ec1..a4fdb7d86e6e6f82ed4b5572bf70d7f379554836 100644
--- a/interfaces/user/user.go
+++ b/interfaces/user/user.go
@@ -1,7 +1,6 @@
 package user
 
 import (
-	"gitlab.com/elixxir/client/interfaces/bind"
 	"gitlab.com/elixxir/client/interfaces/contact"
 	"gitlab.com/elixxir/crypto/cyclic"
 	"gitlab.com/xx_network/crypto/signature/rsa"
@@ -24,46 +23,10 @@ type User struct {
 	E2eDhPublicKey  *cyclic.Int
 }
 
-func (u *User) GetID() []byte {
-	return u.ID.Marshal()
-}
-
-func (u *User) GetSalt() []byte {
-	return u.Salt
-}
-
-func (u *User) GetRSAPrivateKeyPem() []byte {
-	return rsa.CreatePrivateKeyPem(u.RSA)
-}
-
-func (u *User) GetRSAPublicKeyPem() []byte {
-	return rsa.CreatePublicKeyPem(u.RSA.GetPublic())
-}
-
-func (u *User) IsPrecanned() bool {
-	return u.Precanned
-}
-
-func (u *User) GetCmixDhPrivateKey() []byte {
-	return u.CmixDhPrivateKey.Bytes()
-}
-
-func (u *User) GetCmixDhPublicKey() []byte {
-	return u.CmixDhPublicKey.Bytes()
-}
-
-func (u *User) GetE2EDhPrivateKey() []byte {
-	return u.E2eDhPrivateKey.Bytes()
-}
-
-func (u *User) GetE2EDhPublicKey() []byte {
-	return u.E2eDhPublicKey.Bytes()
-}
-
-func (u *User) GetContact() bind.Contact {
+func (u *User) GetContact() contact.Contact {
 	return contact.Contact{
 		ID:       u.ID.DeepCopy(),
 		DhPubKey: u.E2eDhPublicKey,
 		Facts:    make([]contact.Fact, 0),
 	}
-}
+}
\ No newline at end of file