============ API Security ============ Overview ======== AgriSmart will provide you with a Key ID and a Secret. You'll use the secret to construct a SHA256 HMAC digest of the parameters to the API for each call. SSL Required ============ Calls to the API must be made using SSL. Any non-SSL calls will be rejected. Secret ====== The production secret we provide you must be kept secure. This secret is never transmitted across the wire and should be treated like a private key. Anyone who has access to your Key ID and Secret can make calls to our API on your behalf. Sample C# Code ============== Here is a simplistic sample C# client that can call any of our APIs: :: using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Net; using System.Web; using System.Security.Cryptography; using System.Text; using System.Threading.Tasks; namespace JobAPITest { class Client { public const bool DEV = true; public string KeyID { get; set; } public string Secret { get; set; } public string Path { get; set; } public string Method { get; set; } public string Body { get; set; } public SortedDictionary Parameters { get; private set; } public Client() { Method = "GET"; Parameters = new SortedDictionary(); } public string MakeRequest() { DateTime d = DateTime.Now.ToUniversalTime(); string ds = d.ToString("yyyyMMddHHmmss'Z'"); Debug.WriteLine(KeyID); Debug.WriteLine(ds); byte[] secretBytes = Encoding.UTF8.GetBytes(Secret); byte[] contentBytes = Encoding.UTF8.GetBytes(KeyID); HMACSHA256 sha256 = new HMACSHA256(secretBytes); byte[] keyBytes = sha256.ComputeHash(contentBytes); contentBytes = Encoding.UTF8.GetBytes(ds); sha256 = new HMACSHA256(keyBytes); keyBytes = sha256.ComputeHash(contentBytes); foreach (var item in Parameters) { contentBytes = Encoding.UTF8.GetBytes(item.Value); sha256 = new HMACSHA256(keyBytes); keyBytes = sha256.ComputeHash(contentBytes); } if ("GET" != Method) { contentBytes = Encoding.UTF8.GetBytes(Body); sha256 = new HMACSHA256(keyBytes); keyBytes = sha256.ComputeHash(contentBytes); } contentBytes = Encoding.UTF8.GetBytes(Path); sha256 = new HMACSHA256(keyBytes); keyBytes = sha256.ComputeHash(contentBytes); StringBuilder sb = new StringBuilder(); foreach (byte b in keyBytes) { sb.AppendFormat("{0:x2}", b); } Debug.WriteLine(sb.ToString()); StringBuilder urlBuilder = new StringBuilder(); string baseUrl = "https://staging.agrismartis.com"; if (DEV) baseUrl = "http://localdev.agrismartis.com:3000"; urlBuilder.AppendFormat("{0}{1}?kid={2}&date={3}&key={4}", baseUrl, Path, KeyID, ds, sb.ToString() ); if("GET" == Method) { foreach(var item in Parameters) { urlBuilder.AppendFormat("&{0}={1}", item.Key, item.Value); } } string url = urlBuilder.ToString(); Debug.WriteLine(url); HttpWebRequest wr = WebRequest.CreateHttp(url); wr.Method = Method; if("GET" != Method) { wr.ContentType = "application/json"; Debug.WriteLine(Body); byte[] formBytes = Encoding.UTF8.GetBytes(Body); wr.ContentLength = formBytes.Length; Stream requestStream = wr.GetRequestStream(); requestStream.Write(formBytes, 0, formBytes.Length); requestStream.Close(); } HttpWebResponse resp = null; try { resp = (HttpWebResponse)wr.GetResponse(); } catch (WebException ex) { resp = (HttpWebResponse)ex.Response; } StreamReader sr = new StreamReader(resp.GetResponseStream()); string body = sr.ReadToEnd(); Debug.WriteLine(url); Debug.WriteLine(body); return body.Replace("\n", "\r\n"); } } } This client can be used to call the POST method of the Jobs API like so: :: Client client = new Client(); client.KeyID = KeyID; client.Secret = Secret; client.Path = "/api/jobs"; client.Method = "POST"; client.Body = requestTextBox.Text.Trim(); resultsTextBox.Text = client.MakeRequest();