diff --git a/api/send.go b/api/send.go
index 5ef62966daf88579091196898ce4e661583696e3..28b8435425b8941290581342ee54838a8de27eda 100644
--- a/api/send.go
+++ b/api/send.go
@@ -16,6 +16,7 @@ import (
 	"gitlab.com/elixxir/primitives/format"
 	"gitlab.com/xx_network/primitives/id"
 	"gitlab.com/xx_network/primitives/id/ephemeral"
+	"time"
 )
 
 //This holds all functions to send messages over the network
@@ -24,7 +25,7 @@ import (
 // the provided msgType. Returns the list of rounds in which parts of
 // the message were sent or an error if it fails.
 func (c *Client) SendE2E(m message.Send, param params.E2E) ([]id.Round,
-	e2e.MessageID, error) {
+	e2e.MessageID, time.Time, error) {
 	jww.INFO.Printf("SendE2E(%s, %d. %v)", m.Recipient,
 		m.MessageType, m.Payload)
 	return c.network.SendE2E(m, param, nil)
diff --git a/api/utilsInterfaces_test.go b/api/utilsInterfaces_test.go
index ad97286b779237335a1e9b14f2606266d97ad3cf..e421ffdc9aa20bd5c8ce89b1a7dea24432e7f9d9 100644
--- a/api/utilsInterfaces_test.go
+++ b/api/utilsInterfaces_test.go
@@ -20,6 +20,7 @@ import (
 	"gitlab.com/xx_network/comms/connect"
 	"gitlab.com/xx_network/primitives/id"
 	"gitlab.com/xx_network/primitives/id/ephemeral"
+	"time"
 )
 
 // Mock comm struct which returns no historical round data
@@ -94,9 +95,9 @@ func (t *testNetworkManagerGeneric) CheckGarbledMessages() {
 	return
 }
 func (t *testNetworkManagerGeneric) SendE2E(message.Send, params.E2E, *stoppable.Single) (
-	[]id.Round, cE2e.MessageID, error) {
+	[]id.Round, cE2e.MessageID, time.Time, error) {
 	rounds := []id.Round{id.Round(0), id.Round(1), id.Round(2)}
-	return rounds, cE2e.MessageID{}, nil
+	return rounds, cE2e.MessageID{}, time.Time{}, nil
 
 }
 func (t *testNetworkManagerGeneric) SendUnsafe(m message.Send, p params.Unsafe) ([]id.Round, error) {
diff --git a/bindings/message.go b/bindings/message.go
index 44526fa2e3756868e1b895452d1484f1ff4366fa..680d9caf778d8d8ceb700b0a3d3ad2b8b6b20d4b 100644
--- a/bindings/message.go
+++ b/bindings/message.go
@@ -40,7 +40,7 @@ func (m *Message) GetMessageType() int {
 // GetTimestampMS returns the message's timestamp in milliseconds
 func (m *Message) GetTimestampMS() int64 {
 	ts := m.r.Timestamp.UnixNano()
-	ts = (ts + 999999) / 1000000
+	ts = (ts + 500000) / 1000000
 	return ts
 }
 
diff --git a/bindings/send.go b/bindings/send.go
index 586100d051b0f4f0248b235630111476b87b930f..cef9c99500772b54012dcf07f6b4d3aaea5628a8 100644
--- a/bindings/send.go
+++ b/bindings/send.go
@@ -15,6 +15,7 @@ import (
 	"gitlab.com/elixxir/client/interfaces/params"
 	"gitlab.com/elixxir/crypto/e2e"
 	"gitlab.com/xx_network/primitives/id"
+	"time"
 )
 
 // SendCMIX sends a "raw" CMIX message payload to the provided
@@ -163,7 +164,7 @@ func (c *Client) SendE2E(recipient, payload []byte, messageType int, parameters
 		MessageType: message.Type(messageType),
 	}
 
-	rids, mid, err := c.api.SendE2E(m, p)
+	rids, mid, ts, err := c.api.SendE2E(m, p)
 	if err != nil {
 		return nil, errors.New(fmt.Sprintf("Failed SendE2E: %+v", err))
 	}
@@ -171,6 +172,7 @@ func (c *Client) SendE2E(recipient, payload []byte, messageType int, parameters
 	sr := SendReport{
 		rl:  &RoundList{list: rids},
 		mid: mid,
+		ts:  ts,
 	}
 
 	return &sr, nil
@@ -180,6 +182,7 @@ func (c *Client) SendE2E(recipient, payload []byte, messageType int, parameters
 type SendReport struct {
 	rl  *RoundList
 	mid e2e.MessageID
+	ts  time.Time
 }
 
 type SendReportDisk struct {
@@ -195,6 +198,18 @@ func (sr *SendReport) GetMessageID() []byte {
 	return sr.mid[:]
 }
 
+// GetTimestampMS returns the message's timestamp in milliseconds
+func (sr *SendReport) GetTimestampMS() int64 {
+	ts := sr.ts.UnixNano()
+	ts = (ts + 500000) / 1000000
+	return ts
+}
+
+// GetTimestampNano returns the message's timestamp in nanoseconds
+func (sr *SendReport) GetTimestampNano() int64 {
+	return sr.ts.UnixNano()
+}
+
 func (sr *SendReport) Marshal() ([]byte, error) {
 	srd := SendReportDisk{
 		List: sr.rl.list,
diff --git a/cmd/root.go b/cmd/root.go
index 9ebdc637ac86440f250319c0db384eb16632fda3..41cd73e10c7b68e224776771c31e8cfb1323fbe7 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -198,7 +198,7 @@ var rootCmd = &cobra.Command{
 					paramsUnsafe)
 				roundTimeout = paramsUnsafe.Timeout
 			} else {
-				roundIDs, _, err = client.SendE2E(msg,
+				roundIDs, _, _, err = client.SendE2E(msg,
 					paramsE2E)
 				roundTimeout = paramsE2E.Timeout
 			}
diff --git a/groupChat/sendRequests.go b/groupChat/sendRequests.go
index 3e4cc39f2995dbe870b4caa771cbd3a075c77eb7..70c5501ec7c6492a1b33f5a5309b2602c38ad06e 100644
--- a/groupChat/sendRequests.go
+++ b/groupChat/sendRequests.go
@@ -110,7 +110,7 @@ func (m Manager) sendRequest(memberID *id.ID, request []byte) ([]id.Round, error
 		MessageType: message.GroupCreationRequest,
 	}
 
-	rounds, _, err := m.net.SendE2E(sendMsg, params.GetDefaultE2E(), nil)
+	rounds, _, _, err := m.net.SendE2E(sendMsg, params.GetDefaultE2E(), nil)
 	if err != nil {
 		return nil, errors.Errorf(sendE2eErr, memberID, err)
 	}
diff --git a/groupChat/utils_test.go b/groupChat/utils_test.go
index bdf58edfa1a3e2070c2d6144411463a6740c97a0..4997976c643c3d90de630309daee335c503c63b0 100644
--- a/groupChat/utils_test.go
+++ b/groupChat/utils_test.go
@@ -36,6 +36,7 @@ import (
 	"math/rand"
 	"sync"
 	"testing"
+	"time"
 )
 
 // newTestManager creates a new Manager for testing.
@@ -240,20 +241,20 @@ func (tnm *testNetworkManager) GetE2eMsg(i int) message.Send {
 	return tnm.e2eMessages[i]
 }
 
-func (tnm *testNetworkManager) SendE2E(msg message.Send, _ params.E2E, _ *stoppable.Single) ([]id.Round, e2e.MessageID, error) {
+func (tnm *testNetworkManager) SendE2E(msg message.Send, _ params.E2E, _ *stoppable.Single) ([]id.Round, e2e.MessageID, time.Time, error) {
 	tnm.Lock()
 	defer tnm.Unlock()
 
 	tnm.errSkip++
 	if tnm.sendErr == 1 {
-		return nil, e2e.MessageID{}, errors.New("SendE2E error")
+		return nil, e2e.MessageID{}, time.Time{}, errors.New("SendE2E error")
 	} else if tnm.sendErr == 2 && tnm.errSkip%2 == 0 {
-		return nil, e2e.MessageID{}, errors.New("SendE2E error")
+		return nil, e2e.MessageID{}, time.Time{}, errors.New("SendE2E error")
 	}
 
 	tnm.e2eMessages = append(tnm.e2eMessages, msg)
 
-	return []id.Round{0, 1, 2, 3}, e2e.MessageID{}, nil
+	return []id.Round{0, 1, 2, 3}, e2e.MessageID{}, time.Time{}, nil
 }
 
 func (tnm *testNetworkManager) SendUnsafe(message.Send, params.Unsafe) ([]id.Round, error) {
diff --git a/interfaces/networkManager.go b/interfaces/networkManager.go
index c3bc9f49d6994012f0f2cbc58ed0016b62180f59..3e40b9baea140a99fb615362ec50ee02c6a09f5d 100644
--- a/interfaces/networkManager.go
+++ b/interfaces/networkManager.go
@@ -17,11 +17,12 @@ import (
 	"gitlab.com/elixxir/primitives/format"
 	"gitlab.com/xx_network/primitives/id"
 	"gitlab.com/xx_network/primitives/id/ephemeral"
+	"time"
 )
 
 type NetworkManager interface {
 	// The stoppable can be nil.
-	SendE2E(m message.Send, p params.E2E, stop *stoppable.Single) ([]id.Round, e2e.MessageID, error)
+	SendE2E(m message.Send, p params.E2E, stop *stoppable.Single) ([]id.Round, e2e.MessageID, time.Time, error)
 	SendUnsafe(m message.Send, p params.Unsafe) ([]id.Round, error)
 	SendCMIX(message format.Message, recipient *id.ID, p params.CMIX) (id.Round, ephemeral.Id, error)
 	SendManyCMIX(messages map[id.ID]format.Message, p params.CMIX) (id.Round, []ephemeral.Id, error)
@@ -50,4 +51,4 @@ type NetworkManager interface {
 }
 
 //for use in key exchange which needs to be callable inside of network
-type SendE2E func(m message.Send, p params.E2E, stop *stoppable.Single) ([]id.Round, e2e.MessageID, error)
+type SendE2E func(m message.Send, p params.E2E, stop *stoppable.Single) ([]id.Round, e2e.MessageID, time.Time, error)
diff --git a/keyExchange/rekey.go b/keyExchange/rekey.go
index f4caacd2586bd7a8c0c8c296ba7f8ae19377db4f..5acc9ba71f383b5e8ae15966421ecd227ed7f6e7 100644
--- a/keyExchange/rekey.go
+++ b/keyExchange/rekey.go
@@ -104,7 +104,7 @@ func negotiate(instance *network.Instance, sendE2E interfaces.SendE2E,
 	e2eParams := params.GetDefaultE2E()
 	e2eParams.Type = params.KeyExchange
 
-	rounds, _, err := sendE2E(m, e2eParams, stop)
+	rounds, _, _, err := sendE2E(m, e2eParams, stop)
 	// If the send fails, returns the error so it can be handled. The caller
 	// should ensure the calling session is in a state where the Rekey will
 	// be triggered next time a key is used
diff --git a/keyExchange/trigger.go b/keyExchange/trigger.go
index c88d068fe8d1463ea4c2b5408dd9b18c4030e488..e25da821f9a3485969608bd320a7f22534622255 100644
--- a/keyExchange/trigger.go
+++ b/keyExchange/trigger.go
@@ -127,7 +127,7 @@ func handleTrigger(sess *storage.Session, net interfaces.NetworkManager,
 	// send fails
 	sess.GetCriticalMessages().AddProcessing(m, e2eParams)
 
-	rounds, _, err := net.SendE2E(m, e2eParams, stop)
+	rounds, _, _, err := net.SendE2E(m, e2eParams, stop)
 	if err != nil {
 		return err
 	}
diff --git a/keyExchange/utils_test.go b/keyExchange/utils_test.go
index cb0518466f10c4737fcc2376ce38ddfaeb318225..d844f16b46bf90b026d6ede34b743432939e03c2 100644
--- a/keyExchange/utils_test.go
+++ b/keyExchange/utils_test.go
@@ -31,6 +31,7 @@ import (
 	"gitlab.com/xx_network/primitives/ndf"
 	"gitlab.com/xx_network/primitives/netTime"
 	"testing"
+	"time"
 )
 
 // Generate partner ID for two people, used for smoke tests
@@ -67,9 +68,9 @@ func (t *testNetworkManagerGeneric) CheckGarbledMessages() {
 }
 
 func (t *testNetworkManagerGeneric) SendE2E(message.Send, params.E2E, *stoppable.Single) (
-	[]id.Round, cE2e.MessageID, error) {
+	[]id.Round, cE2e.MessageID, time.Time, error) {
 	rounds := []id.Round{id.Round(0), id.Round(1), id.Round(2)}
-	return rounds, cE2e.MessageID{}, nil
+	return rounds, cE2e.MessageID{}, time.Time{}, nil
 
 }
 
@@ -169,7 +170,7 @@ func (t *testNetworkManagerFullExchange) CheckGarbledMessages() {
 // Intended for alice to send to bob. Trigger's Bob's confirmation, chaining the operation
 // together
 func (t *testNetworkManagerFullExchange) SendE2E(message.Send, params.E2E, *stoppable.Single) (
-	[]id.Round, cE2e.MessageID, error) {
+	[]id.Round, cE2e.MessageID, time.Time, error) {
 
 	rounds := []id.Round{id.Round(0), id.Round(1), id.Round(2)}
 	alicePrivKey := aliceSession.E2e().GetDHPrivateKey()
@@ -193,7 +194,7 @@ func (t *testNetworkManagerFullExchange) SendE2E(message.Send, params.E2E, *stop
 
 	bobSwitchboard.Speak(confirmMessage)
 
-	return rounds, cE2e.MessageID{}, nil
+	return rounds, cE2e.MessageID{}, time.Time{}, nil
 }
 
 func (t *testNetworkManagerFullExchange) SendUnsafe(m message.Send, p params.Unsafe) ([]id.Round, error) {
diff --git a/network/ephemeral/testutil.go b/network/ephemeral/testutil.go
index 3b443dfe3a85f8c85e92dd235b190e00171df3ef..c5cbd8b7c03861888392f9a4b8077b0cf49fb72d 100644
--- a/network/ephemeral/testutil.go
+++ b/network/ephemeral/testutil.go
@@ -10,6 +10,7 @@ package ephemeral
 import (
 	"gitlab.com/elixxir/client/network/gateway"
 	"testing"
+	"time"
 
 	jww "github.com/spf13/jwalterweatherman"
 	"gitlab.com/elixxir/client/interfaces"
@@ -34,7 +35,7 @@ type testNetworkManager struct {
 }
 
 func (t *testNetworkManager) SendE2E(m message.Send, _ params.E2E, _ *stoppable.Single) ([]id.Round,
-	e2e.MessageID, error) {
+	e2e.MessageID, time.Time, error) {
 	rounds := []id.Round{
 		id.Round(0),
 		id.Round(1),
@@ -43,7 +44,7 @@ func (t *testNetworkManager) SendE2E(m message.Send, _ params.E2E, _ *stoppable.
 
 	t.msg = m
 
-	return rounds, e2e.MessageID{}, nil
+	return rounds, e2e.MessageID{}, time.Time{}, nil
 }
 
 func (t *testNetworkManager) SendUnsafe(m message.Send, _ params.Unsafe) ([]id.Round, error) {
diff --git a/network/message/critical.go b/network/message/critical.go
index 84b88da602ac8fb87a1562d25ab8a52c6f1c23ed..9c5b6bff7c824a925c969459ddb683e38a1faa1d 100644
--- a/network/message/critical.go
+++ b/network/message/critical.go
@@ -54,7 +54,7 @@ func (m *Manager) criticalMessages(stop *stoppable.Single) {
 			jww.INFO.Printf("Resending critical message to %s ",
 				msg.Recipient)
 			//send the message
-			rounds, _, err := m.SendE2E(msg, param, stop)
+			rounds, _, _, err := m.SendE2E(msg, param, stop)
 			//if the message fail to send, notify the buffer so it can be handled
 			//in the future and exit
 			if err != nil {
diff --git a/network/message/sendE2E.go b/network/message/sendE2E.go
index 7b468ad1a30c818396d631b4b9f85b5945dd88ab..e26dcb6de4ee21a8a72bcebf2dbf7ea26220453d 100644
--- a/network/message/sendE2E.go
+++ b/network/message/sendE2E.go
@@ -23,9 +23,9 @@ import (
 )
 
 func (m *Manager) SendE2E(msg message.Send, param params.E2E,
-	stop *stoppable.Single) ([]id.Round, e2e.MessageID, error) {
+	stop *stoppable.Single) ([]id.Round, e2e.MessageID, time.Time, error) {
 	if msg.MessageType == message.Raw {
-		return nil, e2e.MessageID{}, errors.Errorf("Raw (%d) is a reserved "+
+		return nil, e2e.MessageID{}, time.Time{}, errors.Errorf("Raw (%d) is a reserved "+
 			"message type", msg.MessageType)
 	}
 	//timestamp the message
@@ -35,7 +35,7 @@ func (m *Manager) SendE2E(msg message.Send, param params.E2E,
 	partitions, internalMsgId, err := m.partitioner.Partition(msg.Recipient, msg.MessageType, ts,
 		msg.Payload)
 	if err != nil {
-		return nil, e2e.MessageID{}, errors.WithMessage(err, "failed to send unsafe message")
+		return nil, e2e.MessageID{}, time.Time{}, errors.WithMessage(err, "failed to send unsafe message")
 	}
 
 	//encrypt then send the partitions over cmix
@@ -45,7 +45,7 @@ func (m *Manager) SendE2E(msg message.Send, param params.E2E,
 	// get the key manager for the partner
 	partner, err := m.Session.E2e().GetPartner(msg.Recipient)
 	if err != nil {
-		return nil, e2e.MessageID{}, errors.WithMessagef(err,
+		return nil, e2e.MessageID{}, time.Time{}, errors.WithMessagef(err,
 			"Could not send End to End encrypted "+
 				"message, no relationship found with %s", msg.Recipient)
 	}
@@ -83,7 +83,7 @@ func (m *Manager) SendE2E(msg message.Send, param params.E2E,
 			key, err = partner.GetKeyForSending(param.Type)
 		}
 		if err != nil {
-			return nil, e2e.MessageID{}, errors.WithMessagef(err,
+			return nil, e2e.MessageID{}, time.Time{}, errors.WithMessagef(err,
 				"Failed to get key for end to end encryption")
 		}
 
@@ -113,7 +113,7 @@ func (m *Manager) SendE2E(msg message.Send, param params.E2E,
 	if numFail > 0 {
 		jww.INFO.Printf("Failed to E2E send %d/%d to %s",
 			numFail, len(partitions), msg.Recipient)
-		return nil, e2e.MessageID{}, errors.Errorf("Failed to E2E send %v/%v sub payloads:"+
+		return nil, e2e.MessageID{}, time.Time{}, errors.Errorf("Failed to E2E send %v/%v sub payloads:"+
 			" %s", numFail, len(partitions), errRtn)
 	} else {
 		jww.INFO.Printf("Successfully E2E sent %d/%d to %s",
@@ -122,5 +122,5 @@ func (m *Manager) SendE2E(msg message.Send, param params.E2E,
 
 	//return the rounds if everything send successfully
 	msgID := e2e.NewMessageID(partner.GetSendRelationshipFingerprint(), internalMsgId)
-	return roundIds, msgID, nil
+	return roundIds, msgID, ts, nil
 }
diff --git a/network/send.go b/network/send.go
index d54e478c7c705f4995c451b1e302e5ae77d292f7..8fff3ac152e65a55822d6e824aba7f7f6d4f09eb 100644
--- a/network/send.go
+++ b/network/send.go
@@ -17,6 +17,7 @@ import (
 	"gitlab.com/elixxir/primitives/format"
 	"gitlab.com/xx_network/primitives/id"
 	"gitlab.com/xx_network/primitives/id/ephemeral"
+	"time"
 )
 
 // SendCMIX sends a "raw" CMIX message payload to the provided
@@ -63,10 +64,10 @@ func (m *manager) SendUnsafe(msg message.Send, param params.Unsafe) ([]id.Round,
 // the provided msgType. Returns the list of rounds in which parts of
 // the message were sent or an error if it fails.
 func (m *manager) SendE2E(msg message.Send, e2eP params.E2E, stop *stoppable.Single) (
-	[]id.Round, e2e.MessageID, error) {
+	[]id.Round, e2e.MessageID, time.Time, error) {
 
 	if !m.Health.IsHealthy() {
-		return nil, e2e.MessageID{}, errors.New("Cannot send e2e " +
+		return nil, e2e.MessageID{}, time.Time{}, errors.New("Cannot send e2e " +
 			"message when the network is not healthy")
 	}
 
diff --git a/single/manager_test.go b/single/manager_test.go
index 1a62edf8405d450a82688e05a1e7b04af3f5ef06..a787e7462870d0f3cda30a5a31b3a89a92c3a1f3 100644
--- a/single/manager_test.go
+++ b/single/manager_test.go
@@ -283,8 +283,8 @@ func (tnm *testNetworkManager) GetMsg(i int) format.Message {
 	return tnm.msgs[i]
 }
 
-func (tnm *testNetworkManager) SendE2E(message.Send, params.E2E, *stoppable.Single) ([]id.Round, e2e.MessageID, error) {
-	return nil, e2e.MessageID{}, nil
+func (tnm *testNetworkManager) SendE2E(message.Send, params.E2E, *stoppable.Single) ([]id.Round, e2e.MessageID, time.Time, error) {
+	return nil, e2e.MessageID{}, time.Time{}, nil
 }
 
 func (tnm *testNetworkManager) SendUnsafe(_ message.Send, _ params.Unsafe) ([]id.Round, error) {