private string _GenerateAuthHeader(string method, string resource, string date, string requestBodyHash)
        {
            string signature = (method + "\n" + date + "\n" + resource + "\n" + requestBodyHash).Trim();

            System.Security.Cryptography.HMACSHA1 hmac = new System.Security.Cryptography.HMACSHA1();
            hmac.Key = Encoding.UTF8.GetBytes(this.secretKey);

            string authStr = this.publicKey + ':' + SimplyCastAPIConnector.BytesToHex(hmac.ComputeHash(Encoding.UTF8.GetBytes(signature)));

            return("Authorization: HMAC " + System.Convert.ToBase64String(Encoding.UTF8.GetBytes(authStr)));
        }
 /// <summary>
 /// Main API class constructor.
 /// </summary>
 /// <param name="publicKey">The desired account API public key.</param>
 /// <param name="secretKey">The desired account API secret key.</param>
 public SimplyCastAPI(string publicKey, string secretKey)
 {
     this.connection     = new SimplyCastAPIConnector(publicKey, secretKey);
     this.contactManager = new ContactManagerAPI(connection);
     this.simplycast360  = new SimplyCast360API(connection);
 }
        /// <summary>
        /// Main API calling function.
        /// </summary>
        /// <typeparam name="T">The entity response return type.</typeparam>
        /// <param name="method">The HTTP method (GET, POST, etc).</param>
        /// <param name="resource">The API resource (the part of the URL
        /// between the base URL and the query parameters.</param>
        /// <param name="queryParameters">A dictionary of request query
        /// parameters.</param>
        /// <param name="requestBody">A serializable object containing the
        /// rquest body.</param>
        /// <returns>A response entity.</returns>
        public T Call <T>(string method, string resource, Dictionary <string, string> queryParameters, object requestBody)
        {
            string requestBodyString = "";

            if (requestBody == null)
            {
                requestBodyString = "";
            }
            else
            {
                requestBodyString = this._Serialize(requestBody);
            }

            string date = DateTime.UtcNow.ToString("r");

            string requestBodyHash = "";

            if (requestBodyString.Length > 0)
            {
                requestBodyHash = System.Convert.ToBase64String(Encoding.UTF8.GetBytes(SimplyCastAPIConnector.BytesToHex(System.Security.Cryptography.MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(requestBodyString.Trim())))));
            }

            string authHeader = this._GenerateAuthHeader(method, resource, date, requestBodyHash);

            string url = this.apiURL.Trim('/') + '/' + resource.Trim('/');

            if (queryParameters != null && queryParameters.Count > 0)
            {
                url = url + "?";
                foreach (KeyValuePair <string, string> q in queryParameters)
                {
                    url += System.Uri.EscapeDataString(q.Key) + "=" + System.Uri.EscapeDataString(q.Value) + "&";
                }
                url = url.TrimEnd('&');
            }

            HttpWebRequest webHandle = (HttpWebRequest)WebRequest.Create(url);

            webHandle.Method = method;
            webHandle.Headers.Add("X-Date", date);
            webHandle.Accept = "application/xml";
            webHandle.Headers.Add(authHeader);

            if (requestBodyString.Length > 0)
            {
                int contentLength = Encoding.UTF8.GetBytes(requestBodyString).Length;
                webHandle.ContentType   = "application/xml";
                webHandle.ContentLength = contentLength;
                webHandle.Headers.Add("Content-MD5", requestBodyHash);
                Stream requestStream = webHandle.GetRequestStream();
                requestStream.Write(Encoding.UTF8.GetBytes(requestBodyString), 0, contentLength);
                requestStream.Close();
            }

            HttpWebResponse webResponse;

            try
            {
                webResponse = (HttpWebResponse)webHandle.GetResponse();
            }
            catch (WebException e)
            {
                if (e.Response != null)
                {
                    webResponse = (HttpWebResponse)e.Response;
                }
                else
                {
                    throw e;
                }
            }

            Stream       receiveStream = webResponse.GetResponseStream();
            StreamReader readStream    = new StreamReader(receiveStream, Encoding.UTF8);
            string       responseData  = readStream.ReadToEnd();

            readStream.Close();
            receiveStream.Close();

            if ((int)webResponse.StatusCode >= 400)
            {
                APIException exception;
                try
                {
                    Error error = this._Deserialize <Error>(responseData);
                    exception                   = new APIException(error.Message);
                    exception.StatusCode        = webResponse.StatusCode;
                    exception.StatusDescription = webResponse.StatusDescription;
                }
                catch (Exception e)
                {
                    exception                   = new APIException("An error condition occurred from the API, but could not be deserialized.", e);
                    exception.StatusCode        = webResponse.StatusCode;
                    exception.StatusDescription = webResponse.StatusDescription;
                }
                throw exception;
            }
            else if (webResponse.StatusCode == HttpStatusCode.NoContent)
            {
                return(default(T));
            }

            //Bypass the serializer if the caller wants to handle it itself.
            if (typeof(T) == typeof(string))
            {
                return((T)Convert.ChangeType(responseData, typeof(T)));
            }
            else
            {
                return((T)this._Deserialize <T>(responseData));
            }
        }
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="connection">The API connection, provided by
 /// the SimplyCastAPI class.</param>
 public ResourceAPI(SimplyCastAPIConnector connection)
 {
     this.connection = connection;
 }