/// <summary>
        /// Find keyword objects by list of keyword names
        /// </summary>
        /// <param name="keywords">list of keyword names</param>
        /// <returns>list with keyword objects</returns>
        /// <exception cref="BadRequestException">          in case HTTP response code is 400 - Bad request, the request was formatted improperly.</exception>
        /// <exception cref="UnauthorizedException">        in case HTTP response code is 401 - Unauthorized, API Key missing or invalid.</exception>
        /// <exception cref="AccessForbiddenException">     in case HTTP response code is 403 - Forbidden, insufficient permissions.</exception>
        /// <exception cref="ResourceNotFoundException">    in case HTTP response code is 404 - NOT FOUND, the resource requested does not exist.</exception>
        /// <exception cref="InternalServerErrorException"> in case HTTP response code is 500 - Internal Server Error.</exception>
        /// <exception cref="CallfireApiException">         in case HTTP response code is something different from codes listed above.</exception>
        /// <exception cref="CallfireClientException">      in case error has occurred in client.</exception>
        public IList <Keyword> Find(IList <string> keywords)
        {
            var queryParams = new List <KeyValuePair <string, object> >();

            ClientUtils.AddQueryParamIfSet("keywords", keywords, queryParams);
            return(Client.Get <ListHolder <Keyword> >(KEYWORDS_PATH, queryParams).Items);
        }
        /// <summary>
        /// Create a text broadcast campaign using the Text Broadcast API. A campaign can be created with
        /// no contacts and bare minimum configuration, but contacts will have to be added further on to use the campaign.
        /// If start set to true campaign starts immediately
        /// </summary>
        /// <param name="broadcast">text broadcast to create</param>
        /// <param name="start">if set to true then broadcast will start immediately, by default it set to false</param>
        /// <param name="strictValidation">apply strict validation for contacts</param>
        /// <returns>ResourceId object with id of created broadcast</returns>
        /// <exception cref="BadRequestException">          in case HTTP response code is 400 - Bad request, the request was formatted improperly.</exception>
        /// <exception cref="UnauthorizedException">        in case HTTP response code is 401 - Unauthorized, API Key missing or invalid.</exception>
        /// <exception cref="AccessForbiddenException">     in case HTTP response code is 403 - Forbidden, insufficient permissions.</exception>
        /// <exception cref="ResourceNotFoundException">    in case HTTP response code is 404 - NOT FOUND, the resource requested does not exist.</exception>
        /// <exception cref="InternalServerErrorException"> in case HTTP response code is 500 - Internal Server Error.</exception>
        /// <exception cref="CallfireApiException">         in case HTTP response code is something different from codes listed above.</exception>
        /// <exception cref="CallfireClientException">      in case error has occurred in client.</exception>
        public ResourceId Create(TextBroadcast broadcast, bool start = false, bool?strictValidation = null)
        {
            var queryParams = new List <KeyValuePair <string, object> >(2);

            ClientUtils.AddQueryParamIfSet("start", start.ToString(), queryParams);
            ClientUtils.AddQueryParamIfSet("strictValidation", strictValidation.ToString(), queryParams);
            return(Client.Post <ResourceId>(TB_PATH, broadcast, queryParams));
        }
        /// <summary>
        /// Upload contact lists from CSV file
        /// Create contact list which includes list of contacts by file.
        /// </summary>
        /// <param name="name">contact list name</param>
        /// <param name="filePath">path to CSV file with contacts to upload</param>
        /// <param name="useCustomFields">A flag to indicate how to define property names for contacts. If true, uses the field and property names exactly as defined. If false will assign custom properties and fields to A, B, C, etc</param>
        /// <returns>newly created contact list id</returns>
        /// <exception cref="BadRequestException">          in case HTTP response code is 400 - Bad request, the request was formatted improperly.</exception>
        /// <exception cref="UnauthorizedException">        in case HTTP response code is 401 - Unauthorized, API Key missing or invalid.</exception>
        /// <exception cref="AccessForbiddenException">     in case HTTP response code is 403 - Forbidden, insufficient permissions.</exception>
        /// <exception cref="ResourceNotFoundException">    in case HTTP response code is 404 - NOT FOUND, the resource requested does not exist.</exception>
        /// <exception cref="InternalServerErrorException"> in case HTTP response code is 500 - Internal Server Error.</exception>
        /// <exception cref="CallfireApiException">         in case HTTP response code is something different from codes listed above.</exception>
        /// <exception cref="CallfireClientException">      in case error has occurred in client.</exception>
        public ResourceId CreateFromCsv(string name, string filePath, bool?useCustomFields = null)
        {
            var formParams = new List <KeyValuePair <string, object> >(2);

            ClientUtils.AddQueryParamIfSet("name", name, formParams);
            ClientUtils.AddQueryParamIfSet("useCustomFields", useCustomFields, formParams);
            return(Client.PostFile <ResourceId>(LISTS_UPLOAD_PATH, filePath, formParams));
        }
        /// <summary>
        /// Send texts to recipients through existing campaign, if null default campaign will be used
        /// Use the /texts API to quickly send individual texts.A verified Caller ID and sufficient
        /// credits are required to make a call.
        /// </summary>
        /// <param name="recipients">call recipients</param>
        /// <param name="campaignId">specify a campaignId to send calls quickly on a previously created campaign</param>
        /// <param name="fields">limit fields returned. Example fields=id,name</param>
        /// <returns>list with created text objects</returns>
        /// <exception cref="BadRequestException">          in case HTTP response code is 400 - Bad request, the request was formatted improperly.</exception>
        /// <exception cref="UnauthorizedException">        in case HTTP response code is 401 - Unauthorized, API Key missing or invalid.</exception>
        /// <exception cref="AccessForbiddenException">     in case HTTP response code is 403 - Forbidden, insufficient permissions.</exception>
        /// <exception cref="ResourceNotFoundException">    in case HTTP response code is 404 - NOT FOUND, the resource requested does not exist.</exception>
        /// <exception cref="InternalServerErrorException"> in case HTTP response code is 500 - Internal Server Error.</exception>
        /// <exception cref="CallfireApiException">         in case HTTP response code is something different from codes listed above.</exception>
        /// <exception cref="CallfireClientException">      in case error has occurred in client.</exception>
        public IList <Text> Send(List <TextRecipient> recipients, long?campaignId = null, string fields = null)
        {
            Validate.NotBlank(recipients.ToString(), "recipients cannot be blank");
            var queryParams = new List <KeyValuePair <string, object> >(2);

            ClientUtils.AddQueryParamIfSet("campaignId", campaignId, queryParams);
            ClientUtils.AddQueryParamIfSet("fields", fields, queryParams);
            return(Client.Post <ListHolder <Text> >(TEXTS_PATH, recipients, queryParams).Items);
        }
        /// <summary>
        /// Use this API to toggle not dialed recipients in created text broadcast. Post a list of Recipient
        /// objects which will be immediately disabled/enabled if still not sent. Recipients may be added
        /// as a list of contact ids, or list of numbers. If recipients array contains already dialed contact - it would be ignored.
        /// </summary>
        /// <param name="id">id of call broadcast</param>
        /// <param name="recipients">recipients to add</param>
        /// <param name="enable">flag to indicate action (true is enabling and vice versa)</param>
        /// <exception cref="BadRequestException">          in case HTTP response code is 400 - Bad request, the request was formatted improperly.</exception>
        /// <exception cref="UnauthorizedException">        in case HTTP response code is 401 - Unauthorized, API Key missing or invalid.</exception>
        /// <exception cref="AccessForbiddenException">     in case HTTP response code is 403 - Forbidden, insufficient permissions.</exception>
        /// <exception cref="ResourceNotFoundException">    in case HTTP response code is 404 - NOT FOUND, the resource requested does not exist.</exception>
        /// <exception cref="InternalServerErrorException"> in case HTTP response code is 500 - Internal Server Error.</exception>
        /// <exception cref="CallfireApiException">         in case HTTP response code is something different from codes listed above.</exception>
        /// <exception cref="CallfireClientException">      in case error has occurred in client.</exception>
        public void ToggleRecipientsStatus(long id, IList <Recipient> recipients, bool enable = false)
        {
            var queryParams = new List <KeyValuePair <string, object> >(1);

            ClientUtils.AddQueryParamIfSet("enable", enable, queryParams);
            string path = TB_ITEM_TOGGLE_RECIPIENTS_STATUS_PATH.ReplaceFirst(ClientConstants.PLACEHOLDER, id.ToString());

            Client.Post <object>(path, recipients, queryParams);
        }
        /// <summary>
        /// Delete contact list items
        /// </summary>
        /// <param name="contactListId">id of contact list</param>
        /// <param name="contactIds">ids of items to remove</param>
        /// <exception cref="BadRequestException">          in case HTTP response code is 400 - Bad request, the request was formatted improperly.</exception>
        /// <exception cref="UnauthorizedException">        in case HTTP response code is 401 - Unauthorized, API Key missing or invalid.</exception>
        /// <exception cref="AccessForbiddenException">     in case HTTP response code is 403 - Forbidden, insufficient permissions.</exception>
        /// <exception cref="ResourceNotFoundException">    in case HTTP response code is 404 - NOT FOUND, the resource requested does not exist.</exception>
        /// <exception cref="InternalServerErrorException"> in case HTTP response code is 500 - Internal Server Error.</exception>
        /// <exception cref="CallfireApiException">         in case HTTP response code is something different from codes listed above.</exception>
        /// <exception cref="CallfireClientException">      in case error has occurred in client.</exception>
        public void RemoveListItems(long contactListId, List <long> contactIds)
        {
            Validate.NotBlank(contactListId.ToString(), "id cannot be blank");
            string path        = LISTS_ITEMS_PATH.ReplaceFirst(ClientConstants.PLACEHOLDER, contactListId.ToString());
            var    queryParams = new List <KeyValuePair <string, object> >(1);

            ClientUtils.AddQueryParamIfSet("contactId", contactIds, queryParams);
            Client.Delete(path, queryParams);
        }
        /// <summary>
        /// Delete DNC list items
        /// </summary>
        /// <param name="id">id of DNC list</param>
        /// <param name="numbers">numbers to remove</param>
        /// <exception cref="BadRequestException">          in case HTTP response code is 400 - Bad request, the request was formatted improperly.</exception>
        /// <exception cref="UnauthorizedException">        in case HTTP response code is 401 - Unauthorized, API Key missing or invalid.</exception>
        /// <exception cref="AccessForbiddenException">     in case HTTP response code is 403 - Forbidden, insufficient permissions.</exception>
        /// <exception cref="ResourceNotFoundException">    in case HTTP response code is 404 - NOT FOUND, the resource requested does not exist.</exception>
        /// <exception cref="InternalServerErrorException"> in case HTTP response code is 500 - Internal Server Error.</exception>
        /// <exception cref="CallfireApiException">         in case HTTP response code is something different from codes listed above.</exception>
        /// <exception cref="CallfireClientException">      in case error has occurred in client.</exception>
        public void RemoveListItems(long id, IList <string> numbers)
        {
            Validate.NotBlank(id.ToString(), "id cannot be blank");
            string path        = DNC_LISTS_LIST_ITEMS_PATH.ReplaceFirst(ClientConstants.PLACEHOLDER, id.ToString());
            var    queryParams = new List <KeyValuePair <string, object> >(1);

            ClientUtils.AddQueryParamIfSet("number", numbers, queryParams);
            Client.Delete(path, queryParams);
        }
        /// <summary>
        /// Use this API to add recipients to an already created text broadcast. Post a list of Recipient
        /// objects for them to be immediately added to the text broadcast campaign. These contacts do not
        /// go through validation process, and will be acted upon as they are added. Recipients may be added
        /// as a list of contact ids, or list of numbers.
        /// </summary>
        /// <param name="id">id of text broadcast</param>
        /// <param name="recipients">recipients to add</param>
        /// <param name="fields">limit fields returned. E.g. fields=id,name or fields=items(id,name)</param>
        /// <param name="strictValidation">apply strict validation for contacts</param>
        /// <returns>Text objects</returns>
        /// <exception cref="BadRequestException">          in case HTTP response code is 400 - Bad request, the request was formatted improperly.</exception>
        /// <exception cref="UnauthorizedException">        in case HTTP response code is 401 - Unauthorized, API Key missing or invalid.</exception>
        /// <exception cref="AccessForbiddenException">     in case HTTP response code is 403 - Forbidden, insufficient permissions.</exception>
        /// <exception cref="ResourceNotFoundException">    in case HTTP response code is 404 - NOT FOUND, the resource requested does not exist.</exception>
        /// <exception cref="InternalServerErrorException"> in case HTTP response code is 500 - Internal Server Error.</exception>
        /// <exception cref="CallfireApiException">         in case HTTP response code is something different from codes listed above.</exception>
        /// <exception cref="CallfireClientException">      in case error has occurred in client.</exception>
        public IList <Text> AddRecipients(long id, IList <TextRecipient> recipients, String fields = null, bool?strictValidation = null)
        {
            var queryParams = new List <KeyValuePair <string, object> >(2);

            ClientUtils.AddQueryParamIfSet("fields", fields, queryParams);
            ClientUtils.AddQueryParamIfSet("strictValidation", strictValidation, queryParams);
            string path = TB_ITEM_RECIPIENTS_PATH.ReplaceFirst(ClientConstants.PLACEHOLDER, id.ToString());

            return(Client.Post <ListHolder <Text> >(path, recipients, queryParams).Items);
        }
        /// <summary>
        /// Search Universal Do Not Contact by number
        /// </summary>
        /// <param name="toNumber">Phone Number in Do Not Contact list</param>
        /// <param name="fromNumber">Searches for entries where fromNumber is communicating with toNumber, or vice versa.</param>
        /// <param name="fields">Limit fields returned. Example fields=limit,offset,items(id,name)</param>
        /// <returns>list of universal dncs</returns>
        /// <exception cref="BadRequestException">          in case HTTP response code is 400 - Bad request, the request was formatted improperly.</exception>
        /// <exception cref="UnauthorizedException">        in case HTTP response code is 401 - Unauthorized, API Key missing or invalid.</exception>
        /// <exception cref="AccessForbiddenException">     in case HTTP response code is 403 - Forbidden, insufficient permissions.</exception>
        /// <exception cref="ResourceNotFoundException">    in case HTTP response code is 404 - NOT FOUND, the resource requested does not exist.</exception>
        /// <exception cref="InternalServerErrorException"> in case HTTP response code is 500 - Internal Server Error.</exception>
        /// <exception cref="CallfireApiException">         in case HTTP response code is something different from codes listed above.</exception>
        /// <exception cref="CallfireClientException">      in case error has occurred in client.</exception>
        public IList <UniversalDnc> GetUniversalDncNumber(string toNumber, string fromNumber = null, string fields = null)
        {
            Validate.NotBlank(toNumber, "toNumber cannot be blank");
            string path        = DNC_LISTS_UNIVERSAL_PATH.ReplaceFirst(ClientConstants.PLACEHOLDER, toNumber);
            var    queryParams = new List <KeyValuePair <string, object> >(2);

            ClientUtils.AddQueryParamIfSet("fields", fields, queryParams);
            ClientUtils.AddQueryParamIfSet("fromNumber", fromNumber, queryParams);
            return(Client.Get <ListHolder <UniversalDnc> >(path, queryParams).Items);
        }
        /// <summary>
        /// Get statistics on text broadcast
        /// </summary>
        /// <param name="id">id of text broadcast</param>
        /// <param name="fields">limit fields returned. E.g. fields=id,name or fields=items(id,name)</param>
        /// <param name="begin">begin date to filter</param>
        /// <param name="end">end date to filter</param>
        /// <returns>broadcast stats object</returns>
        /// <exception cref="BadRequestException">          in case HTTP response code is 400 - Bad request, the request was formatted improperly.</exception>
        /// <exception cref="UnauthorizedException">        in case HTTP response code is 401 - Unauthorized, API Key missing or invalid.</exception>
        /// <exception cref="AccessForbiddenException">     in case HTTP response code is 403 - Forbidden, insufficient permissions.</exception>
        /// <exception cref="ResourceNotFoundException">    in case HTTP response code is 404 - NOT FOUND, the resource requested does not exist.</exception>
        /// <exception cref="InternalServerErrorException"> in case HTTP response code is 500 - Internal Server Error.</exception>
        /// <exception cref="CallfireApiException">         in case HTTP response code is something different from codes listed above.</exception>
        /// <exception cref="CallfireClientException">      in case error has occurred in client.</exception>
        public TextBroadcastStats GetStats(long id, string fields = null, DateTime?begin = null, DateTime?end = null)
        {
            var queryParams = new List <KeyValuePair <string, object> >(3);

            ClientUtils.AddQueryParamIfSet("fields", fields, queryParams);
            ClientUtils.AddQueryParamIfSet("begin", begin, queryParams);
            ClientUtils.AddQueryParamIfSet("end", end, queryParams);
            String path = TB_ITEM_STATS_PATH.ReplaceFirst(ClientConstants.PLACEHOLDER, id.ToString());

            return(Client.Get <TextBroadcastStats>(path, queryParams));
        }