{"_id":"59e70b9ee027ae002e7d2ee8","category":{"_id":"59e70b9ee027ae002e7d2ed6","version":"59e70b9ee027ae002e7d2ed2","project":"5496d393f52a630b00519cdd","__v":0,"sync":{"url":"","isSync":false},"reference":false,"createdAt":"2014-12-21T18:05:46.941Z","from_sync":false,"order":3,"slug":"rest-api","title":"REST API"},"user":"5496d353f52a630b00519cdc","parentDoc":null,"project":"5496d393f52a630b00519cdd","version":{"_id":"59e70b9ee027ae002e7d2ed2","project":"5496d393f52a630b00519cdd","__v":2,"createdAt":"2017-10-18T08:06:54.462Z","releaseDate":"2017-10-18T08:06:54.462Z","categories":["59e70b9ee027ae002e7d2ed3","59e70b9ee027ae002e7d2ed4","59e70b9ee027ae002e7d2ed5","59e70b9ee027ae002e7d2ed6","59e70b9ee027ae002e7d2ed7","59e70b9ee027ae002e7d2ed8","59e70b9ee027ae002e7d2ed9","59e70b9ee027ae002e7d2eda","59e70b9ee027ae002e7d2edb","59e70b9ee027ae002e7d2edc","59e70b9ee027ae002e7d2edd","59e70b9ee027ae002e7d2ede","59e70b9ee027ae002e7d2edf","5b8661ccdd19310003a3fa0b"],"is_deprecated":false,"is_hidden":false,"is_beta":true,"is_stable":true,"codename":"","version_clean":"2.0.10","version":"2.0.10"},"githubsync":"","__v":0,"updates":[],"next":{"pages":[],"description":""},"createdAt":"2014-12-21T17:06:52.639Z","link_external":false,"link_url":"","sync_unique":"","hidden":false,"api":{"results":{"codes":[]},"settings":"","auth":"required","params":[],"url":""},"isReference":false,"order":1,"body":"##Requirements\n  * For query authentication you will need your Placer’s App Secret. App Secret is provided with the App Key after registering with Placer. \n  * It is highly recommended that you will fully implement and run (at least once) one of Placer’s SDK’s for Android or iOS to collect data, so server queries will not return empty.\n \n##REST API\nThe base URL for all production queries is: https://api.placer.io.\nRequests are done using HTTP GET method.\n\nFor example, the following request generates a list of 10 devices linked to your app:\n*https://api.placer.io/v2/apps/324123/devices?timestamp=1261496500&limit=10&signature=abcdef0123456789* \n\nQuery results are being returned in a JSON format.\n\n##Authentication\nPlacer uses a hash-based message authentication code (HMAC) for server to server queries. The App Secret you received from Placer will never be sent directly to the server, but a hash-code based on it will be sent instead.\nPlacer’s uses HMAC-SHA1 function for generating the signature.\n\n##Generating and adding the signature to query\nThe signature is based on signing the query parameters while they are sorted in alphabetical order. Your Placer’s App Secret is used as the signing token. \nNotes:\n  * All queries must be added with a “timestamp” parameter. Timestamp denotes seconds since epoch in UTC. Requests older than 3 minutes will not be honored.\n  * Be sure to generate the hash before URL encoding of the query string and parameters. \n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Example\"\n}\n[/block]\nHere is an example of a GET request to generate a list of Placer’s devices in your app:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"https://api.placer.io/v2/apps/324123/devices?timestamp=1261496500&limit=10\",\n      \"language\": \"curl\"\n    }\n  ]\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"warning\",\n  \"body\": \"This request was added with the mandatory timestamp value and is missing the signature\",\n  \"title\": \"Notice\"\n}\n[/block]\n##Steps in generating the signature\n1 - Identify the parameters\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"timestamp=1261496500,limit=10\",\n      \"language\": \"html\"\n    }\n  ]\n}\n[/block]\n2 - Sort them in alphabetical order using the “key”  (in lower case): \n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"limit=10timestamp=1261496500\",\n      \"language\": \"curl\"\n    }\n  ]\n}\n[/block]\n3 - Add the URL path (“/v2/apps/324123/devices”) and concatenate to one string:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"/v2/apps/324123/deviceslimit10timestamp1261496500\",\n      \"language\": \"curl\"\n    }\n  ]\n}\n[/block]\n4 - Use HMAC-SHA1 function with the new string and Placer’ App Secret to generate the signature.\n\n\n5 - Add the signature to the query:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"https://api.placer.io/v2/apps/324123/devices?timestamp=1261496500&limit=10&signature=abcdef0123456789\",\n      \"language\": \"curl\"\n    }\n  ]\n}\n[/block]\n##All done! \nThe query will be authenticated and list of devices will be returned.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Python Example\"\n}\n[/block]\n[Download the example .py file](http://storage.googleapis.com/public_drops/PlacerExample.py.zip)\n##Calculate signature function\nThe following code can be used to calculate the signature over the request elements:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"import hmac\\nimport hashlib\\nimport urlparse\\n\\ndef calc_signature_over_request(url, query_dict, signing_key):\\n   \\\"\\\"\\\"\\n   Returns the calculated signature over the request query.\\n   params:\\n       url - the 'path' part of the entire url. If complete url is provided, the path  will be calculated from it.\\n\\n       query_dict - dictionary containing the query parameters. If complete url is provided, the query dict will be calculated from it.\\n\\n       signing_key - The key used for calculating the signature. Should be the application secret.\\n\\n   \\\"\\\"\\\"\\n   url_parts = urlparse.urlparse(url)\\n   url_path = url_parts.path\\n\\n   if not query_dict and url_parts.query:\\n       query_dict = urlparse.parse_qs(url_parts.query, keep_blank_values=True)\\n\\n   h = hmac.new(signing_key, digestmod=hashlib.sha1)\\n   h.update(url_path)\\n\\n   for key in sorted(query_dict.keys()): # sort keys in lexicographic order\\n       key_lower = str(key).lower()\\n       if key_lower == 'signature':  # skip the signature params when calculating signature\\n           continue\\n\\n       h.update(key_lower)\\n\\n       value_list = query_dict[key]\\n       if not isinstance(value_list, list):\\n           # treat all params as if they are lists\\n           value_list = [value_list, ]\\n\\n       for item in sorted(value_list):\\n           item_lower = str(item).lower()\\n           h.update(item_lower)\\n\\n   signature = h.hexdigest()\\n   return signature\",\n      \"language\": \"python\"\n    }\n  ]\n}\n[/block]\n##Usage\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"APP_KEY = \\\"YOUR_KEY\\\"\\nAPP_SECRET = \\\"YOUR_SECRET\\\"\\n\\nBASE_URL = \\\"https://api.placer.io\\\"\\nQUERY = {\\n   'limit': 20,\\n   'timestamp': int(calendar.timegm(time.gmtime())),\\n}\\nURL = \\\"/v2/apps/\\\"+APP_KEY+\\\"/devices\\\"\\n\\nsignature = calc_signature_over_request(URL, QUERY, APP_SECRET)\\nQUERY['signature'] = signature # add signature as query param\\n\\nimport urllib\\n\\n# construct the url\\nencoded_params = urllib.urlencode(QUERY)\\n\\nfull_url = BASE_URL + URL + \\\"?\\\" + encoded_params\\nprint(full_url)\\n\\n# send request\\nf = urllib.urlopen(full_url)\\ndata = json.loads(f.read())\",\n      \"language\": \"python\"\n    }\n  ]\n}\n[/block]","excerpt":"Implementing the Server-to-server API will allow you to fully utilize the capabilities of Placer’s insights for your application and service.\nThis section describes all the necessary information you need for getting started with server authenticated queries.","slug":"server-2-server-rest-api","type":"basic","title":"Authentication"}

Authentication

Implementing the Server-to-server API will allow you to fully utilize the capabilities of Placer’s insights for your application and service. This section describes all the necessary information you need for getting started with server authenticated queries.

##Requirements * For query authentication you will need your Placer’s App Secret. App Secret is provided with the App Key after registering with Placer. * It is highly recommended that you will fully implement and run (at least once) one of Placer’s SDK’s for Android or iOS to collect data, so server queries will not return empty. ##REST API The base URL for all production queries is: https://api.placer.io. Requests are done using HTTP GET method. For example, the following request generates a list of 10 devices linked to your app: *https://api.placer.io/v2/apps/324123/devices?timestamp=1261496500&limit=10&signature=abcdef0123456789* Query results are being returned in a JSON format. ##Authentication Placer uses a hash-based message authentication code (HMAC) for server to server queries. The App Secret you received from Placer will never be sent directly to the server, but a hash-code based on it will be sent instead. Placer’s uses HMAC-SHA1 function for generating the signature. ##Generating and adding the signature to query The signature is based on signing the query parameters while they are sorted in alphabetical order. Your Placer’s App Secret is used as the signing token. Notes: * All queries must be added with a “timestamp” parameter. Timestamp denotes seconds since epoch in UTC. Requests older than 3 minutes will not be honored. * Be sure to generate the hash before URL encoding of the query string and parameters. [block:api-header] { "type": "basic", "title": "Example" } [/block] Here is an example of a GET request to generate a list of Placer’s devices in your app: [block:code] { "codes": [ { "code": "https://api.placer.io/v2/apps/324123/devices?timestamp=1261496500&limit=10", "language": "curl" } ] } [/block] [block:callout] { "type": "warning", "body": "This request was added with the mandatory timestamp value and is missing the signature", "title": "Notice" } [/block] ##Steps in generating the signature 1 - Identify the parameters [block:code] { "codes": [ { "code": "timestamp=1261496500,limit=10", "language": "html" } ] } [/block] 2 - Sort them in alphabetical order using the “key” (in lower case): [block:code] { "codes": [ { "code": "limit=10timestamp=1261496500", "language": "curl" } ] } [/block] 3 - Add the URL path (“/v2/apps/324123/devices”) and concatenate to one string: [block:code] { "codes": [ { "code": "/v2/apps/324123/deviceslimit10timestamp1261496500", "language": "curl" } ] } [/block] 4 - Use HMAC-SHA1 function with the new string and Placer’ App Secret to generate the signature. 5 - Add the signature to the query: [block:code] { "codes": [ { "code": "https://api.placer.io/v2/apps/324123/devices?timestamp=1261496500&limit=10&signature=abcdef0123456789", "language": "curl" } ] } [/block] ##All done! The query will be authenticated and list of devices will be returned. [block:api-header] { "type": "basic", "title": "Python Example" } [/block] [Download the example .py file](http://storage.googleapis.com/public_drops/PlacerExample.py.zip) ##Calculate signature function The following code can be used to calculate the signature over the request elements: [block:code] { "codes": [ { "code": "import hmac\nimport hashlib\nimport urlparse\n\ndef calc_signature_over_request(url, query_dict, signing_key):\n \"\"\"\n Returns the calculated signature over the request query.\n params:\n url - the 'path' part of the entire url. If complete url is provided, the path will be calculated from it.\n\n query_dict - dictionary containing the query parameters. If complete url is provided, the query dict will be calculated from it.\n\n signing_key - The key used for calculating the signature. Should be the application secret.\n\n \"\"\"\n url_parts = urlparse.urlparse(url)\n url_path = url_parts.path\n\n if not query_dict and url_parts.query:\n query_dict = urlparse.parse_qs(url_parts.query, keep_blank_values=True)\n\n h = hmac.new(signing_key, digestmod=hashlib.sha1)\n h.update(url_path)\n\n for key in sorted(query_dict.keys()): # sort keys in lexicographic order\n key_lower = str(key).lower()\n if key_lower == 'signature': # skip the signature params when calculating signature\n continue\n\n h.update(key_lower)\n\n value_list = query_dict[key]\n if not isinstance(value_list, list):\n # treat all params as if they are lists\n value_list = [value_list, ]\n\n for item in sorted(value_list):\n item_lower = str(item).lower()\n h.update(item_lower)\n\n signature = h.hexdigest()\n return signature", "language": "python" } ] } [/block] ##Usage [block:code] { "codes": [ { "code": "APP_KEY = \"YOUR_KEY\"\nAPP_SECRET = \"YOUR_SECRET\"\n\nBASE_URL = \"https://api.placer.io\"\nQUERY = {\n 'limit': 20,\n 'timestamp': int(calendar.timegm(time.gmtime())),\n}\nURL = \"/v2/apps/\"+APP_KEY+\"/devices\"\n\nsignature = calc_signature_over_request(URL, QUERY, APP_SECRET)\nQUERY['signature'] = signature # add signature as query param\n\nimport urllib\n\n# construct the url\nencoded_params = urllib.urlencode(QUERY)\n\nfull_url = BASE_URL + URL + \"?\" + encoded_params\nprint(full_url)\n\n# send request\nf = urllib.urlopen(full_url)\ndata = json.loads(f.read())", "language": "python" } ] } [/block]