/// <summary>
        /// Validate asynchronously the punchout setup request and token based authentication
        /// </summary>
        /// <param name="url">The Uri the request is sent to.</param>
        /// <param name="credentials">ApiCredentials</param>
        /// <returns></returns>
        private string ValidateAsync(string url, ApiCredentials credentials = null)
        {
            if (IsAuthenticationEnabled)
            {
                if (credentials.IsNotNull())
                {
                    this.Credentials = credentials;
                }

                // Punchout setup request
                if (this.CurrentEndpoint.IsNull())
                {
                    return("PUNCHOUT_SETUP_REQUEST");
                }

                // Authentication / Authorization
                if (url.StartsWith("authenticate") == false && this.CurrentToken.IsNull())
                {
                    //await Authenticate();
                    return("AUTHENTICATE");
                }
            }

            return("OK");
        }
        /// <summary>
        /// Constructor with token based authentication
        /// </summary>
        public ApiEngine(ApiCredentials credentials, bool useCredentials = true, string clientIP = "")
        {
            this.Credentials           = credentials;
            this.UseDefaultCredentials = useCredentials;
            this.ClientIP = clientIP;

            PunchoutSetupRequest();
        }
        /// <summary>
        /// Validate the punchout setup request and token based authentication
        /// </summary>
        /// <param name="url">The Uri the request is sent to.</param>
        /// <param name="credentials">ApiCredentials</param>
        private void Validate(string url, ApiCredentials credentials = null)
        {
            if (IsAuthenticationEnabled)
            {
                if (credentials.IsNotNull())
                {
                    this.Credentials = credentials;
                }

                // Punchout setup request
                if (this.CurrentEndpoint.IsNull())
                {
                    throw new Exception("Please carry out the punchout setup request in order to continue.");
                }

                // Authentication / Authorization
                if (url.StartsWith("authenticate") == false && this.CurrentToken.IsNull())
                {
                    throw new Exception("The current token is null or empty");
                }
            }
        }
        /// <summary>
        /// Sends an object to a web api endpoint using the POST Http verb
        /// </summary>
        /// <typeparam name="T">input generic param type</typeparam>
        /// <param name="url">The Uri the request is sent to.</param>
        /// <param name="payload">payload object</param>
        /// <param name="credentials">ApiCredentials</param>
        /// <returns>Response</returns>
        public async Task <Response <TOutput> > PostItemAsync <TInput, TOutput>(string url, TInput payload, ApiCredentials credentials = null)
            where TInput : new()
            where TOutput : new()
        {
            Validate(url, credentials);

            var output = new Response <TOutput>();

            try
            {
                var requestUri = GetUrl(url);

                using (var request = CreateHttpRequestMessage(requestUri, HttpMethod.Post, null))
                {
                    var client = HttpClientSingleton.GetClient();

                    using (var response = await client.PostAsJsonAsync(requestUri, payload).ConfigureAwait(false))
                    {
                        if (response.IsSuccessStatusCode)
                        {
                            response.EnsureSuccessStatusCode();

                            output.IsOk       = true;
                            output.StatusCode = response.StatusCode;

                            GetResponseContent <TOutput>(output, response);
                        }
                        else
                        {
                            GetDetails(output, response);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                HandleError(output, e);
            }

            return(output);
        }
 /// <summary>
 /// Sends an object to a web api endpoint using the POST Http verb
 /// </summary>
 /// <typeparam name="T">input generic param type</typeparam>
 /// <param name="url">The Uri the request is sent to.</param>
 /// <param name="payload">payload object</param>
 /// <param name="credentials">ApiCredentials</param>
 /// <returns>Response</returns>
 public Response <TOutput> PostItem <TInput, TOutput>(string url, TInput payload, ApiCredentials credentials = null)
     where TInput : new()
     where TOutput : new()
 {
     return(PostItemAsync <TInput, TOutput>(url, payload, credentials).Result);
 }
 /// <summary>
 /// Sends an object or a list to a web api endpoint using the POST Http verb
 /// </summary>
 /// <typeparam name="T">input generic param type</typeparam>
 /// <param name="url">The Uri the request is sent to.</param>
 /// <param name="payload">payload object</param>
 /// <param name="credentials">ApiCredentials</param>
 /// <returns>Response</returns>
 public Response <bool> PostItem <T>(string url, T payload, ApiCredentials credentials = null) where T : new()
 {
     return(PostItemAsync <T>(url, payload, credentials).Result);
 }