/// <summary>
        /// Sends a raw REST request to the API. Includes error handling logic but no retry logic.
        /// </summary>
        /// <param name="method">The request method.</param>
        /// <param name="path">The request path.</param>
        /// <param name="queryParamaters">The query parameters, if any.</param>
        /// <param name="content">The request content, if any.</param>
        async Task <HttpResponseMessage> IApiRequestor.RawRequestAsync(HttpMethod method, string path, string[] queryParameters, HttpContent content, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            if (string.IsNullOrWhiteSpace(ApiKey))
            {
                throw new InvalidOperationException("No authentication provided.");
            }

            // Add the base API URI to the path and add the API key.
            path = $"{BaseApiUri}{path}?key={ApiKey}";

            // Add any provided query parameters.
            if (queryParameters != null)
            {
                // Remove potentially empty strings.
                queryParameters = queryParameters.Where(q => !string.IsNullOrWhiteSpace(q)).ToArray();

                if (queryParameters.Length > 0)
                {
                    path += $"&{string.Join("&", queryParameters)}";
                }
            }

            // Build the request using provided HTTP method, and build the request URI using the base API URI, provided path, and validated API key.
            var request = new HttpRequestMessage(method, path);

            // Assign request content, if supported by HTTP method.
            if (method != HttpMethod.Get)
            {
                request.Content = content;
            }

            var response = await HttpClient.SendAsync(request, cancellationToken).ConfigureAwait(false);

            // Happy days! Return the response.
            if (response.IsSuccessStatusCode)
            {
                return(response);
            }

            // If we're here, an exception of some description will be thrown.

            cancellationToken.ThrowIfCancellationRequested();

            try
            {
                var responseString = await response.Content.ReadAsStringAsync().ConfigureAwait(false);

                var apiError = JsonConvert.DeserializeObject <ApiError>(responseString);

                throw new ApiException("An error occurred with the request.", response, apiError);
            }
            catch
            {
                throw ApiException.InvalidServerResponse(response);
            }
        }
        /// <summary>
        /// Request a serialized object response with content.
        /// </summary>
        /// <param name="method">The request method.</param>
        /// <param name="path">The request path.</param>
        /// <param name="queryParameters">The query parameters, if any.</param>
        /// <param name="content">The request content.</param>
        async Task <TResponse> IApiRequestor.RequestJsonSerializedAsync <TResponse>(HttpMethod method, string path, string[] queryParameters, HttpContent content, CancellationToken cancellationToken)
        {
            var response = await((IApiRequestor)this).RequestAsync(method, path, queryParameters, content, cancellationToken).ConfigureAwait(false);

            if (!response.Content.Headers.ContentType.MediaType.StartsWith("application/json", StringComparison.CurrentCultureIgnoreCase))
            {
                throw ApiException.InvalidServerResponse(response);
            }

            return(JsonConvert.DeserializeObject <TResponse>(await response.Content.ReadAsStringAsync().ConfigureAwait(false)));
        }