/// <summary>
        /// Returns a listing of all Direct Messages / Chats a user is a member of.
        /// </summary>
        /// <returns>A list of <see cref="Chat"/>.</returns>
        public virtual async Task <ICollection <Chat> > GetChatsAsync()
        {
            const int MaxPerPage = 100; // GroupMe allows 100 Chats/Page.

            var request = this.CreateRestRequestV3($"/chats", Method.GET);

            request.AddParameter("per_page", MaxPerPage); // always all available chats.

            var cancellationTokenSource = new CancellationTokenSource();
            var restResponse            = await this.ApiClient.ExecuteAsync(request, cancellationTokenSource.Token);

            if (restResponse.StatusCode == System.Net.HttpStatusCode.OK)
            {
                var results = JsonConvert.DeserializeObject <ChatsList>(restResponse.Content);

                foreach (var chat in results.Chats)
                {
                    // ensure every Chat has a reference to the parent client (this)
                    chat.Client = this;

                    // required to establish a constant, non-foreign-key Primary Key for Chat
                    chat.Id = chat.OtherUser.Id;

                    var oldChat = this.ChatsList.Find(g => g.Id == chat.Id);

                    if (oldChat == null)
                    {
                        this.ChatsList.Add(chat);
                    }
                    else
                    {
                        DataMerger.MergeChat(oldChat, chat);
                    }
                }

                return(results.Chats);
            }
            else
            {
                throw new System.Net.WebException($"Failure retreving /Groups. Status Code {restResponse.StatusCode}");
            }
        }
        /// <summary>
        /// Returns a listing of a maximum of 200 <see cref="Contact"/>s of the user, as specified by input parameters.
        /// </summary>
        /// <param name="retrieveSinceMode">Specify whether to employ "since" retrieval mode for receiving list of <see cref="Contact"/>s.</param>
        /// <param name="messageCreatedAtIso8601">The ISO8601 timestamp used to determine which contacts to receive if the "since" retrieval mode is true.</param>
        /// <returns>A list of <see cref="Contact"/>s of maximum length 200.</returns>
        public virtual async Task <ICollection <Contact> > GetContactsAsync(bool retrieveSinceMode = false, string messageCreatedAtIso8601 = "")
        {
            const string IncludeBlocked = "true";     // based on GroupMe Web, can retrieve 200 contacts per API request

            var request = this.CreateRestRequestV4($"/relationships", Method.GET);

            request.AddParameter("include_blocked", IncludeBlocked);

            if (retrieveSinceMode)
            {
                request.AddParameter("since", messageCreatedAtIso8601);
            }

            var cancellationTokenSource = new CancellationTokenSource();
            var restResponse            = await this.ApiClient.ExecuteAsync(request, cancellationTokenSource.Token);

            if (restResponse.StatusCode == System.Net.HttpStatusCode.OK)
            {
                var results = JsonConvert.DeserializeObject <ContactsList>(restResponse.Content);

                foreach (var contact in results.Contacts)
                {
                    var oldContact = this.ContactsList.Find(c => c.Id == contact.Id);
                    if (oldContact == null)
                    {
                        this.ContactsList.Add(contact);
                    }
                    else
                    {
                        DataMerger.MergeContact(oldContact, contact);
                    }

                    contact.Client = this;
                }

                return(results.Contacts);
            }
            else
            {
                throw new System.Net.WebException($"Failure retrieving /Contacts. Status Code {restResponse.StatusCode}");
            }
        }
        /// <summary>
        /// Returns a listing of all Group Chats a user is a member of.
        /// </summary>
        /// <returns>A list of <see cref="Group"/>.</returns>
        public virtual async Task <ICollection <Group> > GetGroupsAsync()
        {
            const int MaxPerPage = 500; // GroupMe allows 500 Groups/page

            var request = this.CreateRestRequestV3($"/groups", Method.GET);

            request.AddParameter("per_page", MaxPerPage); // always all available groups.

            var cancellationTokenSource = new CancellationTokenSource();
            var restResponse            = await this.ApiClient.ExecuteAsync(request, cancellationTokenSource.Token);

            if (restResponse.StatusCode == System.Net.HttpStatusCode.OK)
            {
                var results = JsonConvert.DeserializeObject <GroupsList>(restResponse.Content);

                foreach (var group in results.Groups)
                {
                    // ensure every Group has a reference to the parent client (this)
                    group.Client = this;

                    var oldGroup = this.GroupsList.Find(g => g.Id == group.Id);

                    if (oldGroup == null)
                    {
                        this.GroupsList.Add(group);
                    }
                    else
                    {
                        DataMerger.MergeGroup(oldGroup, group);
                    }
                }

                return(results.Groups);
            }
            else
            {
                throw new System.Net.WebException($"Failure retreving /Groups. Status Code {restResponse.StatusCode}");
            }
        }