diff --git a/bindings/broadcast.go b/bindings/broadcast.go
index 9dc521d03a88ecb523c7f2aaf9f911e144f10aa4..97def13f6a1f337a8de6518c50eb7f72d7699468 100644
--- a/bindings/broadcast.go
+++ b/bindings/broadcast.go
@@ -44,9 +44,11 @@ type ChannelDef struct {
 
 // BroadcastMessage is the bindings representation of a broadcast message.
 //
-// Example JSON:
-//  {"RoundID":42,
+// BroadcastMessage Example JSON:
+//  {
+// 	 "RoundID":42,
 //   "EphID":[0,0,0,0,0,0,24,61],
+//   "RoundURL":"https://dashboard.xx.network/rounds/25?xxmessenger=true",
 //   "Payload":"SGVsbG8sIGJyb2FkY2FzdCBmcmllbmRzIQ=="
 //  }
 type BroadcastMessage struct {
@@ -57,13 +59,16 @@ type BroadcastMessage struct {
 // BroadcastReport is the bindings representation of the info on how a broadcast
 // message was sent
 //
-// Example JSON:
-//  {"RoundID":42,
-//   "EphID":[0,0,0,0,0,0,24,61]
+// BroadcastReport Example JSON:
+//  {
+//	 "Rounds": [25, 26, 29],
+//   "EphID":[0,0,0,0,0,0,24,61],
+//   "RoundURL":"https://dashboard.xx.network/rounds/25?xxmessenger=true"
 //  }
 type BroadcastReport struct {
 	RoundsList
-	EphID ephemeral.Id
+	RoundURL string
+	EphID    ephemeral.Id
 }
 
 // BroadcastListener is the public function type bindings can use to listen for
@@ -131,6 +136,7 @@ func (c *Channel) Listen(l BroadcastListener, method int) error {
 		l.Callback(json.Marshal(&BroadcastMessage{
 			BroadcastReport: BroadcastReport{
 				RoundsList: makeRoundsList(round.ID),
+				RoundURL:   getRoundURL(round.ID),
 				EphID:      receptionID.EphId,
 			},
 			Payload: payload,
@@ -152,6 +158,7 @@ func (c *Channel) Broadcast(payload []byte) ([]byte, error) {
 		return nil, err
 	}
 	return json.Marshal(BroadcastReport{
+		RoundURL:   getRoundURL(rid),
 		RoundsList: makeRoundsList(rid.ID),
 		EphID:      eid,
 	})
@@ -174,6 +181,7 @@ func (c *Channel) BroadcastAsymmetric(payload, pk []byte) ([]byte, error) {
 	}
 	return json.Marshal(BroadcastReport{
 		RoundsList: makeRoundsList(rid.ID),
+		RoundURL:   getRoundURL(rid),
 		EphID:      eid,
 	})
 }
diff --git a/bindings/connect.go b/bindings/connect.go
index faaffc1956afc88ef17762cf52bd22fc09ae737e..df3d4ae46c7f7c0a016ecd75fb576e0e48c98e87 100644
--- a/bindings/connect.go
+++ b/bindings/connect.go
@@ -94,6 +94,7 @@ func (c *Connection) SendE2E(mt int, payload []byte) ([]byte, error) {
 
 	sr := E2ESendReport{
 		RoundsList: makeRoundsList(sendReport.RoundList...),
+		RoundURL:   getRoundURL(sendReport.RoundList[0]),
 		MessageID:  sendReport.MessageId.Marshal(),
 		Timestamp:  sendReport.SentTime.UnixNano(),
 		KeyResidue: sendReport.KeyResidue.Marshal(),
diff --git a/bindings/delivery.go b/bindings/delivery.go
index 89521d887175367d6fd40966363b8e12a7fbd89a..6420196d4e16f34edae4510cb7d1d228f7e0b2d2 100644
--- a/bindings/delivery.go
+++ b/bindings/delivery.go
@@ -9,6 +9,7 @@ package bindings
 
 import (
 	"encoding/json"
+	"fmt"
 	"time"
 
 	"github.com/pkg/errors"
@@ -17,9 +18,33 @@ import (
 	"gitlab.com/xx_network/primitives/id"
 )
 
+// dashboardBaseURL is the base of the xx network's round dashboard URL.
+// This should be used by any type of send report's GetRoundURL method.
+var dashboardBaseURL = "https://dashboard.xx.network"
+
+// SetDashboardURL is a function which modifies the base dashboard URL
+// that is returned as part of any send report. Internally, this is defaulted
+// to "https://dashboard.xx.network". This should only be called if the user
+// explicitly wants to modify the dashboard URL. This function is not
+// thread-safe, and as such should only be called on setup.
+//
+// Parameters:
+//  - newURL - A valid URL that will be used for round look up on any send
+//    report.
+func SetDashboardURL(newURL string) {
+	dashboardBaseURL = newURL
+}
+
+// getRoundURL is a helper function which returns the specific round
+// within any type of send report, if they have a round in their RoundsList.
+// This helper function is messenger specific.
+func getRoundURL(round id.Round) string {
+	return fmt.Sprintf("%s/rounds/%d?xxmessenger=true", dashboardBaseURL, round)
+}
+
 // RoundsList contains a list of round IDs.
 //
-// Example marshalled roundList object:
+// JSON Example:
 //  [1001,1003,1006]
 type RoundsList struct {
 	Rounds []uint64
diff --git a/bindings/e2eHandler.go b/bindings/e2eHandler.go
index 3eeffdd546b2acdb8934c485ed76b8c7b6dcda08..4b63407520f8e1aa756f2e749e4b0971fc72fdd2 100644
--- a/bindings/e2eHandler.go
+++ b/bindings/e2eHandler.go
@@ -23,15 +23,17 @@ import (
 // E2ESendReport is the bindings' representation of the return values of
 // SendE2E.
 //
-// Example E2ESendReport:
-//{
-//"Rounds": [ 1, 4, 9],
-//"MessageID": "iM34yCIr4Je8ZIzL9iAAG1UWAeDiHybxMTioMAaezvs=",
-//"Timestamp": 1661532254302612000,
-//"KeyResidue": "9q2/A69EAuFM1hFAT7Bzy5uGOQ4T6bPFF72h5PlgCWE="
-//}
+// E2ESendReport Example JSON:
+//  {
+//		"Rounds": [ 1, 4, 9],
+//      "RoundURL":"https://dashboard.xx.network/rounds/25?xxmessenger=true",
+//		"MessageID": "iM34yCIr4Je8ZIzL9iAAG1UWAeDiHybxMTioMAaezvs=",
+//		"Timestamp": 1661532254302612000,
+//		"KeyResidue": "9q2/A69EAuFM1hFAT7Bzy5uGOQ4T6bPFF72h5PlgCWE="
+//  }
 type E2ESendReport struct {
 	RoundsList
+	RoundURL   string
 	MessageID  []byte
 	Timestamp  int64
 	KeyResidue []byte
@@ -160,6 +162,7 @@ func (e *E2e) SendE2E(messageType int, recipientId, payload,
 
 	result := E2ESendReport{
 		RoundsList: makeRoundsList(sendReport.RoundList...),
+		RoundURL:   getRoundURL(sendReport.RoundList[0]),
 		MessageID:  sendReport.MessageId.Marshal(),
 		Timestamp:  sendReport.SentTime.UnixNano(),
 		KeyResidue: sendReport.KeyResidue.Marshal(),
diff --git a/bindings/group.go b/bindings/group.go
index 6b2041bdb548f3d3f9ccb5b6758e1be45c28faca..7ecd29558fdb3aeeeb449b3635b43cee15516806 100644
--- a/bindings/group.go
+++ b/bindings/group.go
@@ -157,6 +157,7 @@ func (g *GroupChat) MakeGroup(
 	report := GroupReport{
 		Id:         grp.ID.Bytes(),
 		RoundsList: makeRoundsList(roundIDs...),
+		RoundURL:   getRoundURL(roundIDs[0]),
 		Status:     int(status),
 	}
 
@@ -199,6 +200,7 @@ func (g *GroupChat) ResendRequest(groupId []byte) ([]byte, error) {
 	report := &GroupReport{
 		Id:         grp.ID.Bytes(),
 		RoundsList: makeRoundsList(rnds...),
+		RoundURL:   getRoundURL(rnds[0]),
 		Status:     int(status),
 	}
 
@@ -269,6 +271,7 @@ func (g *GroupChat) Send(groupId, message []byte, tag string) ([]byte, error) {
 
 	// Construct send report
 	sendReport := &GroupSendReport{
+		RoundURL:   getRoundURL(round),
 		RoundsList: makeRoundsList(round.ID),
 		Timestamp:  timestamp.UnixNano(),
 		MessageID:  msgID.Bytes(),
@@ -407,6 +410,7 @@ type GroupRequest interface {
 }
 
 // GroupChatProcessor manages the handling of received group chat messages.
+// The decryptedMessage field will be a JSON marshalled GroupChatMessage.
 type GroupChatProcessor interface {
 	Process(decryptedMessage, msg, receptionId []byte, ephemeralId,
 		roundId int64, err error)
@@ -419,13 +423,53 @@ type groupChatProcessor struct {
 	bindingsCb GroupChatProcessor
 }
 
+// GroupChatMessage is the bindings layer representation of the
+// [groupChat.MessageReceive].
+//
+// GroupChatMessage Example JSON:
+//  {
+//    "GroupId": "AAAAAAAJlasAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE",
+//    "SenderId": "AAAAAAAAB8gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD",
+//    "MessageId": "Zm9ydHkgZml2ZQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
+//    "Payload": "Zm9ydHkgZml2ZQ==",
+//    "Timestamp": 1663009269474079000
+//  }
+type GroupChatMessage struct {
+	// GroupId is the ID of the group that this message was sent on.
+	GroupId []byte
+
+	// SenderId is the ID of the sender of this message.
+	SenderId []byte
+
+	// MessageId is the ID of this group message.
+	MessageId []byte
+
+	// Payload is the content of the message.
+	Payload []byte
+
+	// Timestamp is the time this message was sent on.
+	Timestamp int64
+}
+
+// convertMessageReceive is a helper function which converts a
+// [groupChat.MessageReceive] to the bindings-layer representation GroupChatMessage.
+func convertMessageReceive(decryptedMsg gc.MessageReceive) GroupChatMessage {
+	return GroupChatMessage{
+		GroupId:   decryptedMsg.GroupID.Bytes(),
+		SenderId:  decryptedMsg.SenderID.Bytes(),
+		MessageId: decryptedMsg.ID.Bytes(),
+		Payload:   decryptedMsg.Payload,
+		Timestamp: decryptedMsg.Timestamp.UnixNano(),
+	}
+}
+
 // convertProcessor turns the input of a groupChat.Processor to the
 // binding-layer primitives equivalents within the GroupChatProcessor.Process.
 func convertGroupChatProcessor(decryptedMsg gc.MessageReceive, msg format.Message,
 	receptionID receptionID.EphemeralIdentity, round rounds.Round) (
 	decryptedMessage, message, receptionId []byte, ephemeralId, roundId int64, err error) {
 
-	decryptedMessage, err = json.Marshal(decryptedMsg)
+	decryptedMessage, err = json.Marshal(convertMessageReceive(decryptedMsg))
 	message = msg.Marshal()
 	receptionId = receptionID.Source.Marshal()
 	ephemeralId = receptionID.EphId.Int64()
@@ -451,16 +495,34 @@ func (gcp *groupChatProcessor) String() string {
 // GroupReport is returned when creating a new group and contains the ID of
 // the group, a list of rounds that the group requests were sent on, and the
 // status of the send operation.
+//
+// Example GroupReport JSON:
+//		{
+//			"Id": "AAAAAAAAAM0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE",
+//			"Rounds": [25, 64],
+//			"RoundURL": "https://dashboard.xx.network/rounds/25?xxmessenger=true",
+//			"Status": 1
+//		}
 type GroupReport struct {
 	Id []byte
 	RoundsList
-	Status int
+	RoundURL string
+	Status   int
 }
 
 // GroupSendReport is returned when sending a group message. It contains the
 // round ID sent on and the timestamp of the send operation.
+//
+// Example GroupSendReport JSON:
+//      {
+//  	"Rounds": [25,	64],
+//  	"RoundURL": "https://dashboard.xx.network/rounds/25?xxmessenger=true",
+//  	"Timestamp": 1662577352813112000,
+//  	"MessageID": "69ug6FA50UT2q6MWH3hne9PkHQ+H9DnEDsBhc0m0Aww="
+//	    }
 type GroupSendReport struct {
 	RoundsList
+	RoundURL  string
 	Timestamp int64
 	MessageID []byte
 }
diff --git a/bindings/json_test.go b/bindings/json_test.go
deleted file mode 100644
index 4dd6eeadcfe5f789aa59ef1f2a1ba7b372e2b709..0000000000000000000000000000000000000000
--- a/bindings/json_test.go
+++ /dev/null
@@ -1,40 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-// Copyright © 2022 xx foundation                                             //
-//                                                                            //
-// Use of this source code is governed by a license that can be found in the  //
-// LICENSE file.                                                              //
-////////////////////////////////////////////////////////////////////////////////
-
-package bindings
-
-import (
-	"encoding/json"
-	"gitlab.com/elixxir/crypto/e2e"
-	"math/rand"
-	"testing"
-	"time"
-)
-
-func TestName(t *testing.T) {
-	rl := []uint64{1, 4, 9}
-	prng := rand.New(rand.NewSource(42))
-	rfp := make([]byte, 32)
-	prng.Read(rfp)
-	mid := e2e.NewMessageID(rfp, prng.Uint64())
-
-	randData := make([]byte, 32)
-	prng.Read(randData)
-	k := e2e.Key{}
-	copy(k[:], randData)
-	kr := e2e.NewKeyResidue(k)
-
-	report := E2ESendReport{
-		RoundsList: RoundsList{rl},
-		MessageID:  mid.Marshal(),
-		Timestamp:  time.Now().UnixNano(),
-		KeyResidue: kr.Marshal(),
-	}
-
-	marshal, _ := json.Marshal(report)
-	t.Logf("%s", marshal)
-}
diff --git a/bindings/listener.go b/bindings/listener.go
index cc2bba18222e19a6f4bbf0f3f57948e7e9899872..8eaf0faff2e58bb188a9451f624d2eae1926bd9c 100644
--- a/bindings/listener.go
+++ b/bindings/listener.go
@@ -62,6 +62,7 @@ type Message struct {
 
 	Encrypted bool
 	RoundId   int
+	RoundURL  string
 }
 
 // Hear is called to receive a message in the UI.
@@ -76,6 +77,7 @@ func (l listener) Hear(item receive.Message) {
 		Timestamp:   item.Timestamp.UnixNano(),
 		Encrypted:   item.Encrypted,
 		RoundId:     int(item.Round.ID),
+		RoundURL:    getRoundURL(item.Round.ID),
 	}
 	result, err := json.Marshal(&m)
 	if err != nil {
diff --git a/bindings/single.go b/bindings/single.go
index 71c4420148dcf7049a4b4fdc911afd990b810838..d6625cd71d8fe027fa2a64ca1b146d30e6f6eef0 100644
--- a/bindings/single.go
+++ b/bindings/single.go
@@ -64,6 +64,7 @@ func TransmitSingleUse(e2eID int, recipient []byte, tag string, payload,
 		EphID:       eid.EphId.Int64(),
 		ReceptionID: eid.Source,
 		RoundsList:  makeRoundsList(rids...),
+		RoundURL:    getRoundURL(rids[0]),
 	}
 	return json.Marshal(sr)
 }
@@ -99,14 +100,16 @@ func Listen(e2eID int, tag string, cb SingleUseCallback) (Stopper, error) {
 // SingleUseSendReport is the bindings-layer struct used to represent
 // information returned by single.TransmitRequest.
 //
-// JSON example:
+// SingleUseSendReport JSON example:
 //  {
 //   "Rounds":[1,5,9],
+//   "RoundURL": "https://dashboard.xx.network/rounds/25?xxmessenger=true",
 //   "EphID":1655533,
 //   "ReceptionID":"emV6aW1hAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD"}
 //  }
 type SingleUseSendReport struct {
 	RoundsList
+	RoundURL    string
 	ReceptionID *id.ID
 	EphID       int64
 }
@@ -115,9 +118,10 @@ type SingleUseSendReport struct {
 // information passed to the single.Response callback interface in response to
 // single.TransmitRequest.
 //
-// JSON example:
+// SingleUseResponseReport JSON example:
 //  {
 //   "Rounds":[1,5,9],
+//   "RoundURL": "https://dashboard.xx.network/rounds/25?xxmessenger=true",
 //   "Payload":"rSuPD35ELWwm5KTR9ViKIz/r1YGRgXIl5792SF8o8piZzN6sT4Liq4rUU/nfOPvQEjbfWNh/NYxdJ72VctDnWw==",
 //   "EphID":1655533,
 //   "ReceptionID":"emV6aW1hAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD"},
@@ -125,6 +129,7 @@ type SingleUseSendReport struct {
 //  }
 type SingleUseResponseReport struct {
 	RoundsList
+	RoundURL    string
 	Payload     []byte
 	ReceptionID *id.ID
 	EphID       int64
@@ -134,16 +139,18 @@ type SingleUseResponseReport struct {
 // SingleUseCallbackReport is the bindings-layer struct used to represent
 // single -use messages received by a callback passed into single.Listen.
 //
-// JSON example:
-//  {
-//   "Rounds":[1,5,9],
-//   "Payload":"rSuPD35ELWwm5KTR9ViKIz/r1YGRgXIl5792SF8o8piZzN6sT4Liq4rUU/nfOPvQEjbfWNh/NYxdJ72VctDnWw==",
-//   "Partner":"emV6aW1hAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD",
-//   "EphID":1655533,
-//   "ReceptionID":"emV6aW1hAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD"}
-//  }
+// SingleUseCallbackReport JSON example:
+//    {
+//      "Rounds":[1,5,9],
+//      "RoundURL": "https://dashboard.xx.network/rounds/25?xxmessenger=true",
+//      "Payload":"rSuPD35ELWwm5KTR9ViKIz/r1YGRgXIl5792SF8o8piZzN6sT4Liq4rUU/nfOPvQEjbfWNh/NYxdJ72VctDnWw==",
+//      "Partner":"emV6aW1hAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD",
+//      "EphID":1655533,
+//      "ReceptionID":"emV6aW1hAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD"}
+//    }
 type SingleUseCallbackReport struct {
 	RoundsList
+	RoundURL    string
 	Payload     []byte
 	Partner     *id.ID
 	EphID       int64
@@ -208,6 +215,7 @@ func (sl singleUseListener) Callback(
 	scr := SingleUseCallbackReport{
 		Payload:     req.GetPayload(),
 		RoundsList:  makeRoundsList(rids...),
+		RoundURL:    getRoundURL(rids[0]),
 		Partner:     req.GetPartner(),
 		EphID:       eid.EphId.Int64(),
 		ReceptionID: eid.Source,
@@ -246,6 +254,7 @@ func (sr singleUseResponse) Callback(payload []byte,
 	}
 	sendReport := SingleUseResponseReport{
 		RoundsList:  makeRoundsList(rids...),
+		RoundURL:    getRoundURL(rids[0]),
 		ReceptionID: receptionID.Source,
 		EphID:       receptionID.EphId.Int64(),
 		Payload:     payload,
diff --git a/bindings/ud.go b/bindings/ud.go
index a49031ad7fd9752a99315c6606c04706cbb1b800..d167e145daf1e110bf0728cf13bc28c54287538a 100644
--- a/bindings/ud.go
+++ b/bindings/ud.go
@@ -414,6 +414,7 @@ func LookupUD(e2eID int, udContact []byte, cb UdLookupCallback,
 		EphID:       eid.EphId.Int64(),
 		ReceptionID: eid.Source,
 		RoundsList:  makeRoundsList(rids...),
+		RoundURL:    getRoundURL(rids[0]),
 	}
 
 	return json.Marshal(sr)
@@ -517,6 +518,7 @@ func SearchUD(e2eID int, udContact []byte, cb UdSearchCallback,
 		EphID:       eid.EphId.Int64(),
 		ReceptionID: eid.Source,
 		RoundsList:  makeRoundsList(rids...),
+		RoundURL:    getRoundURL(rids[0]),
 	}
 
 	return json.Marshal(sr)
diff --git a/cmd/callbacks.go b/cmd/callbacks.go
index 79ea1931d349b3c056c29ce33a6dfdbddc60cb7e..058c79dd0430b81243a4077f167694b37a909c3d 100644
--- a/cmd/callbacks.go
+++ b/cmd/callbacks.go
@@ -27,6 +27,7 @@ import (
 type authCallbacks struct {
 	autoConfirm bool
 	confCh      chan *id.ID
+	reqCh       chan *id.ID
 	params      xxdk.E2EParams
 }
 
@@ -34,6 +35,7 @@ func makeAuthCallbacks(autoConfirm bool, params xxdk.E2EParams) *authCallbacks {
 	return &authCallbacks{
 		autoConfirm: autoConfirm,
 		confCh:      make(chan *id.ID, 10),
+		reqCh:       make(chan *id.ID, 10),
 		params:      params,
 	}
 }
@@ -44,7 +46,7 @@ func (a *authCallbacks) Request(requestor contact.Contact,
 	msg := fmt.Sprintf("Authentication channel request from: %s\n",
 		requestor.ID)
 	jww.INFO.Printf(msg)
-	fmt.Printf(msg)
+	fmt.Print(msg)
 	if a.autoConfirm {
 		jww.INFO.Printf("Channel Request: %s",
 			requestor.ID)
@@ -55,8 +57,9 @@ func (a *authCallbacks) Request(requestor contact.Contact,
 		}
 
 		a.confCh <- requestor.ID
+	} else {
+		a.reqCh <- requestor.ID
 	}
-
 }
 
 func (a *authCallbacks) Confirm(requestor contact.Contact,
@@ -72,7 +75,7 @@ func (a *authCallbacks) Reset(requestor contact.Contact,
 	msg := fmt.Sprintf("Authentication channel reset from: %s\n",
 		requestor.ID)
 	jww.INFO.Printf(msg)
-	fmt.Printf(msg)
+	fmt.Print(msg)
 }
 
 func registerMessageListener(user *xxdk.E2e) chan receive.Message {
diff --git a/cmd/root.go b/cmd/root.go
index 66240fdb9b20a332daaca3d7a77ff24a9186a6e6..33ae2745e7a35176a14d1b1bc39f057cbaa85de6 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -14,11 +14,12 @@ import (
 	"encoding/hex"
 	"encoding/json"
 	"fmt"
-	cryptoE2e "gitlab.com/elixxir/crypto/e2e"
 	"io/ioutil"
 	"log"
 	"os"
 
+	cryptoE2e "gitlab.com/elixxir/crypto/e2e"
+
 	"github.com/pkg/profile"
 
 	"strconv"
@@ -76,8 +77,13 @@ var rootCmd = &cobra.Command{
 
 		cmixParams, e2eParams := initParams()
 
-		authCbs := makeAuthCallbacks(
-			viper.GetBool(unsafeChannelCreationFlag), e2eParams)
+		autoConfirm := viper.GetBool(unsafeChannelCreationFlag)
+		acceptChannels := viper.GetBool(acceptChannelFlag)
+		if acceptChannels {
+			autoConfirm = false
+		}
+
+		authCbs := makeAuthCallbacks(autoConfirm, e2eParams)
 		user := initE2e(cmixParams, e2eParams, authCbs)
 
 		jww.INFO.Printf("Client Initialized...")
@@ -96,12 +102,14 @@ var rootCmd = &cobra.Command{
 			recipientContact = readContact(destFile)
 			recipientID = recipientContact.ID
 		} else if destId == "0" || sendId == destId {
-			jww.INFO.Printf("Sending message to self")
+			jww.INFO.Printf("Sending message to self, " +
+				"this will timeout unless authrequest is sent")
 			recipientID = receptionIdentity.ID
 			recipientContact = receptionIdentity.GetContact()
 		} else {
 			recipientID = parseRecipient(destId)
-			jww.INFO.Printf("destId: %v\nrecipientId: %v", destId, recipientID)
+			jww.INFO.Printf("destId: %v\nrecipientId: %v", destId,
+				recipientID)
 
 		}
 		isPrecanPartner := isPrecanID(recipientID)
@@ -151,11 +159,42 @@ var rootCmd = &cobra.Command{
 
 		// Send Messages
 		msgBody := viper.GetString(messageFlag)
+		hasMsgs := true
+		if msgBody == "" {
+			hasMsgs = false
+		}
 		time.Sleep(10 * time.Second)
 
 		// Accept auth request for this recipient
+		authSecs := viper.GetUint(authTimeoutFlag)
 		authConfirmed := false
-		if viper.GetBool(acceptChannelFlag) {
+		jww.INFO.Printf("Preexisting E2e partners: %+v", user.GetE2E().GetAllPartnerIDs())
+		if user.GetE2E().HasAuthenticatedChannel(recipientID) {
+			jww.INFO.Printf("Authenticated channel already in "+
+				"place for %s", recipientID)
+			authConfirmed = true
+		} else {
+			jww.INFO.Printf("No authenticated channel in "+
+				"place for %s", recipientID)
+		}
+
+		if acceptChannels && !authConfirmed {
+			for reqDone := false; !reqDone; {
+				select {
+				case reqID := <-authCbs.reqCh:
+					if recipientID.Cmp(reqID) {
+						reqDone = true
+					} else {
+						fmt.Printf(
+							"unexpected request:"+
+								" %s", reqID)
+					}
+				case <-time.After(time.Duration(authSecs) *
+					time.Second):
+					fmt.Print("timed out on auth request")
+					reqDone = true
+				}
+			}
 			// Verify that the confirmation message makes it to the
 			// original sender
 			if viper.GetBool(verifySendFlag) {
@@ -171,16 +210,6 @@ var rootCmd = &cobra.Command{
 			authConfirmed = true
 		}
 
-		jww.INFO.Printf("Preexisting E2e partners: %+v", user.GetE2E().GetAllPartnerIDs())
-		if user.GetE2E().HasAuthenticatedChannel(recipientID) {
-			jww.INFO.Printf("Authenticated channel already in "+
-				"place for %s", recipientID)
-			authConfirmed = true
-		} else {
-			jww.INFO.Printf("No authenticated channel in "+
-				"place for %s", recipientID)
-		}
-
 		// Send unsafe messages or not?
 		unsafe := viper.GetBool(unsafeFlag)
 		sendAuthReq := viper.GetBool(sendAuthRequestFlag)
@@ -200,7 +229,7 @@ var rootCmd = &cobra.Command{
 			authConfirmed = false
 		}
 
-		if !unsafe && !authConfirmed {
+		if !unsafe && !authConfirmed && hasMsgs {
 			// Signal for authConfirm callback in a separate thread
 			go func() {
 				for {
@@ -216,16 +245,15 @@ var rootCmd = &cobra.Command{
 			scnt := uint(0)
 
 			// Wait until authConfirmed
-			waitSecs := viper.GetUint(authTimeoutFlag)
-			for !authConfirmed && scnt < waitSecs {
+			for !authConfirmed && scnt < authSecs {
 				time.Sleep(1 * time.Second)
 				scnt++
 			}
-			if scnt == waitSecs {
+			if scnt == authSecs {
 				jww.FATAL.Panicf("Could not confirm "+
 					"authentication channel for %s, "+
 					"waited %d seconds.", recipientID,
-					waitSecs)
+					authSecs)
 			}
 			jww.INFO.Printf("Authentication channel confirmation"+
 				" took %d seconds", scnt)
@@ -278,6 +306,13 @@ var rootCmd = &cobra.Command{
 
 		wg := &sync.WaitGroup{}
 		sendCnt := int(viper.GetUint(sendCountFlag))
+		if !hasMsgs && sendCnt != 0 {
+			msg := "No message to send, please set your message" +
+				"or set sendCount to 0 to suppress this warning"
+			jww.WARN.Printf(msg)
+			fmt.Print(msg)
+			sendCnt = 0
+		}
 		wg.Add(sendCnt)
 		go func() {
 			sendDelay := time.Duration(viper.GetUint(sendDelayFlag))
@@ -556,7 +591,7 @@ func addAuthenticatedChannel(user *xxdk.E2e, recipientID *id.ID,
 	msg := fmt.Sprintf("Adding authenticated channel for: %s\n",
 		recipientID)
 	jww.INFO.Printf(msg)
-	fmt.Printf(msg)
+	fmt.Print(msg)
 
 	recipientContact := recipient
 
diff --git a/go.sum b/go.sum
index bb0d85da6ed772424c60be27552323b8d8f05621..25ccb95846b43d260308ccb8aae526bd3b1bafa7 100644
--- a/go.sum
+++ b/go.sum
@@ -637,6 +637,8 @@ gitlab.com/elixxir/crypto v0.0.7-0.20220902165412-5c5e3e990e84 h1:sQCoZ+w09X/8Lj
 gitlab.com/elixxir/crypto v0.0.7-0.20220902165412-5c5e3e990e84/go.mod h1:Sfb4ceEoWLLYNT8V6isZa5k87NfUecM8i34Z+hDYTgg=
 gitlab.com/elixxir/ekv v0.2.1-0.20220901224437-ab4cbf94bf8b h1:0cN/WHbFaonJEN+odqyjtSrkuEbBnEnWfggT91svPGc=
 gitlab.com/elixxir/ekv v0.2.1-0.20220901224437-ab4cbf94bf8b/go.mod h1:USLD7xeDnuZEavygdrgzNEwZXeLQJK/w1a+htpN+JEU=
+gitlab.com/elixxir/ekv v0.2.1 h1:dtwbt6KmAXG2Tik5d60iDz2fLhoFBgWwST03p7T+9Is=
+gitlab.com/elixxir/ekv v0.2.1/go.mod h1:USLD7xeDnuZEavygdrgzNEwZXeLQJK/w1a+htpN+JEU=
 gitlab.com/elixxir/primitives v0.0.0-20200731184040-494269b53b4d/go.mod h1:OQgUZq7SjnE0b+8+iIAT2eqQF+2IFHn73tOo+aV11mg=
 gitlab.com/elixxir/primitives v0.0.0-20200804170709-a1896d262cd9/go.mod h1:p0VelQda72OzoUckr1O+vPW0AiFe0nyKQ6gYcmFSuF8=
 gitlab.com/elixxir/primitives v0.0.0-20200804182913-788f47bded40/go.mod h1:tzdFFvb1ESmuTCOl1z6+yf6oAICDxH2NPUemVgoNLxc=