{"_id":"564d1afb4567342100ad96bf","user":"5515a6df07e9252f00348997","version":{"_id":"564d1af84567342100ad96aa","project":"551375e1d04af219007ddc52","__v":1,"createdAt":"2015-11-19T00:42:32.705Z","releaseDate":"2015-11-19T00:42:32.705Z","categories":["564d1af94567342100ad96ab","564d1af94567342100ad96ac","564d1af94567342100ad96ad","564d1af94567342100ad96ae","564d1af94567342100ad96af","564d1af94567342100ad96b0","564d1af94567342100ad96b1","564d1af94567342100ad96b2"],"is_deprecated":false,"is_hidden":false,"is_beta":false,"is_stable":true,"codename":"","version_clean":"1.1.0","version":"1.1"},"__v":6,"category":{"_id":"564d1af94567342100ad96ae","pages":["564d1afb4567342100ad96bb","564d1afb4567342100ad96bc","564d1afb4567342100ad96bd","564d1afb4567342100ad96be","564d1afb4567342100ad96bf"],"project":"551375e1d04af219007ddc52","version":"564d1af84567342100ad96aa","__v":1,"sync":{"url":"","isSync":false},"reference":false,"createdAt":"2015-03-27T02:56:56.435Z","from_sync":false,"order":3,"slug":"data-retrieval","title":"Data Retrieval"},"project":"551375e1d04af219007ddc52","updates":["55536137eac63f0d003e6b42"],"next":{"pages":[],"description":""},"createdAt":"2015-04-08T05:53:02.823Z","link_external":false,"link_url":"","githubsync":"","sync_unique":"","hidden":false,"api":{"results":{"codes":[]},"settings":"","auth":"required","params":[],"url":""},"isReference":false,"order":4,"body":"[block:callout]\n{\n  \"type\": \"info\",\n  \"title\": \"Syncing User Data\",\n  \"body\": \"Notifications are one way to keep you user's information up-to-date. For best practices, see [Keeping User Data Up-to-date](doc:data-synchronization).\"\n}\n[/block]\nHuman API Notifications will alert your application when a user has connected a device or has new data that is available to pull. Specifically, notifications are **sent whenever Human API servers receive new or updated user data** and are thus a great way to keep local user data within your app in sync.\n\nIn order to take advantage of notification functionality, there are a few steps that you will need to take described below.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Set Up a POST Endpoint to Receive Notifications\"\n}\n[/block]\n#Create Endpoint\nNotifications are sent via a POST request to a specified endpoint on your server.  Please create a dedicated endpoint and ensure that this endpoint:\n- Is publicly accessible\n- Accepts POST requests\n- Replies with a `200` status code within 3 seconds\n[block:callout]\n{\n  \"type\": \"warning\",\n  \"body\": \"Failed notifications may be discarded and continuous failures may result in notifications being disabled for your app. You can later reactivate notifications in the Developer Portal.\"\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"info\",\n  \"title\": \"HTTP/HTTPS\",\n  \"body\": \"Both HTTP and HTTPS endpoints are supported, though the latter is preferred for production environments.\"\n}\n[/block]\n#Update Developer Portal\nAfter creating an endpoint to receive notifications, you must then add it to your Human API account.\n\nTo do so, log into the Developer Portal, click the appropriate app and navigate to the Notifications page. On the Notifications page, check \"Enable notifications\", add the URL of the endpoint that you created in the \"Notify URL\" field and Save Changes. \n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/zSHPRPhTqyidhi8zdhsW_Screen%20Shot%202016-07-05%20at%205.55.15%20PM.png\",\n        \"Screen Shot 2016-07-05 at 5.55.15 PM.png\",\n        \"1300\",\n        \"791\",\n        \"#5488a6\",\n        \"\"\n      ]\n    }\n  ]\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"success\",\n  \"body\": \"To test your newly created endpoint, simply add a user to your application and connect a device. This should trigger a Notification from Human API that will display on the righthand side of the notifications page in blue as shown above.\",\n  \"title\": \"Testing Your Notifications Endpoint\"\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Authenticate Notification with HMAC-SHA1 Signature (optional)\"\n}\n[/block]\n\nAlong with HTTPS, using the notification signature (`X-HumanAPI-Signature`) is a good way to ensure that notifications are entering your system securely.  \n\nThe HMAC-SHA1 signature is calculated using `String(payload + timestamp + nonce)` as the message and your app's `Client Secret` (found under the Settings tab) as the key. For Node.js, we recommend that you use [`crypto-js`](https://www.npmjs.com/package/crypto-js) for this calculation like so:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"var crypto = require('crypto'); //npm install crypto-js --save\\n// ...\\n\\nvar payload = '{\\\"contents\\\":\\\"supersecretstuff\\\"}';\\nvar timestamp = 1403591492088;\\nvar nonce = 105850310064852240;\\n\\nvar clientSecret = 'itsfullofsecrets';\\n\\n// crypto.createHmac(algorithm, key)\\nvar signature = crypto.createHmac('sha1', clientSecret).update(payload + timestamp + nonce).digest('base64');\\n\\n//Correct Result:\\n//signature == \\\"fQkvPoMVwsZWM4/r4VrKlMaCOAw=\\\"\\n\\n//\",\n      \"language\": \"javascript\"\n    },\n    {\n      \"code\": \"using System;\\nusing System;\\nusing System.Collections.Generic;\\nusing System.Linq;\\nusing System.Text;\\nusing System.Security.Cryptography;\\nusing System.IO;\\n\\nnamespace test\\n{\\n\\tclass MainClass\\n\\t{\\n\\t\\tpublic static void Main (string[] args)\\n\\t\\t{\\n\\t\\t\\tstring payload   = \\\"{\\\\\\\"contents\\\\\\\":\\\\\\\"supersecretstuff\\\\\\\"}\\\";\\n\\t\\t\\tstring timestamp = \\\"1403591492088\\\";\\n\\t\\t\\tstring nonce\\t = \\\"105850310064852240\\\";\\n\\n\\t\\t\\tbyte[] signature = GenerateSignature(\\\"itsfullofsecrets\\\", payload + timestamp + nonce);\\n\\n\\t\\t\\tConsole.WriteLine(Convert.ToBase64String(signature));\\n\\t\\t}\\n\\n\\t\\tpublic static byte[] GenerateSignature(string secret, string content)\\n\\t\\t{\\n\\t\\t\\tHMACSHA1 myhmacsha1 = new HMACSHA1(Encoding.UTF8.GetBytes(secret));\\n\\t\\t\\tMemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(content));\\n\\t\\t\\treturn myhmacsha1.ComputeHash(stream);\\n\\t\\t}\\n\\t}\\n}\",\n      \"language\": \"csharp\"\n    }\n  ]\n}\n[/block]\nThere are also standard HMAC-SHA1 libraries for most languages.\n[block:callout]\n{\n  \"type\": \"success\",\n  \"title\": \"Testing Your Signature\",\n  \"body\": \"Use the demo data in the example above to test your implementation.\\n\\nCorrect Result : `fQkvPoMVwsZWM4/r4VrKlMaCOAw=`\"\n}\n[/block]\nFrom now on, so long as the `X-HumanAPI-Signature` == your calculated signature you can ensure that each notification is from us. If these values are not equal, you should ignore and not respond to that request.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Parse the Notification Payload\"\n}\n[/block]\n\nNotifications will be batched for performance, meaning that each notification may contain entries for multiple users.\n\n[block:callout]\n{\n  \"type\": \"warning\",\n  \"body\": \"Please note that only the app's owner can modify the notification settings.\"\n}\n[/block]\n\n# POST Header Structure\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"Content-Type: application/json; charset=utf-8\\nUser-Agent: HumanAPI/1.0\\n\\nX-HumanAPI-Nonce: 105850310064852240\\nX-HumanAPI-Timestamp: 1403591492088\\nX-HumanAPI-Signature: ZTQ0MDg3MmExYjg5ZmYOTA3Y2M4Zjc4NQ==\",\n      \"language\": \"javascript\"\n    }\n  ]\n}\n[/block]\n\n[block:parameters]\n{\n  \"data\": {\n    \"h-0\": \"property\",\n    \"h-1\": \"type\",\n    \"h-2\": \"description\",\n    \"1-0\": \"`User-Agent`\",\n    \"4-0\": \"`X-HumanAPI-Signature`\",\n    \"0-0\": \"`Content-Type`\",\n    \"4-1\": \"`String`\",\n    \"1-1\": \"`String`\",\n    \"0-2\": \"Payload type, always set to `application/json`\",\n    \"0-1\": \"`String`\",\n    \"1-2\": \"`HumanAPI` plus the notifications version (currently only 1.0)\",\n    \"2-0\": \"`X-HumanAPI-Nonce`\",\n    \"2-1\": \"`Integer`\",\n    \"2-2\": \"Random string used in calculating `X-HumanAPI-Signature`.\",\n    \"3-0\": \"`X-HumanAPI-Timestamp`\",\n    \"3-1\": \"`Integer`\",\n    \"4-2\": \"HMAC-SHA1 signature calculated from `String(payload + timestamp + nonce)` using your app's clientSecret as the key.\",\n    \"3-2\": \"Unix timestamp in seconds.\"\n  },\n  \"cols\": 3,\n  \"rows\": 5\n}\n[/block]\n\n# POST Payload Structure\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"[{\\n\\t\\\"humanId\\\": \\\"1cb3eb4ddef09ff8f59f990c104c31ac\\\",\\n\\t\\\"updatedAt\\\": \\\"2016-02-02T02:10:40+00:00\\\",\\n\\t\\\"type\\\": \\\"activitysegment\\\",\\n\\t\\\"model\\\": \\\"activitysegment\\\",\\n\\t\\\"action\\\": \\\"created\\\",\\n\\t\\\"objectId\\\": \\\"56b01020131e6208005bc346\\\",\\n\\t\\\"endpoint\\\": \\\"https://api.humanapi.co/v1/human/activities\\\"\\n}, {\\n\\t\\\"humanId\\\": \\\"1cb3eb4ddef09ff8f59f990c104c31ac\\\",\\n\\t\\\"updatedAt\\\": \\\"2016-02-02T02:10:40+00:00\\\",\\n\\t\\\"type\\\": \\\"activitysummary\\\",\\n\\t\\\"model\\\": \\\"activitysummary\\\",\\n\\t\\\"action\\\": \\\"updated\\\",\\n\\t\\\"objectId\\\": \\\"56b01020131e6208005bc351\\\",\\n\\t\\\"endpoint\\\": \\\"https://api.humanapi.co/v1/human/activities/summaries\\\"\\n}]\",\n      \"language\": \"json\",\n      \"name\": \"JSON Payload\"\n    }\n  ]\n}\n[/block]\n\n[block:parameters]\n{\n  \"data\": {\n    \"h-0\": \"property\",\n    \"h-1\": \"type\",\n    \"h-2\": \"description\",\n    \"0-0\": \"`humanId`\",\n    \"1-0\": \"`updatedAt`\",\n    \"0-1\": \"`String`\",\n    \"1-1\": \"`Date`\",\n    \"1-2\": \"The time at which the record was last updated on our servers (in UTC).\",\n    \"0-2\": \"The unique Human API ID of your app user.\",\n    \"2-0\": \"`type`\",\n    \"2-2\": \"Indicates the type of a `measurement` object.\",\n    \"2-1\": \"`String`\",\n    \"3-0\": \"`model`\",\n    \"3-1\": \"`String`\",\n    \"3-2\": \"The updated record's model.\",\n    \"5-2\": \"The record's unique ID, which can be added to the request route to grab only the updated record.\",\n    \"5-0\": \"`objectId`\",\n    \"5-1\": \"`String`\",\n    \"6-2\": \"The endpoint to which you can append the user's `accessToken` to query for data.\",\n    \"6-1\": \"`String`\",\n    \"6-0\": \"`endpoint`\",\n    \"4-0\": \"`action`\",\n    \"4-1\": \"`String`\",\n    \"4-2\": \"Either `created` or `updated`\"\n  },\n  \"cols\": 3,\n  \"rows\": 7\n}\n[/block]\n# Models & Type\n[block:callout]\n{\n  \"type\": \"warning\",\n  \"title\": \"Deprecated\",\n  \"body\": \"Model/type information has been deprecated. Instead, design your processing system to use the `endpoint` URL (see below for details).\"\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Responding To Notifications\"\n}\n[/block]\nTo respond to the notification and query for the updated data, simply use the provided `endpoint` and `objectId` attributes along with the `accessToken` on your server that corresponds with the provided `humanId`.\n\nSo, for the following notification:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n\\t\\\"humanId\\\": \\\"1cb3eb4ddef09ff8f59f990c104c31ac\\\",\\n\\t\\\"updatedAt\\\": \\\"2016-02-02T02:10:40+00:00\\\",\\n\\t\\\"type\\\": \\\"activitysegment\\\",\\n\\t\\\"model\\\": \\\"activitysegment\\\",\\n\\t\\\"action\\\": \\\"created\\\",\\n\\t\\\"objectId\\\": \\\"56b01020131e6208005bc346\\\",\\n\\t\\\"endpoint\\\": \\\"https://api.humanapi.co/v1/human/activities\\\"\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nThe appropriate query to generate would be:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"//endpoint+objectId+\\\"?access_token=\\\"+(accessToken from humanId)\\nhttps://api.humanapi.co/v1/human/activities/56b01020131e6208005bc346?access_token=<accessToken-for-humanId-1cb3eb4ddef09ff8f59f990c104c31ac>\",\n      \"language\": \"http\"\n    }\n  ]\n}\n[/block]","excerpt":"Using notifications, you can be notified when a user has connected a device or when new data is available.","slug":"notifications","type":"basic","title":"Notifications"}

Notifications

Using notifications, you can be notified when a user has connected a device or when new data is available.

[block:callout] { "type": "info", "title": "Syncing User Data", "body": "Notifications are one way to keep you user's information up-to-date. For best practices, see [Keeping User Data Up-to-date](doc:data-synchronization)." } [/block] Human API Notifications will alert your application when a user has connected a device or has new data that is available to pull. Specifically, notifications are **sent whenever Human API servers receive new or updated user data** and are thus a great way to keep local user data within your app in sync. In order to take advantage of notification functionality, there are a few steps that you will need to take described below. [block:api-header] { "type": "basic", "title": "Set Up a POST Endpoint to Receive Notifications" } [/block] #Create Endpoint Notifications are sent via a POST request to a specified endpoint on your server. Please create a dedicated endpoint and ensure that this endpoint: - Is publicly accessible - Accepts POST requests - Replies with a `200` status code within 3 seconds [block:callout] { "type": "warning", "body": "Failed notifications may be discarded and continuous failures may result in notifications being disabled for your app. You can later reactivate notifications in the Developer Portal." } [/block] [block:callout] { "type": "info", "title": "HTTP/HTTPS", "body": "Both HTTP and HTTPS endpoints are supported, though the latter is preferred for production environments." } [/block] #Update Developer Portal After creating an endpoint to receive notifications, you must then add it to your Human API account. To do so, log into the Developer Portal, click the appropriate app and navigate to the Notifications page. On the Notifications page, check "Enable notifications", add the URL of the endpoint that you created in the "Notify URL" field and Save Changes. [block:image] { "images": [ { "image": [ "https://files.readme.io/zSHPRPhTqyidhi8zdhsW_Screen%20Shot%202016-07-05%20at%205.55.15%20PM.png", "Screen Shot 2016-07-05 at 5.55.15 PM.png", "1300", "791", "#5488a6", "" ] } ] } [/block] [block:callout] { "type": "success", "body": "To test your newly created endpoint, simply add a user to your application and connect a device. This should trigger a Notification from Human API that will display on the righthand side of the notifications page in blue as shown above.", "title": "Testing Your Notifications Endpoint" } [/block] [block:api-header] { "type": "basic", "title": "Authenticate Notification with HMAC-SHA1 Signature (optional)" } [/block] Along with HTTPS, using the notification signature (`X-HumanAPI-Signature`) is a good way to ensure that notifications are entering your system securely. The HMAC-SHA1 signature is calculated using `String(payload + timestamp + nonce)` as the message and your app's `Client Secret` (found under the Settings tab) as the key. For Node.js, we recommend that you use [`crypto-js`](https://www.npmjs.com/package/crypto-js) for this calculation like so: [block:code] { "codes": [ { "code": "var crypto = require('crypto'); //npm install crypto-js --save\n// ...\n\nvar payload = '{\"contents\":\"supersecretstuff\"}';\nvar timestamp = 1403591492088;\nvar nonce = 105850310064852240;\n\nvar clientSecret = 'itsfullofsecrets';\n\n// crypto.createHmac(algorithm, key)\nvar signature = crypto.createHmac('sha1', clientSecret).update(payload + timestamp + nonce).digest('base64');\n\n//Correct Result:\n//signature == \"fQkvPoMVwsZWM4/r4VrKlMaCOAw=\"\n\n//", "language": "javascript" }, { "code": "using System;\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Security.Cryptography;\nusing System.IO;\n\nnamespace test\n{\n\tclass MainClass\n\t{\n\t\tpublic static void Main (string[] args)\n\t\t{\n\t\t\tstring payload = \"{\\\"contents\\\":\\\"supersecretstuff\\\"}\";\n\t\t\tstring timestamp = \"1403591492088\";\n\t\t\tstring nonce\t = \"105850310064852240\";\n\n\t\t\tbyte[] signature = GenerateSignature(\"itsfullofsecrets\", payload + timestamp + nonce);\n\n\t\t\tConsole.WriteLine(Convert.ToBase64String(signature));\n\t\t}\n\n\t\tpublic static byte[] GenerateSignature(string secret, string content)\n\t\t{\n\t\t\tHMACSHA1 myhmacsha1 = new HMACSHA1(Encoding.UTF8.GetBytes(secret));\n\t\t\tMemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(content));\n\t\t\treturn myhmacsha1.ComputeHash(stream);\n\t\t}\n\t}\n}", "language": "csharp" } ] } [/block] There are also standard HMAC-SHA1 libraries for most languages. [block:callout] { "type": "success", "title": "Testing Your Signature", "body": "Use the demo data in the example above to test your implementation.\n\nCorrect Result : `fQkvPoMVwsZWM4/r4VrKlMaCOAw=`" } [/block] From now on, so long as the `X-HumanAPI-Signature` == your calculated signature you can ensure that each notification is from us. If these values are not equal, you should ignore and not respond to that request. [block:api-header] { "type": "basic", "title": "Parse the Notification Payload" } [/block] Notifications will be batched for performance, meaning that each notification may contain entries for multiple users. [block:callout] { "type": "warning", "body": "Please note that only the app's owner can modify the notification settings." } [/block] # POST Header Structure [block:code] { "codes": [ { "code": "Content-Type: application/json; charset=utf-8\nUser-Agent: HumanAPI/1.0\n\nX-HumanAPI-Nonce: 105850310064852240\nX-HumanAPI-Timestamp: 1403591492088\nX-HumanAPI-Signature: ZTQ0MDg3MmExYjg5ZmYOTA3Y2M4Zjc4NQ==", "language": "javascript" } ] } [/block] [block:parameters] { "data": { "h-0": "property", "h-1": "type", "h-2": "description", "1-0": "`User-Agent`", "4-0": "`X-HumanAPI-Signature`", "0-0": "`Content-Type`", "4-1": "`String`", "1-1": "`String`", "0-2": "Payload type, always set to `application/json`", "0-1": "`String`", "1-2": "`HumanAPI` plus the notifications version (currently only 1.0)", "2-0": "`X-HumanAPI-Nonce`", "2-1": "`Integer`", "2-2": "Random string used in calculating `X-HumanAPI-Signature`.", "3-0": "`X-HumanAPI-Timestamp`", "3-1": "`Integer`", "4-2": "HMAC-SHA1 signature calculated from `String(payload + timestamp + nonce)` using your app's clientSecret as the key.", "3-2": "Unix timestamp in seconds." }, "cols": 3, "rows": 5 } [/block] # POST Payload Structure [block:code] { "codes": [ { "code": "[{\n\t\"humanId\": \"1cb3eb4ddef09ff8f59f990c104c31ac\",\n\t\"updatedAt\": \"2016-02-02T02:10:40+00:00\",\n\t\"type\": \"activitysegment\",\n\t\"model\": \"activitysegment\",\n\t\"action\": \"created\",\n\t\"objectId\": \"56b01020131e6208005bc346\",\n\t\"endpoint\": \"https://api.humanapi.co/v1/human/activities\"\n}, {\n\t\"humanId\": \"1cb3eb4ddef09ff8f59f990c104c31ac\",\n\t\"updatedAt\": \"2016-02-02T02:10:40+00:00\",\n\t\"type\": \"activitysummary\",\n\t\"model\": \"activitysummary\",\n\t\"action\": \"updated\",\n\t\"objectId\": \"56b01020131e6208005bc351\",\n\t\"endpoint\": \"https://api.humanapi.co/v1/human/activities/summaries\"\n}]", "language": "json", "name": "JSON Payload" } ] } [/block] [block:parameters] { "data": { "h-0": "property", "h-1": "type", "h-2": "description", "0-0": "`humanId`", "1-0": "`updatedAt`", "0-1": "`String`", "1-1": "`Date`", "1-2": "The time at which the record was last updated on our servers (in UTC).", "0-2": "The unique Human API ID of your app user.", "2-0": "`type`", "2-2": "Indicates the type of a `measurement` object.", "2-1": "`String`", "3-0": "`model`", "3-1": "`String`", "3-2": "The updated record's model.", "5-2": "The record's unique ID, which can be added to the request route to grab only the updated record.", "5-0": "`objectId`", "5-1": "`String`", "6-2": "The endpoint to which you can append the user's `accessToken` to query for data.", "6-1": "`String`", "6-0": "`endpoint`", "4-0": "`action`", "4-1": "`String`", "4-2": "Either `created` or `updated`" }, "cols": 3, "rows": 7 } [/block] # Models & Type [block:callout] { "type": "warning", "title": "Deprecated", "body": "Model/type information has been deprecated. Instead, design your processing system to use the `endpoint` URL (see below for details)." } [/block] [block:api-header] { "type": "basic", "title": "Responding To Notifications" } [/block] To respond to the notification and query for the updated data, simply use the provided `endpoint` and `objectId` attributes along with the `accessToken` on your server that corresponds with the provided `humanId`. So, for the following notification: [block:code] { "codes": [ { "code": "{\n\t\"humanId\": \"1cb3eb4ddef09ff8f59f990c104c31ac\",\n\t\"updatedAt\": \"2016-02-02T02:10:40+00:00\",\n\t\"type\": \"activitysegment\",\n\t\"model\": \"activitysegment\",\n\t\"action\": \"created\",\n\t\"objectId\": \"56b01020131e6208005bc346\",\n\t\"endpoint\": \"https://api.humanapi.co/v1/human/activities\"\n}", "language": "json" } ] } [/block] The appropriate query to generate would be: [block:code] { "codes": [ { "code": "//endpoint+objectId+\"?access_token=\"+(accessToken from humanId)\nhttps://api.humanapi.co/v1/human/activities/56b01020131e6208005bc346?access_token=<accessToken-for-humanId-1cb3eb4ddef09ff8f59f990c104c31ac>", "language": "http" } ] } [/block]