{"info":{"_postman_id":"9efb6fb4-a1a8-4b6e-8891-51ecb5c85492","name":"Surfact API Platform","description":"<html><head></head><body><img src=\"https://content.pstmn.io/56b670e9-a586-4ab5-817c-f47343933dc5/U3VyZmFjdCBEZXZlbG9wZXJzLnBuZw==\" width=\"507\" height=\"313\">\n\n<h3 id=\"surfact-apis-for-integration-partners\"><strong>Surfact APIs for Integration Partners</strong></h3>\n<h4 id=\"📨-get-started-request-api-credentials-by-reaching-out-to-us-through-this-form\"><strong>📨 Get started:</strong> Request API credentials by reaching out to us <a href=\"https://help.surfact.com/en/articles/10494482-integrating-surfact-via-api?intercom_survey_id=53252676\"><b>through this form.</b></a></h4>\n<p>Surfact provides a powerful, API-driven platform to manage and query data from devices belonging to your organization. We support <strong><code>REST</code></strong>, <strong><code>MQTT</code></strong> and <strong><code>Webhooks</code></strong>. This collection will provide you the essentials - from fetching device and variable data to setting up alerts/triggers that can be integrated into your fleet, warehouse, ERP, or transport management system.</p>\n<h4 id=\"not-getting-200-ok-drop-us-a-line-at-supportsurfactcom\"><strong>Not getting</strong> <strong><code>200</code></strong> <strong>OK?</strong> Drop us a line at: <a href=\"https://mailto:support@surfact.com\">support@surfact.com</a></h4>\n</body></html>","schema":"https://schema.getpostman.com/json/collection/v2.0.0/collection.json","toc":[],"owner":"43563920","collectionId":"9efb6fb4-a1a8-4b6e-8891-51ecb5c85492","publishedId":"2sB2x8FrET","public":true,"customColor":{"top-bar":"000000","right-sidebar":"303030","highlight":"1FA377"},"publishDate":"2025-07-10T15:34:47.000Z"},"item":[{"name":"Getting Started","item":[{"name":"Authentication","item":[],"id":"08a02df4-134d-4a04-b4b1-c0edd39fb1cf","description":"<p>Every request to the Surfact API requires a token. A token is a unique key that authorizes your requests.</p>\n<h2 id=\"getting-an-api-token\">Getting an API Token</h2>\n<p>Your API token is available in the My Profile section of your Surfact account.</p>\n<h2 id=\"sending-your-token\">Sending Your Token</h2>\n<h3 id=\"method-1-header-recommended\">Method 1: Header (Recommended)</h3>\n<p>Include the token in the request header:</p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code>X-Auth-Token: your_token_here\n\n</code></pre><p><strong>Example:</strong></p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-bash\">curl -X POST 'https://api.surfact.com/api/v2.0/devices/' \\\n  -H 'Content-Type: application/json' \\\n  -H 'X-Auth-Token: oaXBo6ODhIjPsusNRPUGIK4d72bc73' \\\n  -d '{}'\n\n</code></pre>\n<hr />\n<p>For web and mobile applications, Surfact supports OAuth2 bearer tokens. Contact us for implementation details if you are considering this approach.</p>\n","_postman_id":"08a02df4-134d-4a04-b4b1-c0edd39fb1cf","auth":{"type":"noauth","isInherited":true,"source":{"_postman_id":"bb149234-c87f-4bc8-962b-0ecf72fc6904","id":"bb149234-c87f-4bc8-962b-0ecf72fc6904","name":"Getting Started","type":"folder"}}},{"name":"Data Structure Overview","item":[],"id":"014d2dfe-c61d-4416-b4cd-1093a3e6f8ec","description":"<img src=\"https://content.pstmn.io/b6a62ce7-67d3-4984-a205-a655d684be5c/aW1hZ2UucG5n\" alt=\"Data%20Structure%20Overview%20for%20Surfact%20Platform\" width=\"536\" height=\"377\" />\n\n<h1 id=\"how-the-surfact-platform-works\">How The Surfact Platform Works</h1>\n<p>Every time a device updates a sensor value in a variable, a data-point or \"dot\" is created. Surfact stores dots that come from your devices inside variables, and these stored dots have corresponding timestamps.</p>\n<hr />\n<h2 id=\"data-structure\">Data Structure</h2>\n<p>Each dot contains these items:</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Item</th>\n<th>Description</th>\n<th>Mandatory</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>value</code></td>\n<td>A numerical value. Surfact accepts up to 16 floating-point length numbers.</td>\n<td>Yes</td>\n</tr>\n<tr>\n<td><code>timestamp</code></td>\n<td>Unix Epoch time, in milliseconds. If not specified, our servers will assign one upon reception.</td>\n<td>No</td>\n</tr>\n<tr>\n<td><code>context</code></td>\n<td>An arbitrary collection of key-value pairs. Mostly used to store the latitude and longitude coordinates of GPS devices.</td>\n<td>No</td>\n</tr>\n</tbody>\n</table>\n</div><hr />\n<h2 id=\"values\">Values</h2>\n<p>A numerical value. Surfact accepts up to 16 floating-point length numbers.</p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-json\">{\n  \"value\": 34.87654974\n}\n\n</code></pre>\n<hr />\n<h2 id=\"timestamps\">Timestamps</h2>\n<p>A timestamp is a way to track time as a running total of seconds. This count starts at the Unix Epoch on January 1st, 1970 at UTC.</p>\n<p>When you send data to Surfact, you must set the timestamp in <strong>milliseconds</strong>. If you retrieve a dot's timestamp, it will also be in milliseconds.</p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-json\">{\n  \"timestamp\": 1537453824000\n}\n\n</code></pre>\n<p>The above timestamp corresponds to <strong>Thursday, September 20, 2018 2:30:24 PM</strong>.</p>\n<p>💡 <strong>Pro Tip:</strong> Use <a href=\"https://www.epochconverter.com/\">Epoch Converter</a> to convert between Unix timestamps and human-readable dates.</p>\n<hr />\n<h2 id=\"context\">Context</h2>\n<p>Numerical values are not the only data type supported. You can also store string or char data types inside what we call <strong>context</strong>. The context is a key-value object that allows you to store both numerical and string values.</p>\n<p><strong>Example:</strong></p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-json\">{\n  \"context\": {\n    \"status\": \"on\",\n    \"weather\": \"sunny\"\n  }\n}\n\n</code></pre>\n<h3 id=\"gps-coordinates\">GPS Coordinates</h3>\n<p>Context is commonly used to store the latitude and longitude coordinates of your device for GPS/tracking applications. All Surfact maps use the <code>lat</code> and <code>lng</code> keys from a dot's context to extract your device's coordinates.</p>\n<p>This means you only need to send a single dot with the coordinates in the variable context to plot a map, instead of sending latitude and longitude separately in two different variables.</p>\n<p><strong>Example with GPS coordinates:</strong></p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-json\">{\n  \"context\": {\n    \"lat\": -6.2,\n    \"lng\": 75.4,\n    \"weather\": \"sunny\"\n  }\n}\n\n</code></pre>\n<p>⚠️ <strong>Note:</strong> You can mix both string and numerical values in the context. For geo-localization applications, make sure coordinates are set in decimal degrees.</p>\n","_postman_id":"014d2dfe-c61d-4416-b4cd-1093a3e6f8ec","auth":{"type":"noauth","isInherited":true,"source":{"_postman_id":"bb149234-c87f-4bc8-962b-0ecf72fc6904","id":"bb149234-c87f-4bc8-962b-0ecf72fc6904","name":"Getting Started","type":"folder"}}},{"name":"Identifiers - Key vs. ID","item":[],"id":"75f27009-851c-4844-9926-a4a5dbec206f","description":"<p>This section explains the difference between using keys or IDs.</p>\n<hr />\n<h2 id=\"key-as-path-parameter\">Key as Path Parameter</h2>\n<p>A <strong>key</strong> is an identifier that allows you to identify entities such as Devices or Variables. Entity Key parameters in the path are defined as , e.g. .</p>\n<p>Entity Keys allow you to identify the entity instance with their corresponding <code>id</code> or <code>label</code>. The label identification should use the prefix <code>~</code>.</p>\n<p><strong>Example:</strong></p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-bash\"># GET Request to Obtain a Specific Device\n# URL Definition\nhttps://api.surfact.com/api/v2.0/devices/&lt;device_key&gt;/\n# Identification using Device Id\nhttps://api.surfact.com/api/v2.0/devices/4f169cc906d07d65aa7a/\n# Identification using Device Label\nhttps://api.surfact.com/api/v2.0/devices/~first-device/\n\n</code></pre>\n<hr />\n<h2 id=\"id-as-path-parameter\">Id as Path Parameter</h2>\n<p>An <strong>id</strong> is an identifier that allows you to identify entities such as Devices or Variables. Entity Id parameters in the path are defined as , e.g. .</p>\n<p>Entity Ids allow you to identify the entity instance only by their <code>id</code>.</p>\n<p><strong>Example:</strong></p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-bash\"># GET Request to Obtain a Specific Event Log\n# URL Definition\nhttps://api.surfact.com/api/v2.0/events/&lt;event_key&gt;/logs/&lt;log_id&gt;/\n# Identification using Log Id\nhttps://api.surfact.com/api/v2.0/events/&lt;event_key&gt;/logs/6d07d65aa7a4f169cc90/\n\n</code></pre>\n<hr />\n<h2 id=\"key-as-body-parameter\">Key as Body Parameter</h2>\n<p>Certain POST requests have an entity parameter. A good example is the request to Create an Event. This request has <code>organization</code> as an <code>organization_key</code> parameter.</p>\n<p>When creating an event, the organization parameter can be sent in any of the following ways:</p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-bash\"># POST Request to Create an Event\ncurl -X POST 'https://api.surfact.com/api/v2.0/events/' \\\n  -H 'Content-Type: application/json' \\\n  -H 'X-Auth-Token: oaXBo6ODhIjPsusNRPUGIK4d72bc73' \\\n  -d '{\n    # Sending Organization using the Id\n    \"organization\": \"567890ff1d8472686e9abb4f\"\n    # Sending Organization using the Label\n    \"organization\": \"~first-organization\"\n    # Sending Organization as Object\n    \"organization\": {\"id\": \"567890ff1d8472686e9abb4f\"}\n  }'\n\n</code></pre>\n<hr />\n<h2 id=\"id-as-body-parameter\">Id as Body Parameter</h2>\n<p>It's simple: all entity parameters in the body are <strong>Keys</strong>, hence they can be identified with their <code>id</code>, but also as an object or with their <code>label</code>.</p>\n","_postman_id":"75f27009-851c-4844-9926-a4a5dbec206f","auth":{"type":"noauth","isInherited":true,"source":{"_postman_id":"bb149234-c87f-4bc8-962b-0ecf72fc6904","id":"bb149234-c87f-4bc8-962b-0ecf72fc6904","name":"Getting Started","type":"folder"}}},{"name":"Response Codes","item":[],"id":"b47b5a47-48cb-4d62-b8c0-1d80475452b2","description":"<p>When you make an HTTP request, the Surfact API returns standard HTTP status codes to indicate success or failure:</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Code</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><strong>200</strong></td>\n<td>OK - Request successful</td>\n</tr>\n<tr>\n<td><strong>201</strong></td>\n<td>Created - Request successful and a resource (device or variable) was created</td>\n</tr>\n<tr>\n<td><strong>202</strong></td>\n<td>Accepted - Request accepted for processing, but not yet completed</td>\n</tr>\n<tr>\n<td><strong>204</strong></td>\n<td>No Content - One of the fields is incorrect and the request was not saved. Verify your JSON is valid and fields match the expected types (string, object, or float)</td>\n</tr>\n<tr>\n<td><strong>400</strong></td>\n<td>Bad Request - Invalid request body. Verify your JSON is valid and fields match the expected endpoint types</td>\n</tr>\n<tr>\n<td><strong>401</strong></td>\n<td>Unauthorized - Invalid API key. Check your API key</td>\n</tr>\n<tr>\n<td><strong>402</strong></td>\n<td>Payment Required - Check your account balance</td>\n</tr>\n<tr>\n<td><strong>403</strong></td>\n<td>Forbidden - Invalid token. Verify your authentication token</td>\n</tr>\n<tr>\n<td><strong>404</strong></td>\n<td>Not Found - The requested resource doesn't exist. Check for typos in device/variable labels, IDs, or the request URL</td>\n</tr>\n<tr>\n<td><strong>405</strong></td>\n<td>Method Not Allowed - This endpoint doesn't support the HTTP method used. See the API documentation for allowed methods</td>\n</tr>\n<tr>\n<td><strong>415</strong></td>\n<td>Unsupported Media Type - The request payload format is not supported</td>\n</tr>\n<tr>\n<td><strong>420</strong></td>\n<td>Rate Limit Exceeded - You've exceeded your API limits. Contact Surfact support to upgrade</td>\n</tr>\n<tr>\n<td><strong>423</strong></td>\n<td>Locked - Device is disabled and cannot receive data</td>\n</tr>\n<tr>\n<td><strong>429</strong></td>\n<td>Too Many Requests - Rate limiting in effect. Reduce request frequency</td>\n</tr>\n<tr>\n<td><strong>50x</strong></td>\n<td>Server Error - Surfact is experiencing server issues. Check the status page or try again later</td>\n</tr>\n</tbody>\n</table>\n</div>","_postman_id":"b47b5a47-48cb-4d62-b8c0-1d80475452b2","auth":{"type":"noauth","isInherited":true,"source":{"_postman_id":"bb149234-c87f-4bc8-962b-0ecf72fc6904","id":"bb149234-c87f-4bc8-962b-0ecf72fc6904","name":"Getting Started","type":"folder"}}}],"id":"bb149234-c87f-4bc8-962b-0ecf72fc6904","auth":{"type":"noauth","isInherited":false},"event":[{"listen":"prerequest","script":{"id":"396d1ea5-2c09-4a71-a354-9c00687d0f59","type":"text/javascript","packages":{},"requests":{},"exec":[""]}},{"listen":"test","script":{"id":"98e6fc4a-e4a6-465e-98eb-8de26dc9d5a8","type":"text/javascript","packages":{},"requests":{},"exec":["default test this org","//try this one out",""]}}],"_postman_id":"bb149234-c87f-4bc8-962b-0ecf72fc6904","description":""},{"name":"🌡️ Device Data API","item":[{"name":"Variable Data","id":"4a34bc2f-1763-4f38-8f2a-1b74cefc9896","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[],"url":"https://api.surfact.com/api/v1.6/variables/<variable_id>/values","description":"<p>This endpoint retrieves variable data points.</p>\n<p>Where variable_ID is the ID of the variable from which data will be retrieved.</p>\n<blockquote>\n<p><strong>Default Behavior:</strong> This endpoint retrieves the last 100 data points by default. Use query parameters to filter the request. </p>\n</blockquote>\n<hr />\n<h2 id=\"headers\">Headers</h2>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Header</th>\n<th>Value</th>\n<th>Required</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>X-Auth-Token</td>\n<td>Token</td>\n<td>Yes</td>\n<td>Authentication token</td>\n</tr>\n</tbody>\n</table>\n</div><hr />\n<h2 id=\"query-parameters\">Query Parameters</h2>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Parameter</th>\n<th>Type</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>token</code></td>\n<td>String</td>\n<td>Token to authenticate the request (alternative to header)</td>\n</tr>\n<tr>\n<td><code>page</code></td>\n<td>Integer</td>\n<td>Page number within the paginated result set</td>\n</tr>\n<tr>\n<td><code>page_size</code></td>\n<td>Integer</td>\n<td>Number of results to return per page</td>\n</tr>\n<tr>\n<td><code>start</code></td>\n<td>Integer</td>\n<td>Initial timestamp in milliseconds POSIX format (inclusive)</td>\n</tr>\n<tr>\n<td><code>end</code></td>\n<td>Integer</td>\n<td>Final timestamp in milliseconds POSIX format (inclusive)</td>\n</tr>\n<tr>\n<td><code>format</code></td>\n<td>String</td>\n<td>Format to retrieve the data (<code>json</code> or <code>csv</code>)</td>\n</tr>\n</tbody>\n</table>\n</div><hr />\n<h2 id=\"examples\">Examples</h2>\n<h3 id=\"get-last-data-point\">Get Last Data Point</h3>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-bash\">curl -X GET &amp;#x27;https://api.surfact.com/api/v1.6/variables/&lt;variable_id&gt;/values/?page_size=1&amp;#x27; \\\n  -H 'X-Auth-Token: oaXBo6ODhIjPsusNRPUGIK4d72bc73'\n\n</code></pre>\n<p><strong>Response:</strong></p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-json\">{\n  \"count\": true,\n  \"next\": \"https://api.surfact.com/api/v1.6/variables/&lt;variable_id&gt;/values/?page_size=1&amp;page=2\",\n  \"previous\": null,\n  \"results\": [\n    {\n      \"timestamp\": 1635264014782,\n      \"value\": 0,\n      \"context\": {},\n      \"created_at\": 1635264014782\n    }\n  ]\n}\n\n</code></pre>\n<hr />\n<h3 id=\"get-last-two-data-points\">Get Last Two Data Points</h3>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-bash\">curl -X GET &amp;#x27;https://api.surfact.com/api/v1.6/variables/&lt;variable_id&gt;/values/?page_size=2&amp;#x27; \\\n  -H 'X-Auth-Token: oaXBo6ODhIjPsusNRPUGIK4d72bc73'\n\n</code></pre>\n<p><strong>Response:</strong></p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-json\">{\n  \"count\": true,\n  \"next\": \"https://api.surfact.com/api/v1.6/variables/&lt;variable_id&gt;/values/?page_size=2&amp;page=2\",\n  \"previous\": null,\n  \"results\": [\n    {\n      \"timestamp\": 1635264014782,\n      \"value\": 0,\n      \"context\": {},\n      \"created_at\": 1635264014782\n    },\n    {\n      \"timestamp\": 1635264000173,\n      \"value\": 0,\n      \"context\": {},\n      \"created_at\": 1635264000173\n    }\n  ]\n}\n\n</code></pre>\n<hr />\n<h3 id=\"get-data-points-in-time-range\">Get Data Points in Time Range</h3>\n<p>Retrieves data points between 21/10/2021 00:00:00 and 21/10/2021 00:30:00:</p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-bash\">curl -X GET &amp;#x27;https://api.surfact.com/api/v1.6/variables/&lt;variable_id&gt;/values/?start=1634792400000&amp;end=1634794200000&amp;#x27; \\\n  -H 'X-Auth-Token: oaXBo6ODhIjPsusNRPUGIK4d72bc73'\n\n</code></pre>\n<p><strong>Response:</strong></p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-json\">{\n  \"count\": true,\n  \"next\": null,\n  \"previous\": null,\n  \"results\": [\n    {\n      \"timestamp\": 1634793902308,\n      \"value\": 65084.81,\n      \"context\": {\n        \"Currency\": \"USD\"\n      },\n      \"created_at\": 1634793902308\n    },\n    {\n      \"timestamp\": 1634793603356,\n      \"value\": 65006.39,\n      \"context\": {\n        \"Currency\": \"USD\"\n      },\n      \"created_at\": 1634793603356\n    }\n  ]\n}\n\n</code></pre>\n<hr />\n<h3 id=\"get-data-points-from-a-specific-date\">Get Data Points From a Specific Date</h3>\n<p>Retrieves all data points from 21/10/2021 00:00:00 to present:</p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-bash\">curl -X GET &amp;#x27;https://api.surfact.com/api/v1.6/variables/&lt;variable_id&gt;/values/?start=1634792400000&amp;#x27; \\\n  -H 'X-Auth-Token: oaXBo6ODhIjPsusNRPUGIK4d72bc73'\n\n</code></pre>\n<p><strong>Response:</strong></p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-json\">{\n  \"count\": true,\n  \"next\": \"https://api.surfact.com/api/v1.6/variables/&lt;variable_id&gt;/values/?start=1634792400000&amp;page=2\",\n  \"previous\": null,\n  \"results\": [\n    {\n      \"timestamp\": 1635368101148,\n      \"value\": 58920.82,\n      \"context\": {\n        \"Currency\": \"USD\"\n      },\n      \"created_at\": 1635368101148\n    }\n  ]\n}\n\n</code></pre>\n<hr />\n<h3 id=\"get-data-points-in-csv-format\">Get Data Points in CSV Format</h3>\n<p>Retrieves data points in CSV format:</p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-bash\">curl -X GET &amp;#x27;https://api.surfact.com/api/v1.6/variables/&lt;variable_id&gt;/values/?start=1634792400000&amp;end=1634794200000&amp;format=csv&amp;#x27; \\\n  -H 'X-Auth-Token: oaXBo6ODhIjPsusNRPUGIK4d72bc73'\n\n</code></pre>\n<p><strong>Response:</strong></p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-csv\">context.Currency,created_at,human_readable_date,timestamp,value\nUSD,1634793902308,2021-10-21 01:25:02.308000-04:00,1634793902308,65084.81\nUSD,1634793603356,2021-10-21 01:20:03.356000-04:00,1634793603356,65006.39\nUSD,1634793302168,2021-10-21 01:15:02.168000-04:00,1634793302168,65120.26\n\n</code></pre>\n<hr />\n<h2 id=\"error-response\">Error Response</h2>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-json\">{\n  \"code\": 401002,\n  \"message\": \"Incorrect authentication credentials.\"\n}\n\n</code></pre>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"X-Auth-Token"}]},"isInherited":true,"source":{"_postman_id":"1ce9948b-87a0-41a6-a2da-3fbd10883b7c","id":"1ce9948b-87a0-41a6-a2da-3fbd10883b7c","name":"🌡️ Device Data API","type":"folder"}},"urlObject":{"protocol":"https","path":["api","v1.6","variables","<variable_id>","values"],"host":["api","surfact","com"],"query":[],"variable":[]}},"response":[{"id":"acd183d0-180a-4c54-a07b-c3e09999252c","name":"Get Last Data Point","originalRequest":{"method":"GET","header":[{"key":"X-Auth-Token","value":"oaXBo6ODhIjPsusNRPUGIK4d72bc73"}],"url":{"raw":"https://api.surfact.com/api/v1.6/variables/<variable_id>/values/?page_size=1","protocol":"https","host":["api","surfact","com"],"path":["api","v1.6","variables","<variable_id>","values",""],"query":[{"key":"page_size","value":"1","type":"text"}]}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Auth-Token","value":"oaXBo6ODhIjPsusNRPUGIK4d72bc73","description":"","enabled":true}],"cookie":[],"responseTime":null,"body":"{\n  \"count\": true,\n  \"next\": \"https://api.surfact.com/api/v1.6/variables/<variable_id>/values/?page_size=1&page=2\",\n  \"previous\": null,\n  \"results\": [\n    {\n      \"timestamp\": 1635264014782,\n      \"value\": 0,\n      \"context\": {},\n      \"created_at\": 1635264014782\n    }\n  ]\n}"},{"id":"b9aa28d0-7392-4e82-b95d-03bcb17b315e","name":"Get Last Two Data Points","originalRequest":{"method":"GET","header":[{"key":"X-Auth-Token","value":"oaXBo6ODhIjPsusNRPUGIK4d72bc73"}],"url":{"raw":"https://api.surfact.com/api/v1.6/variables/<variable_id>/values/?page_size=2","protocol":"https","host":["api","surfact","com"],"path":["api","v1.6","variables","<variable_id>","values",""],"query":[{"key":"page_size","value":"2","type":"text"}]}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Auth-Token","value":"oaXBo6ODhIjPsusNRPUGIK4d72bc73","description":"","enabled":true}],"cookie":[],"responseTime":null,"body":"{\n  \"count\": true,\n  \"next\": \"https://api.surfact.com/api/v1.6/variables/<variable_id>/values/?page_size=2&page=2\",\n  \"previous\": null,\n  \"results\": [\n    {\n      \"timestamp\": 1635264014782,\n      \"value\": 0,\n      \"context\": {},\n      \"created_at\": 1635264014782\n    },\n    {\n      \"timestamp\": 1635264000173,\n      \"value\": 0,\n      \"context\": {},\n      \"created_at\": 1635264000173\n    }\n  ]\n}"}],"_postman_id":"4a34bc2f-1763-4f38-8f2a-1b74cefc9896"},{"name":"Variable Aggregated Data","id":"74c4acdd-be3f-4d54-b3b4-df3d1b17c089","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[],"url":"https://api.surfact.com/api/v1.6/variables/<variable_id>/statistics/<aggregation>/<start>/<end>","description":"<p>This endpoint retrieves aggregated statistics for a variable within a specified time range.</p>\n<hr />\n<h2 id=\"path-parameters\">Path Parameters</h2>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Parameter</th>\n<th>Type</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>variable_id</code></td>\n<td>String</td>\n<td>The unique ID of the variable to retrieve data from</td>\n</tr>\n<tr>\n<td><code>aggregation</code></td>\n<td>String</td>\n<td>The aggregation function to apply. Options: <code>mean</code>, <code>min</code>, <code>max</code>, <code>sum</code>, <code>count</code>, <code>variance</code>, <code>stddev</code></td>\n</tr>\n<tr>\n<td><code>start</code></td>\n<td>Integer</td>\n<td>Start timestamp in milliseconds (POSIX format, inclusive)</td>\n</tr>\n<tr>\n<td><code>end</code></td>\n<td>Integer</td>\n<td>End timestamp in milliseconds (POSIX format, inclusive)</td>\n</tr>\n</tbody>\n</table>\n</div><hr />\n<h2 id=\"headers\">Headers</h2>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Header</th>\n<th>Value</th>\n<th>Required</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>X-Auth-Token</code></td>\n<td>Token</td>\n<td>Yes</td>\n<td>Your authentication token (valid for 6 hours)</td>\n</tr>\n</tbody>\n</table>\n</div><hr />\n<p>)</p>\n<hr />\n<hr />\n<h2 id=\"python-example\">Python Example</h2>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-python\">import requests\nfrom datetime import datetime\n# Your credentials\nTOKEN = \"your_token_here\"\nVARIABLE_ID = \"your_variable_id\"\n# Time range (example: full day on Nov 24, 2021)\nstart = 1637730000000  # milliseconds\nend = 1637816399999\n# Get mean value\nurl = f\"https://api.surfact.com/api/v1.6/variables/{VARIABLE_ID}/statistics/mean/{start}/{end}\"\nheaders = {\"X-Auth-Token\": TOKEN}\nresponse = requests.get(url, headers=headers)\ndata = response.json()\nprint(f\"Mean value: {data['mean']}\")\n\n</code></pre>\n<hr />\n<h2 id=\"javascript-example\">JavaScript Example</h2>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-javascript\">const TOKEN = \"your_token_here\";\nconst VARIABLE_ID = \"your_variable_id\";\n// Time range\nconst start = 1637730000000;\nconst end = 1637816399999;\n// Get mean value\nconst url = `https://api.surfact.com/api/v1.6/variables/${VARIABLE_ID}/statistics/mean/${start}/${end}`;\nfetch(url, {\n  headers: {\n    \"X-Auth-Token\": TOKEN\n  }\n})\n  .then(response =&gt; response.json())\n  .then(data =&gt; console.log(\"Mean value:\", data.mean))\n  .catch(error =&gt; console.error(\"Error:\", error));\n\n</code></pre>\n<hr />\n<h2 id=\"notes\">Notes</h2>\n<ul>\n<li><p>Timestamps must be in milliseconds (POSIX format)</p>\n</li>\n<li><p>Time range is inclusive on both start and end</p>\n</li>\n<li><p>For available aggregation types, see the <code>aggregation</code> parameter options above</p>\n</li>\n</ul>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"X-Auth-Token"}]},"isInherited":true,"source":{"_postman_id":"1ce9948b-87a0-41a6-a2da-3fbd10883b7c","id":"1ce9948b-87a0-41a6-a2da-3fbd10883b7c","name":"🌡️ Device Data API","type":"folder"}},"urlObject":{"protocol":"https","path":["api","v1.6","variables","<variable_id>","statistics","<aggregation>","<start>","<end>"],"host":["api","surfact","com"],"query":[],"variable":[]}},"response":[{"id":"3cd6826f-eaa2-4dd2-937e-d8a052b65b04","name":"Get Mean Value","originalRequest":{"method":"GET","header":[{"key":"X-Auth-Token","value":"oaXBo6ODhIjPsusNRPUGIK4d72bc73"}],"url":{"raw":"https://api.surfact.com/api/v1.6/variables/<variable_id>/statistics/mean/1637730000000/1637816399999","protocol":"https","host":["api","surfact","com"],"path":["api","v1.6","variables","<variable_id>","statistics","mean","1637730000000","1637816399999"],"variable":[{"key":"variable_id","value":"<variable_id>"}]}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Auth-Token","value":"oaXBo6ODhIjPsusNRPUGIK4d72bc73","description":"","enabled":true}],"cookie":[],"responseTime":null,"body":"{\n  \"mean\": 56724.07\n}"},{"id":"c2346564-9a8b-420b-8c5e-1abb176247a5","name":"Get Max Value","originalRequest":{"method":"GET","header":[{"key":"X-Auth-Token","value":"oaXBo6ODhIjPsusNRPUGIK4d72bc73"}],"url":{"raw":"https://api.surfact.com/api/v1.6/variables/<variable_id>/statistics/max/1637730000000/1637816399999","protocol":"https","host":["api","surfact","com"],"path":["api","v1.6","variables","<variable_id>","statistics","max","1637730000000","1637816399999"],"variable":[{"key":"variable_id","value":"<variable_id>"}]}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Auth-Token","value":"oaXBo6ODhIjPsusNRPUGIK4d72bc73","description":"","enabled":true}],"cookie":[],"responseTime":null,"body":"{\n  \"max\": 57424.65\n}"},{"id":"067cc227-fc73-4ea9-8ba1-4dcd5a743119","name":"401 Unauthorized","originalRequest":{"method":"GET","header":[{"key":"X-Auth-Token","value":"oaXBo6ODhIjPsusNRPUGIK4d72bc73"}],"url":{"raw":"https://api.surfact.com/api/v1.6/variables/<variable_id>/statistics/mean/1637730000000/1637816399999","protocol":"https","host":["api","surfact","com"],"path":["api","v1.6","variables","<variable_id>","statistics","mean","1637730000000","1637816399999"],"variable":[{"key":"variable_id","value":"<variable_id>"}]}},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"X-Auth-Token","value":"oaXBo6ODhIjPsusNRPUGIK4d72bc73","description":"","enabled":true}],"cookie":[],"responseTime":null,"body":"{\n  \"code\": 401002,\n  \"message\": \"Incorrect authentication credentials.\"\n}"}],"_postman_id":"74c4acdd-be3f-4d54-b3b4-df3d1b17c089"},{"name":"Data Aggregation","id":"d104a208-433d-4d8b-953d-bc4da0b8e90c","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json","type":"text"}],"url":"https://api.surfact.com/api/v1.6/data/stats/aggregation/","description":"<p>Aggregate data from one or multiple variables within a specified time range. This endpoint can return either a single aggregated value across all variables or individual values per variable.</p>\n<hr />\n<h2 id=\"request-body-parameters\">Request Body Parameters</h2>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Parameter</th>\n<th>Type</th>\n<th>Required</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>variables</code></td>\n<td>Array of Strings</td>\n<td>Yes</td>\n<td>Array of variable IDs to aggregate</td>\n</tr>\n<tr>\n<td><code>aggregation</code></td>\n<td>String</td>\n<td>Yes</td>\n<td>Aggregation function: <code>mean</code>, <code>min</code>, <code>max</code>, <code>sum</code>, <code>count</code>, <code>variance</code>, <code>stddev</code></td>\n</tr>\n<tr>\n<td><code>join_dataframes</code></td>\n<td>Boolean</td>\n<td>No</td>\n<td><code>true</code>: single aggregated value across all variables  <br /><code>false</code>: individual value per variable (default)</td>\n</tr>\n<tr>\n<td><code>start</code></td>\n<td>Integer</td>\n<td>No</td>\n<td>Start timestamp in milliseconds (POSIX format, inclusive)</td>\n</tr>\n<tr>\n<td><code>end</code></td>\n<td>Integer</td>\n<td>No</td>\n<td>End timestamp in milliseconds (POSIX format, inclusive)</td>\n</tr>\n<tr>\n<td><code>tz</code></td>\n<td>String</td>\n<td>No</td>\n<td>Timezone for timestamp interpretation (e.g., <code>America/New_York</code>, <code>Europe/London</code>)</td>\n</tr>\n<tr>\n<td><code>precision</code></td>\n<td>Integer</td>\n<td>No</td>\n<td>Decimal places for results (omit for full precision)</td>\n</tr>\n</tbody>\n</table>\n</div><hr />\n<h2 id=\"time-range-behavior\">Time Range Behavior</h2>\n<ul>\n<li><p><strong>No</strong> <strong><code>start</code></strong> <strong>or</strong> <strong><code>end</code></strong>: Uses last 100 values from each variable</p>\n</li>\n<li><p><strong>Only</strong> <strong><code>start</code></strong>: Aggregates from start timestamp to current time</p>\n</li>\n<li><p><strong>Only</strong> <strong><code>end</code></strong>: Aggregates from beginning of data to end timestamp</p>\n</li>\n<li><p><strong>Both</strong> <strong><code>start</code></strong> <strong>and</strong> <strong><code>end</code></strong>: Aggregates within specified range (inclusive)</p>\n</li>\n</ul>\n<hr />\n<h2 id=\"examples\">Examples</h2>\n<h3 id=\"example-1-single-aggregated-value-combined\">Example 1: Single Aggregated Value (Combined)</h3>\n<p>Get the mean value across multiple variables combined into one result:</p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-bash\">curl -X POST 'https://api.surfact.com/api/v1.6/data/stats/aggregation/' \\\n  -H 'Content-Type: application/json' \\\n  -H 'X-Auth-Token: oaXBo6ODhIjPsusNRPUGIK4d72bc73' \\\n  -d '{\n    \"variables\": [\"618848b4b09758ded46bafda\", \"618848b7b31be1cb509c0a3c\"],\n    \"aggregation\": \"mean\",\n    \"join_dataframes\": true,\n    \"start\": 1636321611000,\n    \"end\": 1636321629000,\n    \"tz\": \"America/New_York\",\n    \"precision\": 2\n  }'\n\n</code></pre>\n<p><strong>Success Response (200):</strong></p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-json\">{\n  \"results\": [\n    {\n      \"value\": 62873.88,\n      \"timestamp\": 1636318800000\n    }\n  ]\n}\n\n</code></pre>\n<h3 id=\"example-2-individual-values-per-variable\">Example 2: Individual Values Per Variable</h3>\n<p>Get mean values for each variable separately:</p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-bash\">curl -X POST 'https://api.surfact.com/api/v1.6/data/stats/aggregation/' \\\n  -H 'Content-Type: application/json' \\\n  -H 'X-Auth-Token: oaXBo6ODhIjPsusNRPUGIK4d72bc73' \\\n  -d '{\n    \"variables\": [\"618848b4b09758ded46bafda\", \"618848b7b31be1cb509c0a3c\"],\n    \"aggregation\": \"mean\",\n    \"join_dataframes\": false,\n    \"start\": 1636321611000,\n    \"end\": 1636321629000,\n    \"tz\": \"America/New_York\",\n    \"precision\": 2\n  }'\n\n</code></pre>\n<p><strong>Success Response (200):</strong></p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-json\">{\n  \"results\": [\n    {\n      \"value\": 62858.45,\n      \"timestamp\": 1636318807253\n    },\n    {\n      \"value\": 62920.19,\n      \"timestamp\": 1636318800000\n    }\n  ]\n}\n\n</code></pre>\n<hr />\n<h2 id=\"error-responses\">Error Responses</h2>\n<p><strong>400 Bad Request (Invalid JSON):</strong></p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-json\">{\n  \"detail\": \"JSON parse error - Expecting value: line 4 column 22 (char 121)\"\n}\n\n</code></pre>\n<p><strong>401 Unauthorized:</strong></p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-json\">{\n  \"code\": 401001,\n  \"message\": \"Authentication credentials were not provided.\"\n}\n\n</code></pre>\n<hr />\n<h2 id=\"python-example\">Python Example</h2>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-python\">import requests\nfrom datetime import datetime, timezone\nTOKEN = \"your_token_here\"\nVARIABLE_IDS = [\"618848b4b09758ded46bafda\", \"618848b7b31be1cb509c0a3c\"]\nurl = \"https://api.surfact.com/api/v1.6/data/stats/aggregation/\"\nheaders = {\n    \"X-Auth-Token\": TOKEN,\n    \"Content-Type\": \"application/json\"\n}\n# Get combined mean across all variables\npayload = {\n    \"variables\": VARIABLE_IDS,\n    \"aggregation\": \"mean\",\n    \"join_dataframes\": True,\n    \"start\": 1636321611000,\n    \"end\": 1636321629000,\n    \"tz\": \"America/New_York\",\n    \"precision\": 2\n}\nresponse = requests.post(url, json=payload, headers=headers)\ndata = response.json()\nprint(f\"Combined mean: {data['results'][0]['value']}\")\n# Get individual means per variable\npayload[\"join_dataframes\"] = False\nresponse = requests.post(url, json=payload, headers=headers)\ndata = response.json()\nfor i, result in enumerate(data['results']):\n    print(f\"Variable {i+1} mean: {result['value']}\")\n\n</code></pre>\n<hr />\n<h2 id=\"javascript-example\">JavaScript Example</h2>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-javascript\">const TOKEN = \"your_token_here\";\nconst VARIABLE_IDS = [\"618848b4b09758ded46bafda\", \"618848b7b31be1cb509c0a3c\"];\nconst url = \"https://api.surfact.com/api/v1.6/data/stats/aggregation/\";\n// Get combined mean across all variables\nconst payload = {\n  variables: VARIABLE_IDS,\n  aggregation: \"mean\",\n  join_dataframes: true,\n  start: 1636321611000,\n  end: 1636321629000,\n  tz: \"America/New_York\",\n  precision: 2\n};\nfetch(url, {\n  method: \"POST\",\n  headers: {\n    \"X-Auth-Token\": TOKEN,\n    \"Content-Type\": \"application/json\"\n  },\n  body: JSON.stringify(payload)\n})\n  .then(response =&gt; response.json())\n  .then(data =&gt; console.log(\"Combined mean:\", data.results[0].value))\n  .catch(error =&gt; console.error(\"Error:\", error));\n// Get individual means per variable\npayload.join_dataframes = false;\nfetch(url, {\n  method: \"POST\",\n  headers: {\n    \"X-Auth-Token\": TOKEN,\n    \"Content-Type\": \"application/json\"\n  },\n  body: JSON.stringify(payload)\n})\n  .then(response =&gt; response.json())\n  .then(data =&gt; {\n    data.results.forEach((result, i) =&gt; {\n      console.log(`Variable ${i+1} mean:`, result.value);\n    });\n  })\n  .catch(error =&gt; console.error(\"Error:\", error));\n\n</code></pre>\n<hr />\n<h2 id=\"use-cases\">Use Cases</h2>\n<p><strong>Combined aggregation (<strong><strong><code>join_dataframes: true</code></strong></strong>):</strong></p>\n<ul>\n<li><p>Calculate average temperature across multiple sensors</p>\n</li>\n<li><p>Get total count of events across different sources</p>\n</li>\n<li><p>Find maximum value across all monitoring points</p>\n</li>\n</ul>\n<p><strong>Individual aggregation (<strong><strong><code>join_dataframes: false</code></strong></strong>):</strong></p>\n<ul>\n<li><p>Compare performance of different sensors</p>\n</li>\n<li><p>Monitor individual device metrics</p>\n</li>\n<li><p>Generate per-variable reports</p>\n</li>\n</ul>\n<hr />\n<h2 id=\"notes\">Notes</h2>\n<ul>\n<li><p>All timestamps are in milliseconds (POSIX format)</p>\n</li>\n<li><p>Time ranges are inclusive on both start and end</p>\n</li>\n<li><p>Without precision specified, results use full decimal precision</p>\n</li>\n<li><p>Token expires after 6 hours - generate fresh tokens as needed</p>\n</li>\n<li><p>Timezone defaults to UTC if not specified</p>\n</li>\n</ul>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"X-Auth-Token"}]},"isInherited":true,"source":{"_postman_id":"1ce9948b-87a0-41a6-a2da-3fbd10883b7c","id":"1ce9948b-87a0-41a6-a2da-3fbd10883b7c","name":"🌡️ Device Data API","type":"folder"}},"urlObject":{"protocol":"https","path":["api","v1.6","data","stats","aggregation",""],"host":["api","surfact","com"],"query":[],"variable":[]}},"response":[],"_postman_id":"d104a208-433d-4d8b-953d-bc4da0b8e90c"},{"name":"Data Raw Series","id":"b8da6bd7-b4ce-478c-b964-549104882da5","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json","type":"text"}],"url":"https://api.surfact.com/api/v1.6/data/raw/series","description":"<p>Retrieve raw (unaggregated) data from one or multiple variables within a specified time range. This endpoint returns the actual data points with customizable columns.</p>\n<p><strong>Endpoint:</strong></p>\n<hr />\n<h2 id=\"headers\">Headers</h2>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Header</th>\n<th>Value</th>\n<th>Required</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>X-Auth-Token</code></td>\n<td>Token</td>\n<td>Yes</td>\n<td>Your authentication token (valid for 6 hours)</td>\n</tr>\n<tr>\n<td><code>Content-Type</code></td>\n<td><code>application/json</code></td>\n<td>Yes</td>\n<td>Request body format</td>\n</tr>\n</tbody>\n</table>\n</div><hr />\n<h2 id=\"request-body-parameters\">Request Body Parameters</h2>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Parameter</th>\n<th>Type</th>\n<th>Required</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>variables</code></td>\n<td>Array of Strings</td>\n<td>Yes</td>\n<td>Array of variable IDs to retrieve data from</td>\n</tr>\n<tr>\n<td><code>columns</code></td>\n<td>Array of Strings</td>\n<td>Yes</td>\n<td>Data columns to include in response (see options below)</td>\n</tr>\n<tr>\n<td><code>join_dataframes</code></td>\n<td>Boolean</td>\n<td>No</td>\n<td><code>true</code>: combine all variables into single dataset  <br /><code>false</code>: separate dataset per variable (default)</td>\n</tr>\n<tr>\n<td><code>start</code></td>\n<td>Integer</td>\n<td>No</td>\n<td>Start timestamp in milliseconds (POSIX format, inclusive)</td>\n</tr>\n<tr>\n<td><code>end</code></td>\n<td>Integer</td>\n<td>No</td>\n<td>End timestamp in milliseconds (POSIX format, inclusive)</td>\n</tr>\n<tr>\n<td><code>limit</code></td>\n<td>Integer</td>\n<td>No</td>\n<td>Maximum number of values to return per variable</td>\n</tr>\n<tr>\n<td><code>tz</code></td>\n<td>String</td>\n<td>No</td>\n<td>Timezone for timestamp interpretation (e.g., <code>America/New_York</code>, <code>Europe/London</code>)</td>\n</tr>\n<tr>\n<td><code>precision</code></td>\n<td>Integer</td>\n<td>No</td>\n<td>Decimal places for numeric values (omit for full precision)</td>\n</tr>\n</tbody>\n</table>\n</div><hr />\n<h2 id=\"column-options\">Column Options</h2>\n<p>Specify which data fields to include in the response:</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Column</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>value.value</code></td>\n<td>The actual data value</td>\n</tr>\n<tr>\n<td><code>timestamp</code></td>\n<td>Unix timestamp in milliseconds</td>\n</tr>\n<tr>\n<td><code>variable.id</code></td>\n<td>Variable ID</td>\n</tr>\n<tr>\n<td><code>variable.label</code></td>\n<td>Variable label</td>\n</tr>\n<tr>\n<td><code>variable.name</code></td>\n<td>Variable name</td>\n</tr>\n<tr>\n<td><code>variable.properties.color</code></td>\n<td>Variable color property</td>\n</tr>\n<tr>\n<td><code>value.context</code></td>\n<td>Additional context data associated with the value</td>\n</tr>\n<tr>\n<td><code>device.name</code></td>\n<td>Name of the device</td>\n</tr>\n<tr>\n<td><code>device.label</code></td>\n<td>Label of the device</td>\n</tr>\n</tbody>\n</table>\n</div><hr />\n<h2 id=\"query-parameters\">Query Parameters</h2>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Parameter</th>\n<th>Type</th>\n<th>Required</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>token</code></td>\n<td>String</td>\n<td>No</td>\n<td>Alternative authentication method (prototyping only - see <a href=\"https://claude.ai/chat/surfact_authentication.md\">Authentication</a>)</td>\n</tr>\n</tbody>\n</table>\n</div><hr />\n<h2 id=\"time-range-behavior\">Time Range Behavior</h2>\n<ul>\n<li><p><strong>No</strong> <strong><code>start</code></strong> <strong>or</strong> <strong><code>end</code></strong>: Returns last 100 values from each variable</p>\n</li>\n<li><p><strong>Only</strong> <strong><code>start</code></strong>: Returns values from start timestamp to most recent data point</p>\n</li>\n<li><p><strong>Only</strong> <strong><code>end</code></strong>: Returns values from earliest data point to end timestamp</p>\n</li>\n<li><p><strong>Both</strong> <strong><code>start</code></strong> <strong>and</strong> <strong><code>end</code></strong>: Returns values within specified range (inclusive)</p>\n</li>\n</ul>\n<hr />\n<h2 id=\"examples\">Examples</h2>\n<h3 id=\"example-1-get-raw-data-within-time-range\">Example 1: Get Raw Data Within Time Range</h3>\n<p>Retrieve 1 hour of raw data from multiple variables:</p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-bash\">curl -X POST 'https://api.surfact.com/api/v1.6/data/raw/series' \\\n  -H 'Content-Type: application/json' \\\n  -H 'X-Auth-Token: oaXBo6ODhIjPsusNRPUGIK4d72bc73' \\\n  -d '{\n    \"variables\": [\"618848b4b09758ded46bafda\", \"618848b7b31be1cb509c0a3c\"],\n    \"columns\": [\"value.value\", \"timestamp\"],\n    \"join_dataframes\": false,\n    \"start\": 1636318800000,\n    \"end\": 1636322400000,\n    \"tz\": \"America/New_York\",\n    \"precision\": 2\n  }'\n\n</code></pre>\n<p><strong>Success Response (200):</strong></p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-json\">{\n  \"results\": [\n    [\n      [62982.21, 1636322400000],\n      [62983.08, 1636321200000],\n      [63038.95, 1636320000000],\n      [62796.23, 1636318800000]\n    ],\n    [\n      [62850.38, 1636322101553],\n      [62883.23, 1636321804316],\n      [62870.37, 1636321503773],\n      [62983.08, 1636321204195]\n    ]\n  ],\n  \"columns\": [\n    [\"5b17df86642ab66a5f6037d8.value.value\", \"timestamp\"],\n    [\"5ae73c56bbddbd669ed87e0a.value.value\", \"timestamp\"]\n  ]\n}\n\n</code></pre>\n<h3 id=\"example-2-get-last-n-values\">Example 2: Get Last N Values</h3>\n<p>Retrieve the last 3 values from multiple variables:</p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-bash\">curl -X POST 'https://api.surfact.com/api/v1.6/data/raw/series' \\\n  -H 'Content-Type: application/json' \\\n  -H 'X-Auth-Token: oaXBo6ODhIjPsusNRPUGIK4d72bc73' \\\n  -d '{\n    \"variables\": [\"618848b4b09758ded46bafda\", \"618848b7b31be1cb509c0a3c\"],\n    \"columns\": [\"value.value\", \"timestamp\"],\n    \"join_dataframes\": false,\n    \"limit\": 3,\n    \"tz\": \"America/New_York\",\n    \"precision\": 2\n  }'\n\n</code></pre>\n<p><strong>Success Response (200):</strong></p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-json\">{\n  \"results\": [\n    [\n      [62982.21, 1636322400000],\n      [62983.08, 1636321200000],\n      [63038.95, 1636320000000]\n    ],\n    [\n      [62850.38, 1636322101553],\n      [62883.23, 1636321804316],\n      [62870.37, 1636321503773]\n    ]\n  ],\n  \"columns\": [\n    [\"5b17df86642ab66a5f6037d8.value.value\", \"timestamp\"],\n    [\"5ae73c56bbddbd669ed87e0a.value.value\", \"timestamp\"]\n  ]\n}\n\n</code></pre>\n<hr />\n<h2 id=\"error-responses\">Error Responses</h2>\n<p><strong>400 Bad Request (Invalid JSON):</strong></p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-json\">{\n  \"detail\": \"JSON parse error - Expecting value: line 4 column 22 (char 121)\"\n}\n\n</code></pre>\n<p><strong>401 Unauthorized:</strong></p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-json\">{\n  \"code\": 401001,\n  \"message\": \"Authentication credentials were not provided.\"\n}\n\n</code></pre>\n<hr />\n<h2 id=\"python-example\">Python Example</h2>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-python\">import requests\nimport pandas as pd\nfrom datetime import datetime\nTOKEN = \"your_token_here\"\nVARIABLE_IDS = [\"618848b4b09758ded46bafda\", \"618848b7b31be1cb509c0a3c\"]\nurl = \"https://api.surfact.com/api/v1.6/data/raw/series\"\nheaders = {\n    \"X-Auth-Token\": TOKEN,\n    \"Content-Type\": \"application/json\"\n}\n# Get raw data with time range\npayload = {\n    \"variables\": VARIABLE_IDS,\n    \"columns\": [\"value.value\", \"timestamp\", \"variable.name\"],\n    \"join_dataframes\": False,\n    \"start\": 1636318800000,\n    \"end\": 1636322400000,\n    \"tz\": \"America/New_York\",\n    \"precision\": 2\n}\nresponse = requests.post(url, json=payload, headers=headers)\ndata = response.json()\n# Process results for each variable\nfor i, variable_data in enumerate(data['results']):\n    print(f\"\\nVariable {i+1}:\")\n    print(f\"Columns: {data['columns'][i]}\")\n    print(f\"Data points: {len(variable_data)}\")\n    # Convert to DataFrame for easy analysis\n    df = pd.DataFrame(variable_data, columns=data['columns'][i])\n    print(df.head())\n# Get just the last 5 values\npayload_recent = {\n    \"variables\": VARIABLE_IDS,\n    \"columns\": [\"value.value\", \"timestamp\"],\n    \"limit\": 5,\n    \"precision\": 2\n}\nresponse = requests.post(url, json=payload_recent, headers=headers)\nrecent_data = response.json()\nprint(f\"\\nMost recent values: {recent_data['results'][0]}\")\n\n</code></pre>\n<hr />\n<h2 id=\"javascript-example\">JavaScript Example</h2>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-javascript\">const TOKEN = \"your_token_here\";\nconst VARIABLE_IDS = [\"618848b4b09758ded46bafda\", \"618848b7b31be1cb509c0a3c\"];\nconst url = \"https://api.surfact.com/api/v1.6/data/raw/series\";\n// Get raw data with time range\nconst payload = {\n  variables: VARIABLE_IDS,\n  columns: [\"value.value\", \"timestamp\", \"variable.name\"],\n  join_dataframes: false,\n  start: 1636318800000,\n  end: 1636322400000,\n  tz: \"America/New_York\",\n  precision: 2\n};\nfetch(url, {\n  method: \"POST\",\n  headers: {\n    \"X-Auth-Token\": TOKEN,\n    \"Content-Type\": \"application/json\"\n  },\n  body: JSON.stringify(payload)\n})\n  .then(response =&gt; response.json())\n  .then(data =&gt; {\n    data.results.forEach((variableData, i) =&gt; {\n      console.log(`\\nVariable ${i + 1}:`);\n      console.log(`Columns: ${data.columns[i]}`);\n      console.log(`Data points: ${variableData.length}`);\n      console.log(\"Sample data:\", variableData.slice(0, 3));\n    });\n  })\n  .catch(error =&gt; console.error(\"Error:\", error));\n// Get just the last 5 values\nconst recentPayload = {\n  variables: VARIABLE_IDS,\n  columns: [\"value.value\", \"timestamp\"],\n  limit: 5,\n  precision: 2\n};\nfetch(url, {\n  method: \"POST\",\n  headers: {\n    \"X-Auth-Token\": TOKEN,\n    \"Content-Type\": \"application/json\"\n  },\n  body: JSON.stringify(recentPayload)\n})\n  .then(response =&gt; response.json())\n  .then(data =&gt; console.log(\"Most recent values:\", data.results[0]))\n  .catch(error =&gt; console.error(\"Error:\", error));\n\n</code></pre>\n<hr />\n<h2 id=\"response-structure\">Response Structure</h2>\n<p>The response contains:</p>\n<ul>\n<li><p><strong><code>results</code></strong>: Array of datasets (one per variable if <code>join_dataframes: false</code>)</p>\n</li>\n<li><p><strong><code>columns</code></strong>: Array describing column names for each dataset</p>\n</li>\n</ul>\n<p>Each data point in <code>results</code> is an array where values correspond to the <code>columns</code> order:</p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-javascript\">// For columns: [\"value.value\", \"timestamp\"]\n[62982.21, 1636322400000]  // [value, timestamp]\n\n</code></pre>\n<hr />\n<h2 id=\"use-cases\">Use Cases</h2>\n<ul>\n<li><p><strong>Real-time monitoring</strong>: Get the latest values with <code>limit</code> parameter</p>\n</li>\n<li><p><strong>Historical analysis</strong>: Retrieve full time range data for trend analysis</p>\n</li>\n<li><p><strong>Data export</strong>: Pull raw data for external processing or visualization</p>\n</li>\n<li><p><strong>Multi-sensor comparison</strong>: Compare readings across multiple variables</p>\n</li>\n<li><p><strong>Custom reporting</strong>: Select specific columns needed for your application</p>\n</li>\n</ul>\n<hr />\n<h2 id=\"notes\">Notes</h2>\n<ul>\n<li><p>Results are ordered by timestamp (most recent first by default)</p>\n</li>\n<li><p>All timestamps are in milliseconds (POSIX format)</p>\n</li>\n<li><p>Time ranges are inclusive on both start and end</p>\n</li>\n<li><p>Without precision specified, results use full decimal precision</p>\n</li>\n<li><p>Token expires after 6 hours - generate fresh tokens as needed</p>\n</li>\n<li><p>Timezone defaults to UTC if not specified</p>\n</li>\n<li><p>Use <code>limit</code> to control data volume and API response time</p>\n</li>\n</ul>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"X-Auth-Token"}]},"isInherited":true,"source":{"_postman_id":"1ce9948b-87a0-41a6-a2da-3fbd10883b7c","id":"1ce9948b-87a0-41a6-a2da-3fbd10883b7c","name":"🌡️ Device Data API","type":"folder"}},"urlObject":{"protocol":"https","path":["api","v1.6","data","raw","series"],"host":["api","surfact","com"],"query":[],"variable":[]}},"response":[],"_postman_id":"b8da6bd7-b4ce-478c-b964-549104882da5"}],"id":"1ce9948b-87a0-41a6-a2da-3fbd10883b7c","description":"<p>Device Data and all your time series in one place.<br />Base URL is: <code>api.surfact.com/api/v1.6/</code></p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"X-Auth-Token"}]},"isInherited":false},"event":[{"listen":"prerequest","script":{"id":"60fd5ab1-6145-4cd8-b745-54888af19e69","type":"text/javascript","packages":{},"requests":{},"exec":[""]}},{"listen":"test","script":{"id":"4f9f91f7-ed23-40bf-b6fe-f4a12747503f","type":"text/javascript","packages":{},"requests":{},"exec":[""]}}],"_postman_id":"1ce9948b-87a0-41a6-a2da-3fbd10883b7c"},{"name":"⚙️ Device & Organization Management API","item":[{"name":"All Devices","event":[{"listen":"test","script":{"id":"5c4dd332-a4a8-46c1-a8d7-92ebdce9fcbb","exec":["var template = `","<style type=\"text/css\">","    .tftable {font-size:14px;color:#333333;width:100%;border-width: 1px;border-color: #87ceeb;border-collapse: collapse;}","    .tftable th {font-size:18px;background-color:#87ceeb;border-width: 1px;padding: 8px;border-style: solid;border-color: #87ceeb;text-align:left;}","    .tftable tr {background-color:#ffffff;}","    .tftable td {font-size:14px;border-width: 1px;padding: 8px;border-style: solid;border-color: #87ceeb;}","    .tftable tr:hover {background-color:#e0ffff;}","</style>","","<table class=\"tftable\" border=\"1\">","    <tr>","        <th>ID</th>","        <th>Label</th>","        <th>Name</th>","        <th>Description</th>","        <th>Tags</th>","        <th>Active</th>","        <th>Last Activity</th>","        <th>Created At</th>","    </tr>","    ","    {{#each response.results}}","        <tr>","            <td>{{id}}</td>","            <td>{{label}}</td>","            <td>{{name}}</td>","            <td>{{description}}</td>","            <td>{{tags}}</td>","            <td>{{isActive}}</td>","            <td>{{lastActivity}}</td>","            <td>{{createdAt}}</td>","        </tr>","    {{/each}}","</table>","`;","","function constructVisualizerPayload() {","    return {response: pm.response.json()}","}","","pm.visualizer.set(template, constructVisualizerPayload());"],"type":"text/javascript","packages":{}}}],"id":"ef69d58e-6be7-469a-9103-f413c51d57ce","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[],"url":"https://api.surfact.com/api/v2.0/devices","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"X-Auth-Token"}]},"isInherited":true,"source":{"_postman_id":"7d151dbc-c9c6-4d8d-80fe-df86c0296dc0","id":"7d151dbc-c9c6-4d8d-80fe-df86c0296dc0","name":"⚙️ Device & Organization Management API","type":"folder"}},"urlObject":{"protocol":"https","path":["api","v2.0","devices"],"host":["api","surfact","com"],"query":[],"variable":[]}},"response":[{"id":"6110ba73-8498-49d7-a6a9-25fe7551ec0e","name":"All Devices","originalRequest":{"method":"GET","header":[{"key":"","value":"","type":"text","disabled":true}],"url":"https://api.surfact.com/api/v2.0/devices"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"date","value":"Thu, 10 Jul 2025 11:56:50 GMT"},{"key":"content-type","value":"application/json"},{"key":"transfer-encoding","value":"chunked"},{"key":"server","value":"IoTServer"},{"key":"allow","value":"GET, POST, HEAD, OPTIONS"},{"key":"vary","value":"Authorization, origin, Cookie"},{"key":"set-cookie","value":"__ubidots_ui=dXNlcm5hbWU9VEtfT1JHXzExMzM5MV82M18xO3BsYW49ZnJlZS1wbGFu; Domain=.ubidots.com; expires=Fri, 10 Jul 2026 11:56:50 GMT; Max-Age=31536000; Path=/"},{"key":"x-xss-protection","value":"1; mode=block"},{"key":"x-content-type-options","value":"nosniff"},{"key":"strict-transport-security","value":"max-age=31536000; includeSubDomains; preload"},{"key":"content-security-policy","value":"default-src https: wss: data: blob: 'unsafe-eval' 'unsafe-inline'"},{"key":"referrer-policy","value":"strict-origin"},{"key":"permissions-policy","value":"geolocation 'self'; microphone 'none'"},{"key":"x-frame-options","value":"SAMEORIGIN"}],"cookie":[],"responseTime":null,"body":"{\n    \"count\": 6,\n    \"next\": null,\n    \"previous\": null,\n    \"results\": [\n        {\n            \"url\": \"https://api.surfact.com/api/v2.0/devices/6865acf980bcac000f4ca5ec\",\n            \"id\": \"6865acf980bcac000f4ca5ec\",\n            \"organization\": {\n                \"url\": \"https://api.surfact.com/api/v2.0/organizations/6865ac3080bcac000f4ca585\",\n                \"id\": \"6865ac3080bcac000f4ca585\",\n                \"label\": \"1f7fd11c-64fa-416a-9921-256dcbeb0764\",\n                \"name\": \"Demo6\",\n                \"createdAt\": \"2025-07-02T22:01:20.428789Z\"\n            },\n            \"label\": \"a55b6126-c983-4289-8488-d46cf99da76b\",\n            \"name\": \"618-ab9-3cb\",\n            \"description\": \"\",\n            \"tags\": [],\n            \"properties\": {\n                \"qr\": \"https://surfact.azurewebsites.net/?qrid=c44f6701-c0c7-4618-ab9d-3cb0c2b9027b\",\n                \"_icon\": \"hockey-puck\",\n                \"_color\": \"#2fbd68\",\n                \"_config\": {\n                    \"qr\": {\n                        \"key\": \"qr\",\n                        \"text\": \"Qr\",\n                        \"type\": \"text\",\n                        \"value\": \"\",\n                        \"description\": \"Same url as when scanning the QR on the device\"\n                    },\n                    \"duration\": {\n                        \"key\": \"duration\",\n                        \"text\": \"Duration\",\n                        \"type\": \"text\",\n                        \"value\": \"\",\n                        \"description\": \"If a timeout threshold is set as AutoStop on active route\"\n                    },\n                    \"certificate\": {\n                        \"key\": \"certificate\",\n                        \"text\": \"Certificate\",\n                        \"type\": \"text\",\n                        \"value\": \"\",\n                        \"description\": \"Link to download the device calibration certificate\"\n                    },\n                    \"destination\": {\n                        \"key\": \"destination\",\n                        \"text\": \"Destination\",\n                        \"type\": \"text\",\n                        \"value\": \"\",\n                        \"description\": \"If a destination is set as AutoStop on active route\"\n                    },\n                    \"route-status\": {\n                        \"key\": \"route-status\",\n                        \"text\": \"Route status\",\n                        \"type\": \"text\",\n                        \"value\": \"\",\n                        \"description\": \"If the device is in an active route\"\n                    },\n                    \"device-serial\": {\n                        \"key\": \"device-serial\",\n                        \"text\": \"Device serial\",\n                        \"type\": \"text\",\n                        \"value\": \"\",\n                        \"description\": \"Visible ID on device\"\n                    },\n                    \"route-description\": {\n                        \"key\": \"route-description\",\n                        \"text\": \"Route description\",\n                        \"type\": \"text\",\n                        \"value\": \"\",\n                        \"description\": \"Description of active route\"\n                    },\n                    \"max-temp-threshold\": {\n                        \"key\": \"max-temp-threshold\",\n                        \"text\": \"Max Temp Threshold\",\n                        \"type\": \"text\",\n                        \"value\": \"\",\n                        \"description\": \"If a high temperature limit is set on active route\"\n                    },\n                    \"min-temp-threshold\": {\n                        \"key\": \"min-temp-threshold\",\n                        \"text\": \"Min Temp Threshold\",\n                        \"type\": \"text\",\n                        \"value\": \"\",\n                        \"description\": \"If a low temperature limit is set on active route\"\n                    }\n                },\n                \"duration\": \"\",\n                \"certificate\": \"https://surfactdata.blob.core.windows.net/certificate/c44f6701-c0c7-4618-ab9d-3cb0c2b9027b.pdf\",\n                \"destination\": \"\",\n                \"_device_type\": \"plus\",\n                \"route-status\": \"\",\n                \"device-serial\": \"618-ab9-3cb\",\n                \"_location_type\": \"specified\",\n                \"route-description\": \"\",\n                \"_location_variable\": \"position\",\n                \"max-temp-threshold\": \"\",\n                \"min-temp-threshold\": \"\"\n            },\n            \"isActive\": true,\n            \"lastActivity\": 1752148455325,\n            \"createdAt\": \"2025-07-02T22:04:41.456356Z\",\n            \"variables\": \"https://api.surfact.com/api/v2.0/devices/6865acf980bcac000f4ca5ec/variables\",\n            \"variablesCount\": 16\n        },\n        {\n            \"url\": \"https://api.surfact.com/api/v2.0/devices/6865acef80bcac000f4ca5db\",\n            \"id\": \"6865acef80bcac000f4ca5db\",\n            \"organization\": {\n                \"url\": \"https://api.surfact.com/api/v2.0/organizations/6865ac3080bcac000f4ca585\",\n                \"id\": \"6865ac3080bcac000f4ca585\",\n                \"label\": \"1f7fd11c-64fa-416a-9921-256dcbeb0764\",\n                \"name\": \"Demo6\",\n                \"createdAt\": \"2025-07-02T22:01:20.428789Z\"\n            },\n            \"label\": \"446fe7e1-56a8-42c6-961c-56eb89f85dbe\",\n            \"name\": \"3c0-ab5-d96\",\n            \"description\": \"\",\n            \"tags\": [],\n            \"properties\": {\n                \"qr\": \"https://surfact.azurewebsites.net/?qrid=717533cd-3e26-43c0-ab52-d965ac531743\",\n                \"_icon\": \"hockey-puck\",\n                \"_color\": \"#2fbd68\",\n                \"_config\": {\n                    \"qr\": {\n                        \"key\": \"qr\",\n                        \"text\": \"Qr\",\n                        \"type\": \"text\",\n                        \"value\": \"\",\n                        \"description\": \"Same url as when scanning the QR on the device\"\n                    },\n                    \"duration\": {\n                        \"key\": \"duration\",\n                        \"text\": \"Duration\",\n                        \"type\": \"text\",\n                        \"value\": \"\",\n                        \"description\": \"If a timeout threshold is set as AutoStop on active route\"\n                    },\n                    \"certificate\": {\n                        \"key\": \"certificate\",\n                        \"text\": \"Certificate\",\n                        \"type\": \"text\",\n                        \"value\": \"\",\n                        \"description\": \"Link to download the device calibration certificate\"\n                    },\n                    \"destination\": {\n                        \"key\": \"destination\",\n                        \"text\": \"Destination\",\n                        \"type\": \"text\",\n                        \"value\": \"\",\n                        \"description\": \"If a destination is set as AutoStop on active route\"\n                    },\n                    \"route-status\": {\n                        \"key\": \"route-status\",\n                        \"text\": \"Route status\",\n                        \"type\": \"text\",\n                        \"value\": \"\",\n                        \"description\": \"If the device is in an active route\"\n                    },\n                    \"device-serial\": {\n                        \"key\": \"device-serial\",\n                        \"text\": \"Device serial\",\n                        \"type\": \"text\",\n                        \"value\": \"\",\n                        \"description\": \"Visible ID on device\"\n                    },\n                    \"route-description\": {\n                        \"key\": \"route-description\",\n                        \"text\": \"Route description\",\n                        \"type\": \"text\",\n                        \"value\": \"\",\n                        \"description\": \"Description of active route\"\n                    },\n                    \"max-temp-threshold\": {\n                        \"key\": \"max-temp-threshold\",\n                        \"text\": \"Max Temp Threshold\",\n                        \"type\": \"text\",\n                        \"value\": \"\",\n                        \"description\": \"If a high temperature limit is set on active route\"\n                    },\n                    \"min-temp-threshold\": {\n                        \"key\": \"min-temp-threshold\",\n                        \"text\": \"Min Temp Threshold\",\n                        \"type\": \"text\",\n                        \"value\": \"\",\n                        \"description\": \"If a low temperature limit is set on active route\"\n                    }\n                },\n                \"duration\": \"\",\n                \"certificate\": \"https://surfactdata.blob.core.windows.net/certificate/717533cd-3e26-43c0-ab52-d965ac531743.pdf\",\n                \"destination\": \"\",\n                \"_device_type\": \"plus\",\n                \"route-status\": \"\",\n                \"device-serial\": \"3c0-ab5-d96\",\n                \"_location_type\": \"specified\",\n                \"route-description\": \"\",\n                \"_location_variable\": \"position\",\n                \"max-temp-threshold\": \"\",\n                \"min-temp-threshold\": \"\"\n            },\n            \"isActive\": true,\n            \"lastActivity\": 1752147555048,\n            \"createdAt\": \"2025-07-02T22:04:31.454302Z\",\n            \"variables\": \"https://api.surfact.com/api/v2.0/devices/6865acef80bcac000f4ca5db/variables\",\n            \"variablesCount\": 16\n        },\n        {\n            \"url\": \"https://api.surfact.com/api/v2.0/devices/6865ace537ea46000e7286a2\",\n            \"id\": \"6865ace537ea46000e7286a2\",\n            \"organization\": {\n                \"url\": \"https://api.surfact.com/api/v2.0/organizations/6865ac3080bcac000f4ca585\",\n                \"id\": \"6865ac3080bcac000f4ca585\",\n                \"label\": \"1f7fd11c-64fa-416a-9921-256dcbeb0764\",\n                \"name\": \"Demo6\",\n                \"createdAt\": \"2025-07-02T22:01:20.428789Z\"\n            },\n            \"label\": \"91e51b8b-fef4-4752-9668-0e956d69111e\",\n            \"name\": \"4b3-aa7-422\",\n            \"description\": \"\",\n            \"tags\": [],\n            \"properties\": {\n                \"qr\": \"https://surfact.azurewebsites.net/?qrid=3a3306fe-e7ee-44b3-aa74-4228f066a250\",\n                \"_icon\": \"hockey-puck\",\n                \"_color\": \"#2fbd68\",\n                \"_config\": {\n                    \"qr\": {\n                        \"key\": \"qr\",\n                        \"text\": \"Qr\",\n                        \"type\": \"text\",\n                        \"value\": \"\",\n                        \"description\": \"Same url as when scanning the QR on the device\"\n                    },\n                    \"duration\": {\n                        \"key\": \"duration\",\n                        \"text\": \"Duration\",\n                        \"type\": \"text\",\n                        \"value\": \"\",\n                        \"description\": \"If a timeout threshold is set as AutoStop on active route\"\n                    },\n                    \"certificate\": {\n                        \"key\": \"certificate\",\n                        \"text\": \"Certificate\",\n                        \"type\": \"text\",\n                        \"value\": \"\",\n                        \"description\": \"Link to download the device calibration certificate\"\n                    },\n                    \"destination\": {\n                        \"key\": \"destination\",\n                        \"text\": \"Destination\",\n                        \"type\": \"text\",\n                        \"value\": \"\",\n                        \"description\": \"If a destination is set as AutoStop on active route\"\n                    },\n                    \"route-status\": {\n                        \"key\": \"route-status\",\n                        \"text\": \"Route status\",\n                        \"type\": \"text\",\n                        \"value\": \"\",\n                        \"description\": \"If the device is in an active route\"\n                    },\n                    \"device-serial\": {\n                        \"key\": \"device-serial\",\n                        \"text\": \"Device serial\",\n                        \"type\": \"text\",\n                        \"value\": \"\",\n                        \"description\": \"Visible ID on device\"\n                    },\n                    \"route-description\": {\n                        \"key\": \"route-description\",\n                        \"text\": \"Route description\",\n                        \"type\": \"text\",\n                        \"value\": \"\",\n                        \"description\": \"Description of active route\"\n                    },\n                    \"max-temp-threshold\": {\n                        \"key\": \"max-temp-threshold\",\n                        \"text\": \"Max Temp Threshold\",\n                        \"type\": \"text\",\n                        \"value\": \"\",\n                        \"description\": \"If a high temperature limit is set on active route\"\n                    },\n                    \"min-temp-threshold\": {\n                        \"key\": \"min-temp-threshold\",\n                        \"text\": \"Min Temp Threshold\",\n                        \"type\": \"text\",\n                        \"value\": \"\",\n                        \"description\": \"If a low temperature limit is set on active route\"\n                    }\n                },\n                \"duration\": \"\",\n                \"certificate\": \"https://surfactdata.blob.core.windows.net/certificate/3a3306fe-e7ee-44b3-aa74-4228f066a250.pdf\",\n                \"destination\": \"\",\n                \"_device_type\": \"plus\",\n                \"route-status\": \"\",\n                \"device-serial\": \"4b3-aa7-422\",\n                \"_location_type\": \"specified\",\n                \"route-description\": \"\",\n                \"_location_variable\": \"position\",\n                \"max-temp-threshold\": \"\",\n                \"min-temp-threshold\": \"\"\n            },\n            \"isActive\": true,\n            \"lastActivity\": 1752147895051,\n            \"createdAt\": \"2025-07-02T22:04:21.497787Z\",\n            \"variables\": \"https://api.surfact.com/api/v2.0/devices/6865ace537ea46000e7286a2/variables\",\n            \"variablesCount\": 16\n        },\n        {\n            \"url\": \"https://api.surfact.com/api/v2.0/devices/6865acdb80bcac000f4ca598\",\n            \"id\": \"6865acdb80bcac000f4ca598\",\n            \"organization\": {\n                \"url\": \"https://api.surfact.com/api/v2.0/organizations/6865ac3080bcac000f4ca585\",\n                \"id\": \"6865ac3080bcac000f4ca585\",\n                \"label\": \"1f7fd11c-64fa-416a-9921-256dcbeb0764\",\n                \"name\": \"Demo6\",\n                \"createdAt\": \"2025-07-02T22:01:20.428789Z\"\n            },\n            \"label\": \"58a37365-f637-427c-ab1f-4bc55a18319d\",\n            \"name\": \"b9a-b3e-f34\",\n            \"description\": \"\",\n            \"tags\": [],\n            \"properties\": {\n                \"qr\": \"https://surfact.azurewebsites.net/?qrid=95437194-fa9e-4b9a-b3ec-f34396168f33\",\n                \"_icon\": \"hockey-puck\",\n                \"_color\": \"#2fbd68\",\n                \"_config\": {\n                    \"qr\": {\n                        \"key\": \"qr\",\n                        \"text\": \"Qr\",\n                        \"type\": \"text\",\n                        \"value\": \"\",\n                        \"description\": \"Same url as when scanning the QR on the device\"\n                    },\n                    \"duration\": {\n                        \"key\": \"duration\",\n                        \"text\": \"Duration\",\n                        \"type\": \"text\",\n                        \"value\": \"\",\n                        \"description\": \"If a timeout threshold is set as AutoStop on active route\"\n                    },\n                    \"certificate\": {\n                        \"key\": \"certificate\",\n                        \"text\": \"Certificate\",\n                        \"type\": \"text\",\n                        \"value\": \"\",\n                        \"description\": \"Link to download the device calibration certificate\"\n                    },\n                    \"destination\": {\n                        \"key\": \"destination\",\n                        \"text\": \"Destination\",\n                        \"type\": \"text\",\n                        \"value\": \"\",\n                        \"description\": \"If a destination is set as AutoStop on active route\"\n                    },\n                    \"route-status\": {\n                        \"key\": \"route-status\",\n                        \"text\": \"Route status\",\n                        \"type\": \"text\",\n                        \"value\": \"\",\n                        \"description\": \"If the device is in an active route\"\n                    },\n                    \"device-serial\": {\n                        \"key\": \"device-serial\",\n                        \"text\": \"Device serial\",\n                        \"type\": \"text\",\n                        \"value\": \"\",\n                        \"description\": \"Visible ID on device\"\n                    },\n                    \"route-description\": {\n                        \"key\": \"route-description\",\n                        \"text\": \"Route description\",\n                        \"type\": \"text\",\n                        \"value\": \"\",\n                        \"description\": \"Description of active route\"\n                    },\n                    \"max-temp-threshold\": {\n                        \"key\": \"max-temp-threshold\",\n                        \"text\": \"Max Temp Threshold\",\n                        \"type\": \"text\",\n                        \"value\": \"\",\n                        \"description\": \"If a high temperature limit is set on active route\"\n                    },\n                    \"min-temp-threshold\": {\n                        \"key\": \"min-temp-threshold\",\n                        \"text\": \"Min Temp Threshold\",\n                        \"type\": \"text\",\n                        \"value\": \"\",\n                        \"description\": \"If a low temperature limit is set on active route\"\n                    }\n                },\n                \"duration\": \"\",\n                \"certificate\": \"https://surfactdata.blob.core.windows.net/certificate/95437194-fa9e-4b9a-b3ec-f34396168f33.pdf\",\n                \"destination\": \"\",\n                \"_device_type\": \"plus\",\n                \"route-status\": \"\",\n                \"device-serial\": \"b9a-b3e-f34\",\n                \"_location_type\": \"specified\",\n                \"route-description\": \"\",\n                \"_location_variable\": \"position\",\n                \"max-temp-threshold\": \"\",\n                \"min-temp-threshold\": \"\"\n            },\n            \"isActive\": true,\n            \"lastActivity\": 1752140036093,\n            \"createdAt\": \"2025-07-02T22:04:11.474446Z\",\n            \"variables\": \"https://api.surfact.com/api/v2.0/devices/6865acdb80bcac000f4ca598/variables\",\n            \"variablesCount\": 16\n        },\n        {\n            \"url\": \"https://api.surfact.com/api/v2.0/devices/6865accafd265d000ec6a6e0\",\n            \"id\": \"6865accafd265d000ec6a6e0\",\n            \"organization\": {\n                \"url\": \"https://api.surfact.com/api/v2.0/organizations/6865ac3080bcac000f4ca585\",\n                \"id\": \"6865ac3080bcac000f4ca585\",\n                \"label\": \"1f7fd11c-64fa-416a-9921-256dcbeb0764\",\n                \"name\": \"Demo6\",\n                \"createdAt\": \"2025-07-02T22:01:20.428789Z\"\n            },\n            \"label\": \"ce04db35-3f97-46fc-9d6f-f645025f5603\",\n            \"name\": \"338-938-55e\",\n            \"description\": \"\",\n            \"tags\": [],\n            \"properties\": {\n                \"qr\": \"https://surfact.azurewebsites.net/?qrid=83bc3636-be8f-4338-9381-55ecbdacab8a\",\n                \"_icon\": \"hockey-puck\",\n                \"_color\": \"#2fbd68\",\n                \"_config\": {\n                    \"qr\": {\n                        \"key\": \"qr\",\n                        \"text\": \"Qr\",\n                        \"type\": \"text\",\n                        \"value\": \"\",\n                        \"description\": \"Same url as when scanning the QR on the device\"\n                    },\n                    \"duration\": {\n                        \"key\": \"duration\",\n                        \"text\": \"Duration\",\n                        \"type\": \"text\",\n                        \"value\": \"\",\n                        \"description\": \"If a timeout threshold is set as AutoStop on active route\"\n                    },\n                    \"certificate\": {\n                        \"key\": \"certificate\",\n                        \"text\": \"Certificate\",\n                        \"type\": \"text\",\n                        \"value\": \"\",\n                        \"description\": \"Link to download the device calibration certificate\"\n                    },\n                    \"destination\": {\n                        \"key\": \"destination\",\n                        \"text\": \"Destination\",\n                        \"type\": \"text\",\n                        \"value\": \"\",\n                        \"description\": \"If a destination is set as AutoStop on active route\"\n                    },\n                    \"route-status\": {\n                        \"key\": \"route-status\",\n                        \"text\": \"Route status\",\n                        \"type\": \"text\",\n                        \"value\": \"\",\n                        \"description\": \"If the device is in an active route\"\n                    },\n                    \"device-serial\": {\n                        \"key\": \"device-serial\",\n                        \"text\": \"Device serial\",\n                        \"type\": \"text\",\n                        \"value\": \"\",\n                        \"description\": \"Visible ID on device\"\n                    },\n                    \"route-description\": {\n                        \"key\": \"route-description\",\n                        \"text\": \"Route description\",\n                        \"type\": \"text\",\n                        \"value\": \"\",\n                        \"description\": \"Description of active route\"\n                    },\n                    \"max-temp-threshold\": {\n                        \"key\": \"max-temp-threshold\",\n                        \"text\": \"Max Temp Threshold\",\n                        \"type\": \"text\",\n                        \"value\": \"\",\n                        \"description\": \"If a high temperature limit is set on active route\"\n                    },\n                    \"min-temp-threshold\": {\n                        \"key\": \"min-temp-threshold\",\n                        \"text\": \"Min Temp Threshold\",\n                        \"type\": \"text\",\n                        \"value\": \"\",\n                        \"description\": \"If a low temperature limit is set on active route\"\n                    }\n                },\n                \"duration\": \"\",\n                \"certificate\": \"https://surfactdata.blob.core.windows.net/certificate/83bc3636-be8f-4338-9381-55ecbdacab8a.pdf\",\n                \"destination\": \"\",\n                \"_device_type\": \"plus\",\n                \"route-status\": \"\",\n                \"device-serial\": \"338-938-55e\",\n                \"_location_type\": \"specified\",\n                \"route-description\": \"\",\n                \"_location_variable\": \"position\",\n                \"max-temp-threshold\": \"\",\n                \"min-temp-threshold\": \"\"\n            },\n            \"isActive\": true,\n            \"lastActivity\": 1752143459171,\n            \"createdAt\": \"2025-07-02T22:03:54.814368Z\",\n            \"variables\": \"https://api.surfact.com/api/v2.0/devices/6865accafd265d000ec6a6e0/variables\",\n            \"variablesCount\": 16\n        },\n        {\n            \"url\": \"https://api.surfact.com/api/v2.0/devices/6865ac31fd265d000ec6a6de\",\n            \"id\": \"6865ac31fd265d000ec6a6de\",\n            \"organization\": {\n                \"url\": \"https://api.surfact.com/api/v2.0/organizations/6865ac3080bcac000f4ca585\",\n                \"id\": \"6865ac3080bcac000f4ca585\",\n                \"label\": \"1f7fd11c-64fa-416a-9921-256dcbeb0764\",\n                \"name\": \"Demo6\",\n                \"createdAt\": \"2025-07-02T22:01:20.428789Z\"\n            },\n            \"label\": \"1f7fd11c-64fa-416a-9921-256dcbeb0764_reports\",\n            \"name\": \"Demo6_reports\",\n            \"description\": \"\",\n            \"tags\": [],\n            \"properties\": {},\n            \"isActive\": true,\n            \"lastActivity\": 1751493682268,\n            \"createdAt\": \"2025-07-02T22:01:21.203966Z\",\n            \"variables\": \"https://api.surfact.com/api/v2.0/devices/6865ac31fd265d000ec6a6de/variables\",\n            \"variablesCount\": 1\n        }\n    ]\n}"},{"id":"f4724699-6b62-4dc9-b648-0a171646232b","name":"All Devices","originalRequest":{"method":"GET","header":[{"key":"","value":"","type":"text","disabled":true}],"url":"https://api.surfact.com/api/v2.0/devices"},"status":"Unauthorized","code":401,"_postman_previewlanguage":"Text","header":[{"key":"date","value":"Tue, 14 Oct 2025 13:29:03 GMT"},{"key":"content-type","value":"application/json"},{"key":"transfer-encoding","value":"chunked"},{"key":"server","value":"IoTServer"},{"key":"allow","value":"GET, POST, HEAD, OPTIONS"},{"key":"vary","value":"Authorization, origin, Cookie"},{"key":"x-xss-protection","value":"1; mode=block"},{"key":"x-content-type-options","value":"nosniff"},{"key":"strict-transport-security","value":"max-age=31536000; includeSubDomains; preload"},{"key":"content-security-policy","value":"default-src https: wss: data: blob: 'unsafe-eval' 'unsafe-inline'"},{"key":"referrer-policy","value":"strict-origin"},{"key":"permissions-policy","value":"geolocation 'self'; microphone 'none'"},{"key":"x-frame-options","value":"SAMEORIGIN"}],"cookie":[],"responseTime":null,"body":"{\n    \"code\": 401002,\n    \"message\": \"Incorrect authentication credentials.\"\n}"}],"_postman_id":"ef69d58e-6be7-469a-9103-f413c51d57ce"},{"name":"All Variables of a Device","id":"e0cb3ed7-d8fd-42bc-ad28-9aae1acfda82","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[],"url":"https://api.surfact.com/api/v2.0/devices/6780d7f43677a9000bbb0f9a/variables","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"X-Auth-Token"}]},"isInherited":true,"source":{"_postman_id":"7d151dbc-c9c6-4d8d-80fe-df86c0296dc0","id":"7d151dbc-c9c6-4d8d-80fe-df86c0296dc0","name":"⚙️ Device & Organization Management API","type":"folder"}},"urlObject":{"protocol":"https","path":["api","v2.0","devices","6780d7f43677a9000bbb0f9a","variables"],"host":["api","surfact","com"],"query":[],"variable":[]}},"response":[{"id":"6f5a6083-dec5-430b-853a-babd0f807acd","name":"All Variables of a Device","originalRequest":{"method":"GET","header":[],"url":"https://api.surfact.com/api/v2.0/devices/6865acf980bcac000f4ca5ec/variables"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"date","value":"Thu, 10 Jul 2025 16:01:12 GMT"},{"key":"content-type","value":"application/json"},{"key":"transfer-encoding","value":"chunked"},{"key":"server","value":"IoTServer"},{"key":"allow","value":"GET, POST, HEAD, OPTIONS"},{"key":"vary","value":"Authorization, origin, Cookie"},{"key":"set-cookie","value":"__ubidots_ui=dXNlcm5hbWU9VEtfT1JHXzExMzM5MV82M18xO3BsYW49ZnJlZS1wbGFu; Domain=.ubidots.com; expires=Fri, 10 Jul 2026 16:01:12 GMT; Max-Age=31536000; Path=/"},{"key":"x-xss-protection","value":"1; mode=block"},{"key":"x-content-type-options","value":"nosniff"},{"key":"strict-transport-security","value":"max-age=31536000; includeSubDomains; preload"},{"key":"content-security-policy","value":"default-src https: wss: data: blob: 'unsafe-eval' 'unsafe-inline'"},{"key":"referrer-policy","value":"strict-origin"},{"key":"permissions-policy","value":"geolocation 'self'; microphone 'none'"},{"key":"x-frame-options","value":"SAMEORIGIN"}],"cookie":[],"responseTime":null,"body":"{\n    \"count\": 12,\n    \"next\": null,\n    \"previous\": null,\n    \"results\": [\n        {\n            \"url\": \"https://api.surfact.com/api/v2.0/variables/6865acfc37ea46000e7286b3\",\n            \"id\": \"6865acfc37ea46000e7286b3\",\n            \"label\": \"farenheit\",\n            \"name\": \"Farenheit (℉)\",\n            \"description\": \"Temperature in Farenheit degrees\",\n            \"device\": {\n                \"url\": \"https://api.surfact.com/api/v2.0/devices/6865acf980bcac000f4ca5ec\",\n                \"id\": \"6865acf980bcac000f4ca5ec\",\n                \"label\": \"a55b6126-c983-4289-8488-d46cf99da76b\",\n                \"name\": \"618-ab9-3cb\",\n                \"createdAt\": \"2025-07-02T22:04:41.456356Z\"\n            },\n            \"tags\": [],\n            \"properties\": {\n                \"_icon\": \"temperature-half\",\n                \"_color\": \"#2ccce4\",\n                \"hidden\": false,\n                \"isLocationVariable\": false,\n                \"_current_organization_id\": 63,\n                \"_previous_variable_label\": \"farenheit\"\n            },\n            \"type\": \"raw\",\n            \"unit\": \"F\",\n            \"syntheticExpression\": \"\",\n            \"createdAt\": \"2025-07-02T22:04:44.936540Z\",\n            \"lastValue\": {\n                \"value\": 76.64,\n                \"timestamp\": 1752162866000,\n                \"context\": {\n                    \"routeId\": \"\",\n                    \"description\": \"\"\n                },\n                \"created_at\": 1752162884247\n            },\n            \"lastActivity\": 1752162890720,\n            \"valuesUrl\": \"https://api.surfact.com/api/v1.6/variables/6865acfc37ea46000e7286b3/values\"\n        },\n        {\n            \"url\": \"https://api.surfact.com/api/v2.0/variables/6865acfc37ea46000e7286b1\",\n            \"id\": \"6865acfc37ea46000e7286b1\",\n            \"label\": \"battery\",\n            \"name\": \"Battery\",\n            \"description\": \"\",\n            \"device\": {\n                \"url\": \"https://api.surfact.com/api/v2.0/devices/6865acf980bcac000f4ca5ec\",\n                \"id\": \"6865acf980bcac000f4ca5ec\",\n                \"label\": \"a55b6126-c983-4289-8488-d46cf99da76b\",\n                \"name\": \"618-ab9-3cb\",\n                \"createdAt\": \"2025-07-02T22:04:41.456356Z\"\n            },\n            \"tags\": [],\n            \"properties\": {\n                \"_icon\": \"battery-half\",\n                \"_color\": \"#2ccce4\",\n                \"hidden\": false,\n                \"isLocationVariable\": false,\n                \"_current_organization_id\": 63,\n                \"_previous_variable_label\": \"battery\"\n            },\n            \"type\": \"raw\",\n            \"unit\": \"%\",\n            \"syntheticExpression\": \"\",\n            \"createdAt\": \"2025-07-02T22:04:44.561004Z\",\n            \"lastValue\": {\n                \"value\": 100,\n                \"timestamp\": 1752155649000,\n                \"context\": {\n                    \"msg_week\": \"622\",\n                    \"msg_day\": \"96\",\n                    \"bat_voltage\": \"5284\"\n                },\n                \"created_at\": 1752155673768\n            },\n            \"lastActivity\": 1752155673772,\n            \"valuesUrl\": \"https://api.surfact.com/api/v1.6/variables/6865acfc37ea46000e7286b1/values\"\n        },\n        {\n            \"url\": \"https://api.surfact.com/api/v2.0/variables/6865acfc37ea46000e7286b0\",\n            \"id\": \"6865acfc37ea46000e7286b0\",\n            \"label\": \"longitude\",\n            \"name\": \"Longitude\",\n            \"description\": \"\",\n            \"device\": {\n                \"url\": \"https://api.surfact.com/api/v2.0/devices/6865acf980bcac000f4ca5ec\",\n                \"id\": \"6865acf980bcac000f4ca5ec\",\n                \"label\": \"a55b6126-c983-4289-8488-d46cf99da76b\",\n                \"name\": \"618-ab9-3cb\",\n                \"createdAt\": \"2025-07-02T22:04:41.456356Z\"\n            },\n            \"tags\": [],\n            \"properties\": {\n                \"_icon\": \"map-pin\",\n                \"_color\": \"#2ccce4\",\n                \"hidden\": false,\n                \"isLocationVariable\": false,\n                \"_current_organization_id\": 63,\n                \"_previous_variable_label\": \"longitude\"\n            },\n            \"type\": \"raw\",\n            \"unit\": \"\",\n            \"syntheticExpression\": \"\",\n            \"createdAt\": \"2025-07-02T22:04:44.379937Z\",\n            \"lastValue\": {\n                \"value\": 10.83404303,\n                \"timestamp\": 1752155649000,\n                \"context\": {\n                    \"routeId\": \"\",\n                    \"description\": \"\"\n                },\n                \"created_at\": 1752155673768\n            },\n            \"lastActivity\": 1752155673774,\n            \"valuesUrl\": \"https://api.surfact.com/api/v1.6/variables/6865acfc37ea46000e7286b0/values\"\n        },\n        {\n            \"url\": \"https://api.surfact.com/api/v2.0/variables/6865acfc37ea46000e7286af\",\n            \"id\": \"6865acfc37ea46000e7286af\",\n            \"label\": \"latitude\",\n            \"name\": \"Latitude\",\n            \"description\": \"\",\n            \"device\": {\n                \"url\": \"https://api.surfact.com/api/v2.0/devices/6865acf980bcac000f4ca5ec\",\n                \"id\": \"6865acf980bcac000f4ca5ec\",\n                \"label\": \"a55b6126-c983-4289-8488-d46cf99da76b\",\n                \"name\": \"618-ab9-3cb\",\n                \"createdAt\": \"2025-07-02T22:04:41.456356Z\"\n            },\n            \"tags\": [],\n            \"properties\": {\n                \"_icon\": \"map-pin\",\n                \"_color\": \"#2ccce4\",\n                \"hidden\": false,\n                \"isLocationVariable\": false,\n                \"_current_organization_id\": 63,\n                \"_previous_variable_label\": \"latitude\"\n            },\n            \"type\": \"raw\",\n            \"unit\": \"\",\n            \"syntheticExpression\": \"\",\n            \"createdAt\": \"2025-07-02T22:04:44.172814Z\",\n            \"lastValue\": {\n                \"value\": 59.90187049,\n                \"timestamp\": 1752155649000,\n                \"context\": {\n                    \"description\": \"\",\n                    \"routeId\": \"\"\n                },\n                \"created_at\": 1752155673768\n            },\n            \"lastActivity\": 1752155673772,\n            \"valuesUrl\": \"https://api.surfact.com/api/v1.6/variables/6865acfc37ea46000e7286af/values\"\n        },\n        {\n            \"url\": \"https://api.surfact.com/api/v2.0/variables/6865acfb37ea46000e7286ad\",\n            \"id\": \"6865acfb37ea46000e7286ad\",\n            \"label\": \"position\",\n            \"name\": \"Position Accuracy\",\n            \"description\": \"Accuracy of position measured with triangulation in the mobile network of the device\",\n            \"device\": {\n                \"url\": \"https://api.surfact.com/api/v2.0/devices/6865acf980bcac000f4ca5ec\",\n                \"id\": \"6865acf980bcac000f4ca5ec\",\n                \"label\": \"a55b6126-c983-4289-8488-d46cf99da76b\",\n                \"name\": \"618-ab9-3cb\",\n                \"createdAt\": \"2025-07-02T22:04:41.456356Z\"\n            },\n            \"tags\": [],\n            \"properties\": {\n                \"_icon\": \"location-arrow\",\n                \"_color\": \"#2ccce4\",\n                \"hidden\": false,\n                \"isLocationVariable\": true,\n                \"_current_organization_id\": 63,\n                \"_previous_variable_label\": \"position\"\n            },\n            \"type\": \"raw\",\n            \"unit\": \"meters\",\n            \"syntheticExpression\": \"\",\n            \"createdAt\": \"2025-07-02T22:04:43.802802Z\",\n            \"lastValue\": {\n                \"value\": 1708,\n                \"timestamp\": 1752155649000,\n                \"context\": {\n                    \"lng\": 10.83404303,\n                    \"routeId\": \"\",\n                    \"lat\": 59.90187049,\n                    \"description\": \"\"\n                },\n                \"created_at\": 1752155673768\n            },\n            \"lastActivity\": 1752155673772,\n            \"valuesUrl\": \"https://api.surfact.com/api/v1.6/variables/6865acfb37ea46000e7286ad/values\"\n        },\n        {\n            \"url\": \"https://api.surfact.com/api/v2.0/variables/6865acfb37ea46000e7286ac\",\n            \"id\": \"6865acfb37ea46000e7286ac\",\n            \"label\": \"temp-deviation\",\n            \"name\": \"Temp Deviation\",\n            \"description\": \"If an active route has been started with set temperature limits, this variable shows the deviation from the limits\",\n            \"device\": {\n                \"url\": \"https://api.surfact.com/api/v2.0/devices/6865acf980bcac000f4ca5ec\",\n                \"id\": \"6865acf980bcac000f4ca5ec\",\n                \"label\": \"a55b6126-c983-4289-8488-d46cf99da76b\",\n                \"name\": \"618-ab9-3cb\",\n                \"createdAt\": \"2025-07-02T22:04:41.456356Z\"\n            },\n            \"tags\": [],\n            \"properties\": {\n                \"_icon\": \"flag\",\n                \"_color\": \"#2ccce4\",\n                \"hidden\": false,\n                \"isLocationVariable\": false,\n                \"_current_organization_id\": 63,\n                \"_previous_variable_label\": \"temp-deviation\"\n            },\n            \"type\": \"raw\",\n            \"unit\": \"C\",\n            \"syntheticExpression\": \"\",\n            \"createdAt\": \"2025-07-02T22:04:43.622262Z\",\n            \"lastValue\": {\n                \"value\": -2,\n                \"timestamp\": 1752162866000,\n                \"context\": {\n                    \"mintemp\": \"\",\n                    \"maxtemp\": \"\",\n                    \"measuredtemp\": \"24.8\"\n                },\n                \"created_at\": 1752162884247\n            },\n            \"lastActivity\": 1752162890720,\n            \"valuesUrl\": \"https://api.surfact.com/api/v1.6/variables/6865acfb37ea46000e7286ac/values\"\n        },\n        {\n            \"url\": \"https://api.surfact.com/api/v2.0/variables/6865acfb37ea46000e7286ab\",\n            \"id\": \"6865acfb37ea46000e7286ab\",\n            \"label\": \"orientation_z\",\n            \"name\": \"Orientation_z\",\n            \"description\": \"Orientation measured by the device Z axis\",\n            \"device\": {\n                \"url\": \"https://api.surfact.com/api/v2.0/devices/6865acf980bcac000f4ca5ec\",\n                \"id\": \"6865acf980bcac000f4ca5ec\",\n                \"label\": \"a55b6126-c983-4289-8488-d46cf99da76b\",\n                \"name\": \"618-ab9-3cb\",\n                \"createdAt\": \"2025-07-02T22:04:41.456356Z\"\n            },\n            \"tags\": [],\n            \"properties\": {\n                \"_icon\": \"arrows\",\n                \"_color\": \"#2ccce4\",\n                \"hidden\": false,\n                \"isLocationVariable\": false,\n                \"_current_organization_id\": 63,\n                \"_previous_variable_label\": \"orientation_z\"\n            },\n            \"type\": \"raw\",\n            \"unit\": \"Z\",\n            \"syntheticExpression\": \"\",\n            \"createdAt\": \"2025-07-02T22:04:43.430345Z\",\n            \"lastValue\": {\n                \"value\": 0.2,\n                \"timestamp\": 1752162866000,\n                \"context\": {\n                    \"description\": \"\",\n                    \"routeId\": \"\"\n                },\n                \"created_at\": 1752162884247\n            },\n            \"lastActivity\": 1752162884256,\n            \"valuesUrl\": \"https://api.surfact.com/api/v1.6/variables/6865acfb37ea46000e7286ab/values\"\n        },\n        {\n            \"url\": \"https://api.surfact.com/api/v2.0/variables/6865acfb37ea46000e7286aa\",\n            \"id\": \"6865acfb37ea46000e7286aa\",\n            \"label\": \"orientation_y\",\n            \"name\": \"Orientation_y\",\n            \"description\": \"Orientation measured by the device Y axis\",\n            \"device\": {\n                \"url\": \"https://api.surfact.com/api/v2.0/devices/6865acf980bcac000f4ca5ec\",\n                \"id\": \"6865acf980bcac000f4ca5ec\",\n                \"label\": \"a55b6126-c983-4289-8488-d46cf99da76b\",\n                \"name\": \"618-ab9-3cb\",\n                \"createdAt\": \"2025-07-02T22:04:41.456356Z\"\n            },\n            \"tags\": [],\n            \"properties\": {\n                \"_icon\": \"arrows\",\n                \"_color\": \"#2ccce4\",\n                \"hidden\": false,\n                \"isLocationVariable\": false,\n                \"_current_organization_id\": 63,\n                \"_previous_variable_label\": \"orientation_y\"\n            },\n            \"type\": \"raw\",\n            \"unit\": \"Y\",\n            \"syntheticExpression\": \"\",\n            \"createdAt\": \"2025-07-02T22:04:43.242077Z\",\n            \"lastValue\": {\n                \"value\": 3.97,\n                \"timestamp\": 1752162866000,\n                \"context\": {\n                    \"description\": \"\",\n                    \"routeId\": \"\"\n                },\n                \"created_at\": 1752162884247\n            },\n            \"lastActivity\": 1752162884254,\n            \"valuesUrl\": \"https://api.surfact.com/api/v1.6/variables/6865acfb37ea46000e7286aa/values\"\n        },\n        {\n            \"url\": \"https://api.surfact.com/api/v2.0/variables/6865acfb37ea46000e7286a9\",\n            \"id\": \"6865acfb37ea46000e7286a9\",\n            \"label\": \"orientation_x\",\n            \"name\": \"Orientation_x\",\n            \"description\": \"Orientation measured by the device X axis\",\n            \"device\": {\n                \"url\": \"https://api.surfact.com/api/v2.0/devices/6865acf980bcac000f4ca5ec\",\n                \"id\": \"6865acf980bcac000f4ca5ec\",\n                \"label\": \"a55b6126-c983-4289-8488-d46cf99da76b\",\n                \"name\": \"618-ab9-3cb\",\n                \"createdAt\": \"2025-07-02T22:04:41.456356Z\"\n            },\n            \"tags\": [],\n            \"properties\": {\n                \"_icon\": \"arrows\",\n                \"_color\": \"#2ccce4\",\n                \"hidden\": false,\n                \"isLocationVariable\": false,\n                \"_current_organization_id\": 63,\n                \"_previous_variable_label\": \"orientation_x\"\n            },\n            \"type\": \"raw\",\n            \"unit\": \"X\",\n            \"syntheticExpression\": \"\",\n            \"createdAt\": \"2025-07-02T22:04:43.058679Z\",\n            \"lastValue\": {\n                \"value\": 9.13,\n                \"timestamp\": 1752162866000,\n                \"context\": {\n                    \"description\": \"\",\n                    \"routeId\": \"\"\n                },\n                \"created_at\": 1752162884247\n            },\n            \"lastActivity\": 1752162884252,\n            \"valuesUrl\": \"https://api.surfact.com/api/v1.6/variables/6865acfb37ea46000e7286a9/values\"\n        },\n        {\n            \"url\": \"https://api.surfact.com/api/v2.0/variables/6865acfa37ea46000e7286a8\",\n            \"id\": \"6865acfa37ea46000e7286a8\",\n            \"label\": \"light\",\n            \"name\": \"Light\",\n            \"description\": \"Light measured by device\",\n            \"device\": {\n                \"url\": \"https://api.surfact.com/api/v2.0/devices/6865acf980bcac000f4ca5ec\",\n                \"id\": \"6865acf980bcac000f4ca5ec\",\n                \"label\": \"a55b6126-c983-4289-8488-d46cf99da76b\",\n                \"name\": \"618-ab9-3cb\",\n                \"createdAt\": \"2025-07-02T22:04:41.456356Z\"\n            },\n            \"tags\": [],\n            \"properties\": {\n                \"_icon\": \"lightbulb\",\n                \"_color\": \"#2ccce4\",\n                \"hidden\": false,\n                \"isLocationVariable\": false,\n                \"_current_organization_id\": 63,\n                \"_previous_variable_label\": \"light\"\n            },\n            \"type\": \"raw\",\n            \"unit\": \"Lux\",\n            \"syntheticExpression\": \"\",\n            \"createdAt\": \"2025-07-02T22:04:42.870832Z\",\n            \"lastValue\": {\n                \"value\": 0,\n                \"timestamp\": 1752162866000,\n                \"context\": {\n                    \"routeId\": \"\",\n                    \"description\": \"\"\n                },\n                \"created_at\": 1752162884247\n            },\n            \"lastActivity\": 1752162884252,\n            \"valuesUrl\": \"https://api.surfact.com/api/v1.6/variables/6865acfa37ea46000e7286a8/values\"\n        },\n        {\n            \"url\": \"https://api.surfact.com/api/v2.0/variables/6865acfa37ea46000e7286a6\",\n            \"id\": \"6865acfa37ea46000e7286a6\",\n            \"label\": \"humidity\",\n            \"name\": \"Humidity\",\n            \"description\": \"Humidity measured by device\",\n            \"device\": {\n                \"url\": \"https://api.surfact.com/api/v2.0/devices/6865acf980bcac000f4ca5ec\",\n                \"id\": \"6865acf980bcac000f4ca5ec\",\n                \"label\": \"a55b6126-c983-4289-8488-d46cf99da76b\",\n                \"name\": \"618-ab9-3cb\",\n                \"createdAt\": \"2025-07-02T22:04:41.456356Z\"\n            },\n            \"tags\": [],\n            \"properties\": {\n                \"_icon\": \"tint\",\n                \"_color\": \"#d4d4d4\",\n                \"hidden\": false,\n                \"isLocationVariable\": false,\n                \"_current_organization_id\": 63,\n                \"_previous_variable_label\": \"humidity\"\n            },\n            \"type\": \"raw\",\n            \"unit\": \"%RH\",\n            \"syntheticExpression\": \"\",\n            \"createdAt\": \"2025-07-02T22:04:42.494321Z\",\n            \"lastValue\": {\n                \"value\": 45,\n                \"timestamp\": 1752162866000,\n                \"context\": {\n                    \"routeId\": \"\",\n                    \"description\": \"\"\n                },\n                \"created_at\": 1752162884247\n            },\n            \"lastActivity\": 1752162884257,\n            \"valuesUrl\": \"https://api.surfact.com/api/v1.6/variables/6865acfa37ea46000e7286a6/values\"\n        },\n        {\n            \"url\": \"https://api.surfact.com/api/v2.0/variables/6865acfa37ea46000e7286a5\",\n            \"id\": \"6865acfa37ea46000e7286a5\",\n            \"label\": \"temperature\",\n            \"name\": \"Temperature (℃)\",\n            \"description\": \"Temperature measured by device\",\n            \"device\": {\n                \"url\": \"https://api.surfact.com/api/v2.0/devices/6865acf980bcac000f4ca5ec\",\n                \"id\": \"6865acf980bcac000f4ca5ec\",\n                \"label\": \"a55b6126-c983-4289-8488-d46cf99da76b\",\n                \"name\": \"618-ab9-3cb\",\n                \"createdAt\": \"2025-07-02T22:04:41.456356Z\"\n            },\n            \"tags\": [],\n            \"properties\": {\n                \"_icon\": \"thermometer-quarter\",\n                \"_color\": \"#2ccce4\",\n                \"hidden\": false,\n                \"isLocationVariable\": false,\n                \"_current_organization_id\": 63,\n                \"_previous_variable_label\": \"temperature\"\n            },\n            \"type\": \"raw\",\n            \"unit\": \"C\",\n            \"syntheticExpression\": \"\",\n            \"createdAt\": \"2025-07-02T22:04:42.088311Z\",\n            \"lastValue\": {\n                \"value\": 24.8,\n                \"timestamp\": 1752162866000,\n                \"context\": {\n                    \"routeId\": \"\",\n                    \"description\": \"\"\n                },\n                \"created_at\": 1752162884247\n            },\n            \"lastActivity\": 1752162890721,\n            \"valuesUrl\": \"https://api.surfact.com/api/v1.6/variables/6865acfa37ea46000e7286a5/values\"\n        }\n    ]\n}"}],"_postman_id":"e0cb3ed7-d8fd-42bc-ad28-9aae1acfda82"},{"name":"Get Last Value of a Variable","id":"1c1a076d-8574-4a6f-8b76-b6185dc2a9a8","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[],"url":"https://api.surfact.com/api/v2.0/variables/6780d89b84e50c000b809c01","description":"<p>There are two alternate ways to retrieve the most recent value of a specific variable.</p>\n<p>To retrieve a single Variable please make a GET request to the following URL:</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>HTTP Method</th>\n<th>URL</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>GET</td>\n<td><code>https://api.surfact.com/api/v2.0/variables//</code></td>\n</tr>\n</tbody>\n</table>\n</div><p>To retrieve a single Variable of a Device please make a GET request to the following URL:</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>HTTP Method</th>\n<th>URL</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>GET</td>\n<td><code>https://api.surfact.com/api/v2.0/devices//variables//</code></td>\n</tr>\n</tbody>\n</table>\n</div><hr />\n<h2 id=\"path-parameters\">Path Parameters</h2>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Parameter</th>\n<th>Type</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>device_label</code></td>\n<td>String</td>\n<td>The label of the device containing the variable</td>\n</tr>\n<tr>\n<td><code>variable_label</code></td>\n<td>String</td>\n<td>The label of the variable to retrieve</td>\n</tr>\n</tbody>\n</table>\n</div><hr />\n<hr />\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-python\">import requests\nTOKEN = \"your_token_here\"\nDEVICE_LABEL = \"temperature-sensor\"\nVARIABLE_LABEL = \"室温\"\nurl = f\"https://api.surfact.com/api/v1.6/devices/{DEVICE_LABEL}/{VARIABLE_LABEL}/lv\"\nheaders = {\"X-Auth-Token\": TOKEN}\nresponse = requests.get(url, headers=headers)\nif response.status_code == 200:\n    last_value = float(response.text)\n    print(f\"Last value: {last_value}\")\nelse:\n    print(f\"Error: {response.json()}\")\n\n</code></pre>\n<hr />\n<h2 id=\"javascript-example\">JavaScript Example</h2>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-javascript\">const TOKEN = \"your_token_here\";\nconst DEVICE_LABEL = \"temperature-sensor\";\nconst VARIABLE_LABEL = \"室温\";\nconst url = `https://api.surfact.com/api/v1.6/devices/${DEVICE_LABEL}/${VARIABLE_LABEL}/lv`;\nfetch(url, {\n  headers: {\n    \"X-Auth-Token\": TOKEN\n  }\n})\n  .then(response =&gt; response.text())\n  .then(value =&gt; console.log(\"Last value:\", parseFloat(value)))\n  .catch(error =&gt; console.error(\"Error:\", error));\n\n</code></pre>\n<hr />\n<h2 id=\"use-cases\">Use Cases</h2>\n<ul>\n<li><p><strong>Dashboard displays</strong>: Show current sensor readings</p>\n</li>\n<li><p><strong>Status monitoring</strong>: Check latest device status</p>\n</li>\n<li><p><strong>Alerting systems</strong>: Compare current value against thresholds</p>\n</li>\n<li><p><strong>Quick checks</strong>: Get instant value without retrieving full history</p>\n</li>\n</ul>\n<hr />\n<h2 id=\"notes\">Notes</h2>\n<ul>\n<li><p>Response is a simple numeric value (not JSON)</p>\n</li>\n<li><p>Returns only the value itself, without timestamp or metadata</p>\n</li>\n<li><p>For full value details including timestamp and context, use the <a href=\"https://claude.ai/chat/surfact_data_raw_series.md\">Data Raw Series</a> endpoint with <code>limit: 1</code></p>\n</li>\n<li><p>Device and variable labels are case-sensitive</p>\n</li>\n</ul>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"X-Auth-Token"}]},"isInherited":true,"source":{"_postman_id":"7d151dbc-c9c6-4d8d-80fe-df86c0296dc0","id":"7d151dbc-c9c6-4d8d-80fe-df86c0296dc0","name":"⚙️ Device & Organization Management API","type":"folder"}},"urlObject":{"protocol":"https","path":["api","v2.0","variables","6780d89b84e50c000b809c01"],"host":["api","surfact","com"],"query":[],"variable":[]}},"response":[{"id":"0fde0b0d-d569-4449-85f3-15b659e4084f","name":"Individual Variable of a Device","originalRequest":{"method":"GET","header":[],"url":"https://api.surfact.com/api/v2.0/variables/6865acfa37ea46000e7286a5"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"date","value":"Thu, 10 Jul 2025 16:03:17 GMT"},{"key":"content-type","value":"application/json"},{"key":"transfer-encoding","value":"chunked"},{"key":"server","value":"IoTServer"},{"key":"allow","value":"GET, PUT, PATCH, DELETE, HEAD, OPTIONS"},{"key":"vary","value":"Authorization, origin, Cookie"},{"key":"set-cookie","value":"__ubidots_ui=dXNlcm5hbWU9VEtfT1JHXzExMzM5MV82M18xO3BsYW49ZnJlZS1wbGFu; Domain=.ubidots.com; expires=Fri, 10 Jul 2026 16:03:17 GMT; Max-Age=31536000; Path=/"},{"key":"x-xss-protection","value":"1; mode=block"},{"key":"x-content-type-options","value":"nosniff"},{"key":"strict-transport-security","value":"max-age=31536000; includeSubDomains; preload"},{"key":"content-security-policy","value":"default-src https: wss: data: blob: 'unsafe-eval' 'unsafe-inline'"},{"key":"referrer-policy","value":"strict-origin"},{"key":"permissions-policy","value":"geolocation 'self'; microphone 'none'"},{"key":"x-frame-options","value":"SAMEORIGIN"}],"cookie":[],"responseTime":null,"body":"{\n    \"url\": \"https://api.surfact.com/api/v2.0/variables/6865acfa37ea46000e7286a5\",\n    \"id\": \"6865acfa37ea46000e7286a5\",\n    \"label\": \"temperature\",\n    \"name\": \"Temperature (℃)\",\n    \"description\": \"Temperature measured by device\",\n    \"device\": {\n        \"url\": \"https://api.surfact.com/api/v2.0/devices/6865acf980bcac000f4ca5ec\",\n        \"id\": \"6865acf980bcac000f4ca5ec\",\n        \"label\": \"a55b6126-c983-4289-8488-d46cf99da76b\",\n        \"name\": \"618-ab9-3cb\",\n        \"createdAt\": \"2025-07-02T22:04:41.456356Z\"\n    },\n    \"tags\": [],\n    \"properties\": {\n        \"_icon\": \"thermometer-quarter\",\n        \"_color\": \"#2ccce4\",\n        \"hidden\": false,\n        \"isLocationVariable\": false,\n        \"_current_organization_id\": 63,\n        \"_previous_variable_label\": \"temperature\"\n    },\n    \"type\": \"raw\",\n    \"unit\": \"C\",\n    \"syntheticExpression\": \"\",\n    \"createdAt\": \"2025-07-02T22:04:42.088311Z\",\n    \"lastValue\": {\n        \"value\": 24.8,\n        \"timestamp\": 1752162866000,\n        \"context\": {\n            \"routeId\": \"\",\n            \"description\": \"\"\n        },\n        \"created_at\": 1752162884247\n    },\n    \"lastActivity\": 1752162890721,\n    \"valuesUrl\": \"https://api.surfact.com/api/v1.6/variables/6865acfa37ea46000e7286a5/values\"\n}"}],"_postman_id":"1c1a076d-8574-4a6f-8b76-b6185dc2a9a8"},{"name":"All Events","id":"8a952b11-9407-4c61-9ebf-fa1c3e5e7b85","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[],"url":"https://api.surfact.com/api/v2.0/events/","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"X-Auth-Token"}]},"isInherited":true,"source":{"_postman_id":"7d151dbc-c9c6-4d8d-80fe-df86c0296dc0","id":"7d151dbc-c9c6-4d8d-80fe-df86c0296dc0","name":"⚙️ Device & Organization Management API","type":"folder"}},"urlObject":{"protocol":"https","path":["api","v2.0","events",""],"host":["api","surfact","com"],"query":[],"variable":[]}},"response":[{"id":"bd1bac3b-dc1c-4ed9-842c-f20acb8c7c04","name":"No events created","originalRequest":{"method":"GET","header":[],"url":"https://api.surfact.com/api/v2.0/events/"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"date","value":"Thu, 10 Jul 2025 16:04:53 GMT"},{"key":"content-type","value":"application/json"},{"key":"transfer-encoding","value":"chunked"},{"key":"server","value":"IoTServer"},{"key":"allow","value":"GET, POST, HEAD, OPTIONS"},{"key":"vary","value":"Authorization, origin, Cookie"},{"key":"set-cookie","value":"__ubidots_ui=dXNlcm5hbWU9VEtfT1JHXzExMzM5MV82M18xO3BsYW49ZnJlZS1wbGFu; Domain=.ubidots.com; expires=Fri, 10 Jul 2026 16:04:53 GMT; Max-Age=31536000; Path=/"},{"key":"x-xss-protection","value":"1; mode=block"},{"key":"x-content-type-options","value":"nosniff"},{"key":"strict-transport-security","value":"max-age=31536000; includeSubDomains; preload"},{"key":"content-security-policy","value":"default-src https: wss: data: blob: 'unsafe-eval' 'unsafe-inline'"},{"key":"referrer-policy","value":"strict-origin"},{"key":"permissions-policy","value":"geolocation 'self'; microphone 'none'"},{"key":"x-frame-options","value":"SAMEORIGIN"}],"cookie":[],"responseTime":null,"body":"{\n    \"count\": 0,\n    \"next\": null,\n    \"previous\": null,\n    \"results\": []\n}"}],"_postman_id":"8a952b11-9407-4c61-9ebf-fa1c3e5e7b85"},{"name":"Event Logs","id":"232981e3-9b95-4e83-b4c5-485f28ab4705","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[],"url":"https://api.surfact.com/api/v2.0/events/67d452787c33f2000cbbca88/logs","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"X-Auth-Token"}]},"isInherited":true,"source":{"_postman_id":"7d151dbc-c9c6-4d8d-80fe-df86c0296dc0","id":"7d151dbc-c9c6-4d8d-80fe-df86c0296dc0","name":"⚙️ Device & Organization Management API","type":"folder"}},"urlObject":{"protocol":"https","path":["api","v2.0","events","67d452787c33f2000cbbca88","logs"],"host":["api","surfact","com"],"query":[],"variable":[]}},"response":[],"_postman_id":"232981e3-9b95-4e83-b4c5-485f28ab4705"},{"name":"Create Event","id":"567dced7-004b-4d06-b691-1897fa174b10","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n    \"label\": \"if-var0-then-telegram\",\n    \"name\": \"If var0 then Telegram\",\n    \"description\": \"\",\n    \"tags\": [],\n    \"organization\": null,\n    \"isActive\": true,\n    \"triggers\": [\n        [\n            {\n                \"type\": \"last_value\",\n                \"condition\": {\n                    \"value\": \"60\",\n                    \"operator\": \">\",\n                    \"delay\": 0\n                },\n                \"entity\": {\n                    \"type\": \"variable\",\n                    \"value\": [\n                        {\n                            \"id\": \"6780d89b84e50c000b809c01\"\n                        }\n                    ],\n                    \"operator\": \"or\"\n                }\n            }\n        ]\n    ],\n    \"actions\": [\n        {\n            \"data\": {\n                \"message\": \"Hey there, {{variable.name}} was {{last_value}} at {{trigger_timestamp|timestampformat('America/Bogota')}}.\\n{{from_email}}\",\n                \"numbers\": [\n                    {\n                        \"number\": \"+57  (300) 808 - 3219\",\n                        \"country\": {\n                            \"id\": \"CO\",\n                            \"label\": \"Colombia\",\n                            \"value\": \"+57\"\n                        }\n                    }\n                ]\n            },\n            \"name\": \"Send Telegram\",\n            \"type\": \"telegram\",\n            \"isGeneric\": true,\n            \"exclusiveFor\": [],\n            \"repeatAction\": false,\n            \"idGroupAction\": \"6kfdkaaaa\",\n            \"back_to_normal\": false,\n            \"maxRepetitions\": 10,\n            \"repeatInterval\": {\n                \"unit\": \"T\",\n                \"value\": 60\n            }\n        }\n    ],\n    \"activeDates\": {\n        \"dates\": [\n            [\n                [\n                    \"00:00\",\n                    \"23:59\"\n                ]\n            ],\n            [\n                [\n                    \"00:00\",\n                    \"23:59\"\n                ]\n            ],\n            [\n                [\n                    \"00:00\",\n                    \"23:59\"\n                ]\n            ],\n            [\n                [\n                    \"00:00\",\n                    \"23:59\"\n                ]\n            ],\n            [\n                [\n                    \"00:00\",\n                    \"23:59\"\n                ]\n            ],\n            [\n                [\n                    \"00:00\",\n                    \"23:59\"\n                ]\n            ],\n            [\n                [\n                    \"00:00\",\n                    \"23:59\"\n                ]\n            ]\n        ],\n        \"timezone\": \"America/Bogota\"\n    },\n    \"isGlobalEvent\": false,\n    \"isStatusWidgetEvent\": false,\n    \"statusWidgetContext\": {}\n}","options":{"raw":{"language":"json"}}},"url":"https://api.surfact.com/api/v2.0/events/","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"X-Auth-Token"}]},"isInherited":true,"source":{"_postman_id":"7d151dbc-c9c6-4d8d-80fe-df86c0296dc0","id":"7d151dbc-c9c6-4d8d-80fe-df86c0296dc0","name":"⚙️ Device & Organization Management API","type":"folder"}},"urlObject":{"protocol":"https","path":["api","v2.0","events",""],"host":["api","surfact","com"],"query":[],"variable":[]}},"response":[],"_postman_id":"567dced7-004b-4d06-b691-1897fa174b10"}],"id":"7d151dbc-c9c6-4d8d-80fe-df86c0296dc0","description":"<p>Get devices for your organization, see device metadata, setup events (alerts) for devices and more.</p>\n<p>Base URL is: <code>api.surfact.com/api/v2.0/</code></p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"X-Auth-Token"}]},"isInherited":false},"event":[{"listen":"prerequest","script":{"id":"fdd805ee-b266-45d1-937e-fa74898ca4a4","type":"text/javascript","packages":{},"requests":{},"exec":[""]}},{"listen":"test","script":{"id":"e6c570dc-aa0d-4f51-ac34-333b68895d6d","type":"text/javascript","packages":{},"requests":{},"exec":[""]}}],"_postman_id":"7d151dbc-c9c6-4d8d-80fe-df86c0296dc0"},{"name":"🤖 Webhooks / Data Pipelines","item":[{"name":"Your Webhook Endpoint","id":"0a7feaff-2f4e-4ca5-afbc-e3254a6bf0c3","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[],"url":"integrationpartner.endpoint.com/prod/your-URL-Here","description":"<h2 id=\"payload-format\">Payload Format</h2>\n<p><strong>Standard Payload:</strong></p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-json\">{\n  \"device\": \"device-label\",\n  \"variable\": \"variable-label\",\n  \"value\": 23.5,\n  \"timestamp\": 1634311791000,\n  \"context\": {\n    \"status\": \"active\"\n  }\n}\n\n</code></pre>\n<h3 id>**</h3>\n<p>Custom Payload:** Available on request to match your existing infrastructure.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"X-Auth-Token"},{"key":"value","value":"<value>"}]},"isInherited":true,"source":{"_postman_id":"9efb6fb4-a1a8-4b6e-8891-51ecb5c85492","id":"9efb6fb4-a1a8-4b6e-8891-51ecb5c85492","name":"Surfact API Platform","type":"collection"}},"urlObject":{"path":["prod","your-URL-Here"],"host":["integrationpartner","endpoint","com"],"query":[],"variable":[]}},"response":[],"_postman_id":"0a7feaff-2f4e-4ca5-afbc-e3254a6bf0c3"}],"id":"0cce4b93-1eb4-4700-a2b5-b8ce2bee99b3","description":"<h1 id=\"webhooks\">Webhooks</h1>\n<p>Surfact supports webhooks to push data to your systems in real-time, eliminating the need for constant polling.</p>\n<hr />\n<h2 id=\"use-cases\">Use Cases</h2>\n<ul>\n<li><p>Send data to your database or data warehouse</p>\n</li>\n<li><p>Trigger workflows in systems like Zapier or Make</p>\n</li>\n<li><p>Update dashboards in real-time</p>\n</li>\n<li><p>Alert systems when thresholds are exceeded</p>\n</li>\n<li><p>Integrate with custom applications</p>\n</li>\n</ul>\n<hr />\n<h2 id=\"how-it-works\">How It Works</h2>\n<p>When a variable is updated, Surfact automatically sends an HTTP POST request to your configured endpoint with the data payload.</p>\n<p><strong>Benefits:</strong></p>\n<ul>\n<li><p>Real-time notifications</p>\n</li>\n<li><p>Reduced API calls</p>\n</li>\n<li><p>Lower bandwidth usage</p>\n</li>\n<li><p>No polling overhead</p>\n</li>\n</ul>\n<hr />\n<h2 id=\"setup\">Setup</h2>\n<p>To configure a webhook for your account:</p>\n<ol>\n<li><p><strong>Prepare your endpoint:</strong></p>\n<ul>\n<li><p>HTTPS endpoint URL</p>\n</li>\n<li><p>Authentication credentials (if required)</p>\n</li>\n</ul>\n</li>\n<li><p><strong>Contact support:</strong></p>\n<ul>\n<li><p>Email: <a href=\"https://mailto:support@surfact.com\"><b>support@surfact.com</b></a></p>\n</li>\n<li><p>Provide: endpoint URL and auth credentials</p>\n</li>\n<li><p>Specify: custom payload format (if needed)</p>\n</li>\n</ul>\n</li>\n<li><p><strong>We'll configure and test</strong> your webhook</p>\n</li>\n</ol>\n<hr />\n","_postman_id":"0cce4b93-1eb4-4700-a2b5-b8ce2bee99b3","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"X-Auth-Token"},{"key":"value","value":"<value>"}]},"isInherited":true,"source":{"_postman_id":"9efb6fb4-a1a8-4b6e-8891-51ecb5c85492","id":"9efb6fb4-a1a8-4b6e-8891-51ecb5c85492","name":"Surfact API Platform","type":"collection"}}},{"name":"📡 MQTT","item":[{"name":"Broker URLs","item":[],"id":"22657f01-8b98-4448-9291-14db4d68f021","description":"<h1 id=\"broker-urls\">Broker URLs</h1>\n<p>Access the Surfact MQTT broker through plain MQTT or secure MQTT with TLS using the following endpoints.</p>\n<hr />\n<h2 id=\"mqtt\">MQTT</h2>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Security</th>\n<th>Endpoint</th>\n<th>Port</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><strong>No TLS</strong></td>\n<td><code>api.surfact.com</code></td>\n<td><code>1883</code></td>\n</tr>\n<tr>\n<td><strong>TLS</strong></td>\n<td><code>api.surfact.com</code></td>\n<td><code>8883</code></td>\n</tr>\n</tbody>\n</table>\n</div><h3 id=\"tls-certificate\">TLS Certificate</h3>\n<p>Download the Surfact PEM certificate for TLS connections: <a href=\"https://cdn.surfact.com/certs/roots.pem\">surfact-roots.pem</a></p>\n<p>⚠️ <strong>Security Note:</strong> Always use MQTT with TLS in production to ensure your data travels encrypted, protecting your API token and sensor data from third parties.</p>\n<hr />\n<h2 id=\"mqtt-over-websockets\">MQTT over WebSockets</h2>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Security</th>\n<th>Endpoint</th>\n<th>Port</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><strong>No TLS</strong></td>\n<td><code>api.surfact.com</code></td>\n<td><code>8083</code></td>\n</tr>\n<tr>\n<td><strong>TLS</strong></td>\n<td><code>api.surfact.com</code></td>\n<td><code>8084</code></td>\n</tr>\n</tbody>\n</table>\n</div><hr />\n<h2 id=\"fixed-ip-addresses\">Fixed IP Addresses</h2>\n<p>Surfact supports fixed IP addresses for data ingestion, but <strong>we strongly recommend using DNS endpoints</strong> instead. Fixed IPs may change in the future.</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Protocol</th>\n<th>IPv4</th>\n<th>IPv6</th>\n<th>Port</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>MQTT</td>\n<td><code>107.21.125.25</code></td>\n<td><code>2600:1f18:2446:e000::</code></td>\n<td><code>1883</code> / <code>8883</code></td>\n</tr>\n<tr>\n<td>MQTT</td>\n<td><code>54.236.17.128</code></td>\n<td><code>2600:1f18:2446:e001::</code></td>\n<td><code>1883</code> / <code>8883</code></td>\n</tr>\n</tbody>\n</table>\n</div><p>⚠️ <strong>Best Practice:</strong> Always implement firmware routines using DNS endpoints rather than hardcoding IP addresses.</p>\n","_postman_id":"22657f01-8b98-4448-9291-14db4d68f021","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"X-Auth-Token"},{"key":"value","value":"<value>"}]},"isInherited":true,"source":{"_postman_id":"9efb6fb4-a1a8-4b6e-8891-51ecb5c85492","id":"9efb6fb4-a1a8-4b6e-8891-51ecb5c85492","name":"Surfact API Platform","type":"collection"}}},{"name":"MQTT Authentication","item":[],"id":"c1ae270f-247a-4e18-bafd-863aee3d7020","description":"<h1 id=\"mqtt-authentication\">MQTT Authentication</h1>\n<p>To connect to the Surfact MQTT broker, you need a token. A token is a unique key that authorizes your device to interact with the Surfact API.</p>\n<h2 id=\"connection-credentials\">Connection Credentials</h2>\n<p>When establishing a connection with the MQTT broker, use the following credentials:</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Parameter</th>\n<th>Value</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><strong>Username</strong></td>\n<td>Your Surfact token</td>\n</tr>\n<tr>\n<td><strong>Password</strong></td>\n<td>Any character (not required)</td>\n</tr>\n</tbody>\n</table>\n</div><hr />\n<h2 id=\"getting-your-token\">Getting Your Token</h2>\n<p>See the <a href=\"https://claude.ai/chat/surfact_authentication.md\">Authentication</a> documentation for details on:</p>\n<ul>\n<li><p>Retrieving your token from your account</p>\n</li>\n<li><p>Generating tokens programmatically via API</p>\n</li>\n<li><p>Token validity (6 hours)</p>\n</li>\n</ul>\n<hr />\n<h2 id=\"example-connection\">Example Connection</h2>\n<p><strong>Python (paho-mqtt):</strong></p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-python\">import paho.mqtt.client as mqtt\n# Your Surfact token\ntoken = \"BBFF-nQ5jCC445FfClcKLCQ55YhnTb2oh6knHsZO\"\nclient = mqtt.Client(client_id=\"my-device-12345678901234567890\")\nclient.username_pw_set(username=token, password=\"\")\nclient.connect(\"api.surfact.com\", 8883)\n\n</code></pre>\n<p><strong>JavaScript (mqtt.js):</strong></p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-javascript\">const mqtt = require('mqtt');\n// Your Surfact token\nconst token = 'BBFF-nQ5jCC445FfClcKLCQ55YhnTb2oh6knHsZO';\nconst client = mqtt.connect('mqtts://api.surfact.com:8883', {\n  username: token,\n  password: '',\n  clientId: 'my-device-12345678901234567890'\n});\n\n</code></pre>\n<p><strong>Note:</strong> The password field can be left empty or set to any value—it's not validated.</p>\n","_postman_id":"c1ae270f-247a-4e18-bafd-863aee3d7020","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"X-Auth-Token"},{"key":"value","value":"<value>"}]},"isInherited":true,"source":{"_postman_id":"9efb6fb4-a1a8-4b6e-8891-51ecb5c85492","id":"9efb6fb4-a1a8-4b6e-8891-51ecb5c85492","name":"Surfact API Platform","type":"collection"}}},{"name":"Subscribe","item":[{"name":"Subscribe to Variable Last Value","id":"92f578a8-d282-456c-a07f-b342d4737a8f","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"SUBSCRIBE","header":[],"url":"","description":"<p>Use this topic to subscribe to a variable's last value. When you connect, you'll immediately receive the most recent value, then get updates whenever the value changes.</p>\n<hr />\n<h2 id=\"topic-structure\">Topic Structure</h2>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code>/v1.6/devices/&lt;device_label&gt;/&lt;variable_label&gt;/lv\n\n</code></pre><h3 id=\"parameters\">Parameters</h3>\n<ul>\n<li><p><code>{DEVICE_LABEL}</code> - Your device's unique label</p>\n</li>\n<li><p><code>{VARIABLE_LABEL}</code> - The variable you want to monitor</p>\n</li>\n<li><p><code>/lv</code> - Last value suffix</p>\n</li>\n</ul>\n<p>⚠️ <strong>Note:</strong> If the device or variable doesn't exist, the subscription will fail.</p>\n<hr />\n<h2 id=\"connection-parameters\">Connection Parameters</h2>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Field</th>\n<th>Value</th>\n<th>Required</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Host</td>\n<td><code>api.surfact.com</code></td>\n<td>Yes</td>\n</tr>\n<tr>\n<td>Port</td>\n<td><code>1883</code> (no TLS) / <code>8883</code> (TLS)</td>\n<td>Yes</td>\n</tr>\n<tr>\n<td>Username</td>\n<td>Your Surfact token</td>\n<td>Yes</td>\n</tr>\n<tr>\n<td>Password</td>\n<td>Any character or leave blank</td>\n<td>No</td>\n</tr>\n<tr>\n<td>Quality of Service</td>\n<td><code>0</code> or <code>1</code></td>\n<td>No</td>\n</tr>\n</tbody>\n</table>\n</div><hr />\n<h2 id=\"examples\">Examples</h2>\n<h3 id=\"command-line-mosquitto_sub\">Command Line (mosquitto_sub)</h3>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-bash\">mosquitto_sub \\\n  -h \"api.surfact.com\" \\\n  -t \"/v1.6/devices/weather-station/temperature/lv\" \\\n  -u \"{{vault:ubidots-api-key}}\" \\\n  -p 8883 \\\n  -q 1\n\n</code></pre>\n<p><strong>Output:</strong></p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code>24.0\n\n</code></pre><h3 id=\"python-paho-mqtt\">Python (paho-mqtt)</h3>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-python\">import paho.mqtt.client as mqtt\ntoken = \"your-surfact-token\"\ndevice_label = \"weather-station\"\nvariable_label = \"temperature\"\ndef on_connect(client, userdata, flags, rc):\n    print(f\"Connected with result code {rc}\")\n    # Subscribe to last value\n    topic = f\"/v2.0/devices/{device_label}/{variable_label}/lv\"\n    client.subscribe(topic)\n    print(f\"Subscribed to {topic}\")\ndef on_message(client, userdata, msg):\n    value = msg.payload.decode()\n    print(f\"Last value: {value}\")\nclient = mqtt.Client(client_id=\"my-device-12345678901234567890\")\nclient.username_pw_set(username=token, password=\"\")\nclient.on_connect = on_connect\nclient.on_message = on_message\nclient.connect(\"api.surfact.com\", 8883)\nclient.loop_forever()\n\n</code></pre>\n<h3 id=\"javascript-mqttjs\">JavaScript (mqtt.js)</h3>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-javascript\">const mqtt = require('mqtt');\nconst token = 'your-surfact-token';\nconst deviceLabel = 'weather-station';\nconst variableLabel = 'temperature';\nconst client = mqtt.connect('mqtts://api.surfact.com:8883', {\n  username: token,\n  password: '',\n  clientId: 'my-device-12345678901234567890'\n});\nclient.on('connect', () =&gt; {\n  console.log('Connected');\n  const topic = `/v2.0/devices/${deviceLabel}/${variableLabel}/lv`;\n  client.subscribe(topic, (err) =&gt; {\n    if (!err) {\n      console.log(`Subscribed to ${topic}`);\n    }\n  });\n});\nclient.on('message', (topic, message) =&gt; {\n  console.log(`Last value: ${message.toString()}`);\n});\n\n</code></pre>\n<hr />\n<h2 id=\"behavior\">Behavior</h2>\n<p>When you subscribe to a <code>/lv</code> topic:</p>\n<ol>\n<li><p><strong>Immediate delivery:</strong> You receive the variable's current last value immediately upon subscription</p>\n</li>\n<li><p><strong>Updates:</strong> You receive new values whenever the variable is updated</p>\n</li>\n<li><p><strong>Retained messages:</strong> The last value is always available (see <a href=\"https://claude.ai/chat/surfact_mqtt.md#retain-flag\">MQTT Overview</a> for details)</p>\n</li>\n</ol>\n<hr />\n<h2 id=\"use-cases\">Use Cases</h2>\n<p>The <code>/lv</code> topic is ideal for:</p>\n<ul>\n<li><p><strong>Device initialization:</strong> Get the current state immediately when connecting</p>\n</li>\n<li><p><strong>Syncing device state:</strong> Ensure your device matches the cloud state on startup</p>\n</li>\n<li><p><strong>Dashboard displays:</strong> Show the most recent value without waiting for an update</p>\n</li>\n<li><p><strong>Control systems:</strong> Initialize actuators to their last known state</p>\n</li>\n</ul>\n<hr />\n<h2 id=\"comparison\">Comparison</h2>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Topic</th>\n<th>Immediate Value</th>\n<th>Updates</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>/v2.0/devices/{device}/{variable}</code></td>\n<td>❌ No</td>\n<td>✅ Yes</td>\n</tr>\n<tr>\n<td><code>/v2.0/devices/{device}/{variable}/lv</code></td>\n<td>✅ Yes</td>\n<td>✅ Yes</td>\n</tr>\n</tbody>\n</table>\n</div><p>Use the regular topic if you only want to receive updates when values change. Use <code>/lv</code> if you need the current value immediately.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"X-Auth-Token"},{"key":"value","value":"<value>"}]},"isInherited":true,"source":{"_postman_id":"9efb6fb4-a1a8-4b6e-8891-51ecb5c85492","id":"9efb6fb4-a1a8-4b6e-8891-51ecb5c85492","name":"Surfact API Platform","type":"collection"}},"urlObject":{"query":[],"variable":[]}},"response":[],"_postman_id":"92f578a8-d282-456c-a07f-b342d4737a8f"},{"name":"Subscribe to Variable's Last Dot","id":"3c44827f-c7ea-422b-8cdd-256be2d1db0d","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"SUBSCRIBE","header":[],"url":"","description":"<p>Use this topic to subscribe to a variable's last \"dot\" (data point). Unlike the <code>/lv</code> endpoint which returns only the value, this returns the complete data point including value, timestamp, and context.</p>\n<hr />\n<h2 id=\"topic-structure\">Topic Structure</h2>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code>/v1.6/devices/{DEVICE_LABEL}/{VARIABLE_LABEL}\n\n</code></pre><h3 id=\"parameters\">Parameters</h3>\n<ul>\n<li><p><code>{DEVICE_LABEL}</code> - Your device's unique label</p>\n</li>\n<li><p><code>{VARIABLE_LABEL}</code> - The variable you want to monitor</p>\n</li>\n</ul>\n<p>⚠️ <strong>Note:</strong> If the device or variable doesn't exist, the subscription will fail.</p>\n<hr />\n<h2 id=\"connection-parameters\">Connection Parameters</h2>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Field</th>\n<th>Value</th>\n<th>Required</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Host</td>\n<td><code>api.surfact.com</code></td>\n<td>Yes</td>\n</tr>\n<tr>\n<td>Port</td>\n<td><code>1883</code> (no TLS) / <code>8883</code> (TLS)</td>\n<td>Yes</td>\n</tr>\n<tr>\n<td>Username</td>\n<td>Your Surfact token</td>\n<td>Yes</td>\n</tr>\n<tr>\n<td>Password</td>\n<td>Any character or leave blank</td>\n<td>No</td>\n</tr>\n<tr>\n<td>Quality of Service</td>\n<td><code>0</code> or <code>1</code></td>\n<td>No</td>\n</tr>\n</tbody>\n</table>\n</div><hr />\n<h2 id=\"response-format\">Response Format</h2>\n<p>The response is a JSON object containing:</p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-json\">{\n  \"value\": 34.0,\n  \"timestamp\": 1634311791000,\n  \"context\": {\n    \"status\": \"cold\"\n  },\n  \"created_at\": 1634311791000\n}\n\n</code></pre>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Field</th>\n<th>Type</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>value</code></td>\n<td>number</td>\n<td>The variable's value</td>\n</tr>\n<tr>\n<td><code>timestamp</code></td>\n<td>number</td>\n<td>Unix timestamp (milliseconds) when the data was recorded</td>\n</tr>\n<tr>\n<td><code>context</code></td>\n<td>object</td>\n<td>Additional metadata (optional)</td>\n</tr>\n<tr>\n<td><code>created_at</code></td>\n<td>number</td>\n<td>Unix timestamp (milliseconds) when the data was created in Surfact</td>\n</tr>\n</tbody>\n</table>\n</div><hr />\n<h2 id=\"examples\">Examples</h2>\n<h3 id=\"command-line-mosquitto_sub\">Command Line (mosquitto_sub)</h3>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-bash\">mosquitto_sub \\\n  -h \"api.surfact.com\" \\\n  -t \"/v1.6/devices/weather-station/temperature\" \\\n  -u \"{{vault:ubidots-api-key}}\" \\\n  -p 8883 \\\n  -q 1\n\n</code></pre>\n<p><strong>Output:</strong></p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-json\">{\n  \"value\": 34.0,\n  \"timestamp\": 1634311791000,\n  \"context\": {\n    \"status\": \"cold\"\n  },\n  \"created_at\": 1634311791000\n}\n\n</code></pre>\n<h3 id=\"python-paho-mqtt\">Python (paho-mqtt)</h3>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-python\">import paho.mqtt.client as mqtt\nimport json\ntoken = \"your-surfact-token\"\ndevice_label = \"weather-station\"\nvariable_label = \"temperature\"\ndef on_connect(client, userdata, flags, rc):\n    print(f\"Connected with result code {rc}\")\n    topic = f\"/v2.0/devices/{device_label}/{variable_label}\"\n    client.subscribe(topic)\n    print(f\"Subscribed to {topic}\")\ndef on_message(client, userdata, msg):\n    data = json.loads(msg.payload.decode())\n    print(f\"Value: {data['value']}\")\n    print(f\"Timestamp: {data['timestamp']}\")\n    if 'context' in data:\n        print(f\"Context: {data['context']}\")\nclient = mqtt.Client(client_id=\"my-device-12345678901234567890\")\nclient.username_pw_set(username=token, password=\"\")\nclient.on_connect = on_connect\nclient.on_message = on_message\nclient.connect(\"api.surfact.com\", 8883)\nclient.loop_forever()\n\n</code></pre>\n<h3 id=\"javascript-mqttjs\">JavaScript (mqtt.js)</h3>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-javascript\">const mqtt = require('mqtt');\nconst token = 'your-surfact-token';\nconst deviceLabel = 'weather-station';\nconst variableLabel = 'temperature';\nconst client = mqtt.connect('mqtts://api.surfact.com:8883', {\n  username: token,\n  password: '',\n  clientId: 'my-device-12345678901234567890'\n});\nclient.on('connect', () =&gt; {\n  console.log('Connected');\n  const topic = `/v2.0/devices/${deviceLabel}/${variableLabel}`;\n  client.subscribe(topic, (err) =&gt; {\n    if (!err) {\n      console.log(`Subscribed to ${topic}`);\n    }\n  });\n});\nclient.on('message', (topic, message) =&gt; {\n  const data = JSON.parse(message.toString());\n  console.log(`Value: ${data.value}`);\n  console.log(`Timestamp: ${data.timestamp}`);\n  if (data.context) {\n    console.log(`Context: ${JSON.stringify(data.context)}`);\n  }\n});\n\n</code></pre>\n<hr />\n<h2 id=\"behavior\">Behavior</h2>\n<p>When you subscribe to this topic:</p>\n<ol>\n<li><p><strong>Immediate delivery:</strong> You receive the variable's last data point immediately upon subscription</p>\n</li>\n<li><p><strong>Updates:</strong> You receive complete data points whenever the variable is updated</p>\n</li>\n<li><p><strong>Full metadata:</strong> Includes timestamp and context (unlike <code>/lv</code> which only returns the value)</p>\n</li>\n</ol>\n<hr />\n<h2 id=\"use-cases\">Use Cases</h2>\n<p>This topic is ideal when you need:</p>\n<ul>\n<li><p><strong>Timestamp information:</strong> Know exactly when the data was recorded</p>\n</li>\n<li><p><strong>Context metadata:</strong> Access additional information sent with the data point</p>\n</li>\n<li><p><strong>Full data point details:</strong> Complete information for logging or analysis</p>\n</li>\n<li><p><strong>Audit trails:</strong> Track when data was created and recorded</p>\n</li>\n</ul>\n<hr />\n<h2 id=\"comparison\">Comparison</h2>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Topic</th>\n<th>Returns</th>\n<th>Immediate</th>\n<th>Updates</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>/v2.0/devices/{device}/{variable}</code></td>\n<td>Full JSON object</td>\n<td>✅ Yes</td>\n<td>✅ Yes</td>\n</tr>\n<tr>\n<td><code>/v2.0/devices/{device}/{variable}/lv</code></td>\n<td>Value only</td>\n<td>✅ Yes</td>\n<td>✅ Yes</td>\n</tr>\n</tbody>\n</table>\n</div><p>Use <code>/lv</code> if you only need the value. Use the standard topic if you need timestamps, context, or complete data point information.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"X-Auth-Token"},{"key":"value","value":"<value>"}]},"isInherited":true,"source":{"_postman_id":"9efb6fb4-a1a8-4b6e-8891-51ecb5c85492","id":"9efb6fb4-a1a8-4b6e-8891-51ecb5c85492","name":"Surfact API Platform","type":"collection"}},"urlObject":{"query":[],"variable":[]}},"response":[],"_postman_id":"3c44827f-c7ea-422b-8cdd-256be2d1db0d"},{"name":"Subscribe single-level wildcard","id":"1a725224-9b2c-4718-90a4-d1ee35f5e298","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"SUBSCRIBE","header":[],"url":"","description":"<h1 id=\"subscribe-with-wildcards\">Subscribe with Wildcards</h1>\n<p>Use MQTT wildcards to subscribe to multiple topics simultaneously. Wildcards let you monitor multiple devices or variables with a single subscription.</p>\n<hr />\n<h2 id=\"single-level-wildcard-\">Single-Level Wildcard (<code>+</code>)</h2>\n<p>The single-level wildcard (<code>+</code>) matches exactly one level in the topic hierarchy.</p>\n<h3 id=\"syntax\">Syntax</h3>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code>/v1.6/devices/+/{VARIABLE_LABEL}\n\n</code></pre><p>This subscribes to the specified variable across <strong>all devices</strong> that have it.</p>\n<hr />\n<h2 id=\"connection-parameters\">Connection Parameters</h2>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Field</th>\n<th>Value</th>\n<th>Required</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Host</td>\n<td><code>api.surfact.com</code></td>\n<td>Yes</td>\n</tr>\n<tr>\n<td>Port</td>\n<td><code>1883</code> (no TLS) / <code>8883</code> (TLS)</td>\n<td>Yes</td>\n</tr>\n<tr>\n<td>Username</td>\n<td>Your Surfact token</td>\n<td>Yes</td>\n</tr>\n<tr>\n<td>Password</td>\n<td>Any character or leave blank</td>\n<td>No</td>\n</tr>\n<tr>\n<td>Quality of Service</td>\n<td><code>0</code> or <code>1</code></td>\n<td>No</td>\n</tr>\n</tbody>\n</table>\n</div><hr />\n<h2 id=\"examples\">Examples</h2>\n<h3 id=\"scenario\">Scenario</h3>\n<p>You have 3 devices with the following variables:</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Device</th>\n<th>Variables</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>device-a</code></td>\n<td>temperature, pressure, humidity</td>\n</tr>\n<tr>\n<td><code>device-b</code></td>\n<td>temperature</td>\n</tr>\n<tr>\n<td><code>device-c</code></td>\n<td>pressure, humidity</td>\n</tr>\n</tbody>\n</table>\n</div><hr />\n<h3 id=\"example-1-subscribe-to-a-specific-variable-across-all-devices\">Example 1: Subscribe to a Specific Variable Across All Devices</h3>\n<p><strong>Topic:</strong></p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code>/v1.6/devices/+/pressure/lv\n/v1.6/devices/+/pressure\n\n</code></pre><p><strong>Equivalent to:</strong></p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code>/v1.6/devices/device-a/pressure/lv\n/v1.6/devices/device-c/pressure/lv\n\n</code></pre><p>This subscribes to the <code>pressure</code> variable for <strong>any device</strong> that has it. You'll receive updates when <code>device-a</code> or <code>device-c</code> send new pressure values.</p>\n<p><strong>Command Line:</strong></p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-bash\"># Last value only\nmosquitto_sub \\\n  -h \"api.surfact.com\" \\\n  -t \"/v1.6/devices/+/pressure/lv\" \\\n  -u \"{{vault:ubidots-api-key}}\" \\\n  -p 8883 \\\n  -q 1 \\\n  -v\n# Full data point (with timestamp and context)\nmosquitto_sub \\\n  -h \"api.surfact.com\" \\\n  -t \"/v1.6/devices/+/pressure\" \\\n  -u \"{{vault:ubidots-api-key}}\" \\\n  -p 8883 \\\n  -q 1 \\\n  -v\n\n</code></pre>\n<p><strong>Python:</strong></p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-python\">import paho.mqtt.client as mqtt\ntoken = \"your-surfact-token\"\ndef on_connect(client, userdata, flags, rc):\n    print(f\"Connected with result code {rc}\")\n    # Subscribe to pressure variable across all devices\n    client.subscribe(\"/v1.6/devices/+/pressure/lv\")\ndef on_message(client, userdata, msg):\n    # Topic will show which device sent the update\n    print(f\"Topic: {msg.topic}\")\n    print(f\"Value: {msg.payload.decode()}\")\nclient = mqtt.Client(client_id=\"my-device-12345678901234567890\")\nclient.username_pw_set(username=token, password=\"\")\nclient.on_connect = on_connect\nclient.on_message = on_message\nclient.connect(\"api.surfact.com\", 8883)\nclient.loop_forever()\n\n</code></pre>\n<p><strong>JavaScript:</strong></p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-javascript\">const mqtt = require('mqtt');\nconst token = 'your-surfact-token';\nconst client = mqtt.connect('mqtts://api.surfact.com:8883', {\n  username: token,\n  password: '',\n  clientId: 'my-device-12345678901234567890'\n});\nclient.on('connect', () =&gt; {\n  console.log('Connected');\n  // Subscribe to pressure variable across all devices\n  client.subscribe('/v1.6/devices/+/pressure/lv');\n});\nclient.on('message', (topic, message) =&gt; {\n  // Topic will show which device sent the update\n  console.log(`Topic: ${topic}`);\n  console.log(`Value: ${message.toString()}`);\n});\n\n</code></pre>\n<hr />\n<h3 id=\"example-2-subscribe-to-all-variables-from-a-specific-device\">Example 2: Subscribe to All Variables from a Specific Device</h3>\n<p><strong>Topic:</strong></p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code>/v1.6/devices/device-a/+/lv\n/v1.6/devices/device-a/+\n\n</code></pre><p><strong>Equivalent to:</strong></p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code>/v1.6/devices/device-a/temperature/lv\n/v1.6/devices/device-a/pressure/lv\n/v1.6/devices/device-a/humidity/lv\n\n</code></pre><p>This subscribes to <strong>all variables</strong> from <code>device-a</code>. You'll receive updates when any of its variables are updated.</p>\n<p><strong>Command Line:</strong></p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-bash\"># Last value only\nmosquitto_sub \\\n  -h \"api.surfact.com\" \\\n  -t \"/v1.6/devices/device-a/+/lv\" \\\n  -u \"{{vault:ubidots-api-key}}\" \\\n  -p 8883 \\\n  -q 1 \\\n  -v\n# Full data point\nmosquitto_sub \\\n  -h \"api.surfact.com\" \\\n  -t \"/v1.6/devices/device-a/+\" \\\n  -u \"{{vault:ubidots-api-key}}\" \\\n  -p 8883 \\\n  -q 1 \\\n  -v\n\n</code></pre>\n<p><strong>Python:</strong></p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-python\">import paho.mqtt.client as mqtt\ntoken = \"your-surfact-token\"\ndevice_label = \"device-a\"\ndef on_connect(client, userdata, flags, rc):\n    print(f\"Connected with result code {rc}\")\n    # Subscribe to all variables from device-a\n    topic = f\"/v1.6/devices/{device_label}/+/lv\"\n    client.subscribe(topic)\ndef on_message(client, userdata, msg):\n    # Extract variable name from topic\n    parts = msg.topic.split('/')\n    variable = parts[3]  # Variable is at index 3\n    print(f\"Variable: {variable}\")\n    print(f\"Value: {msg.payload.decode()}\")\nclient = mqtt.Client(client_id=\"my-device-12345678901234567890\")\nclient.username_pw_set(username=token, password=\"\")\nclient.on_connect = on_connect\nclient.on_message = on_message\nclient.connect(\"api.surfact.com\", 8883)\nclient.loop_forever()\n\n</code></pre>\n<p><strong>JavaScript:</strong></p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-javascript\">const mqtt = require('mqtt');\nconst token = 'your-surfact-token';\nconst deviceLabel = 'device-a';\nconst client = mqtt.connect('mqtts://api.surfact.com:8883', {\n  username: token,\n  password: '',\n  clientId: 'my-device-12345678901234567890'\n});\nclient.on('connect', () =&gt; {\n  console.log('Connected');\n  // Subscribe to all variables from device-a\n  const topic = `/v1.6/devices/${deviceLabel}/+/lv`;\n  client.subscribe(topic);\n});\nclient.on('message', (topic, message) =&gt; {\n  // Extract variable name from topic\n  const parts = topic.split('/');\n  const variable = parts[3];  // Variable is at index 3\n  console.log(`Variable: ${variable}`);\n  console.log(`Value: ${message.toString()}`);\n});\n\n</code></pre>\n<hr />\n<h2 id=\"multi-level-wildcard-\">Multi-Level Wildcard (<code>#</code>)</h2>\n<p>The multi-level wildcard (<code>#</code>) matches any number of levels in the topic hierarchy. It must be the last character in the topic.</p>\n<h3 id=\"examples-1\">Examples</h3>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code># Subscribe to ALL variables from ALL devices\n/v1.6/devices/#\n# Subscribe to everything for a specific device\n/v1.6/devices/device-a/#\n\n</code></pre><p>⚠️ <strong>Warning:</strong> Multi-level wildcards can generate <strong>very high message volumes</strong>. Use with caution in production environments.</p>\n<hr />\n<h2 id=\"use-cases\">Use Cases</h2>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Wildcard Pattern</th>\n<th>Use Case</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>/v1.6/devices/+/temperature</code></td>\n<td>Monitor temperature across all devices</td>\n</tr>\n<tr>\n<td><code>/v1.6/devices/device-a/+</code></td>\n<td>Monitor all variables from one device</td>\n</tr>\n<tr>\n<td><code>/v1.6/devices/+/+</code></td>\n<td>Monitor first variable from all devices (any variable)</td>\n</tr>\n<tr>\n<td><code>/v1.6/devices/#</code></td>\n<td>Monitor everything (use sparingly!)</td>\n</tr>\n</tbody>\n</table>\n</div><hr />\n<h2 id=\"best-practices\">Best Practices</h2>\n<p>✅ <strong>Do:</strong></p>\n<ul>\n<li><p>Use wildcards to reduce the number of subscriptions</p>\n</li>\n<li><p>Parse the topic in your message handler to identify the source</p>\n</li>\n<li><p>Use single-level wildcards when you know the topic structure</p>\n</li>\n</ul>\n<p>⚠️ <strong>Don't:</strong></p>\n<ul>\n<li><p>Use <code>#</code> in production unless absolutely necessary</p>\n</li>\n<li><p>Subscribe to more data than you need</p>\n</li>\n<li><p>Forget to handle the increased message volume</p>\n</li>\n</ul>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"X-Auth-Token"},{"key":"value","value":"<value>"}]},"isInherited":true,"source":{"_postman_id":"9efb6fb4-a1a8-4b6e-8891-51ecb5c85492","id":"9efb6fb4-a1a8-4b6e-8891-51ecb5c85492","name":"Surfact API Platform","type":"collection"}},"urlObject":{"query":[],"variable":[]}},"response":[],"_postman_id":"1a725224-9b2c-4718-90a4-d1ee35f5e298"},{"name":"Subscribe multi-level wildcard","id":"46ffe1d7-1202-4ac7-8080-81c7ba495e65","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"SUBSCRIBE","header":[],"url":"","description":"<p>Use MQTT's multi-level wildcard to subscribe to multiple topics simultaneously. The multi-level wildcard matches any number of topic levels.</p>\n<hr />\n<h2 id=\"multi-level-wildcard-\">Multi-Level Wildcard (<code>#</code>)</h2>\n<p>The multi-level wildcard (<code>#</code>) matches all remaining levels in the topic hierarchy. It <strong>must always be the last character</strong> in the topic.</p>\n<h3 id=\"syntax\">Syntax</h3>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code>/v1.6/devices/{DEVICE_LABEL}/#\n\n</code></pre><p>This subscribes to <strong>all variables</strong> within the specified device.</p>\n<hr />\n<h2 id=\"connection-parameters\">Connection Parameters</h2>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Field</th>\n<th>Value</th>\n<th>Required</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Host</td>\n<td><code>api.surfact.com</code></td>\n<td>Yes</td>\n</tr>\n<tr>\n<td>Port</td>\n<td><code>1883</code> (no TLS) / <code>8883</code> (TLS)</td>\n<td>Yes</td>\n</tr>\n<tr>\n<td>Username</td>\n<td>Your Surfact token</td>\n<td>Yes</td>\n</tr>\n<tr>\n<td>Password</td>\n<td>Any character or leave blank</td>\n<td>No</td>\n</tr>\n<tr>\n<td>Quality of Service</td>\n<td><code>0</code> or <code>1</code></td>\n<td>No</td>\n</tr>\n</tbody>\n</table>\n</div><hr />\n<h2 id=\"examples\">Examples</h2>\n<h3 id=\"scenario\">Scenario</h3>\n<p>You have 3 devices with the following variables:</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Device</th>\n<th>Variables</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>device-a</code></td>\n<td>temperature, pressure, humidity</td>\n</tr>\n<tr>\n<td><code>device-b</code></td>\n<td>temperature</td>\n</tr>\n<tr>\n<td><code>device-c</code></td>\n<td>pressure, humidity</td>\n</tr>\n</tbody>\n</table>\n</div><hr />\n<h3 id=\"example-1-subscribe-to-all-variables-from-a-specific-device\">Example 1: Subscribe to All Variables from a Specific Device</h3>\n<p><strong>Topic:</strong></p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code>/v1.6/devices/device-a/#\n\n</code></pre><p><strong>Equivalent to:</strong></p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code>/v1.6/devices/device-a/temperature\n/v1.6/devices/device-a/pressure\n/v1.6/devices/device-a/humidity\n\n</code></pre><p>This subscribes to <strong>all variables</strong> from <code>device-a</code>. You'll receive full data points (with timestamp and context) whenever any variable is updated.</p>\n<p><strong>Command Line:</strong></p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-bash\">mosquitto_sub \\\n  -h \"api.surfact.com\" \\\n  -t \"/v1.6/devices/device-a/#\" \\\n  -u \"{{vault:ubidots-api-key}}\" \\\n  -p 8883 \\\n  -q 1 \\\n  -v\n\n</code></pre>\n<p><strong>Python:</strong></p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-python\">import paho.mqtt.client as mqtt\nimport json\ntoken = \"your-surfact-token\"\ndevice_label = \"device-a\"\ndef on_connect(client, userdata, flags, rc):\n    print(f\"Connected with result code {rc}\")\n    # Subscribe to all variables from device-a\n    topic = f\"/v1.6/devices/{device_label}/#\"\n    client.subscribe(topic)\n    print(f\"Subscribed to {topic}\")\ndef on_message(client, userdata, msg):\n    # Extract variable name from topic\n    parts = msg.topic.split('/')\n    variable = parts[3] if len(parts) &gt; 3 else \"unknown\"\n    # Parse the message (could be JSON or plain value)\n    try:\n        data = json.loads(msg.payload.decode())\n        print(f\"Variable: {variable}\")\n        print(f\"Value: {data.get('value', 'N/A')}\")\n        print(f\"Timestamp: {data.get('timestamp', 'N/A')}\")\n    except json.JSONDecodeError:\n        print(f\"Variable: {variable}\")\n        print(f\"Value: {msg.payload.decode()}\")\nclient = mqtt.Client(client_id=\"my-device-12345678901234567890\")\nclient.username_pw_set(username=token, password=\"\")\nclient.on_connect = on_connect\nclient.on_message = on_message\nclient.connect(\"api.surfact.com\", 8883)\nclient.loop_forever()\n\n</code></pre>\n<p><strong>JavaScript:</strong></p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-javascript\">const mqtt = require('mqtt');\nconst token = 'your-surfact-token';\nconst deviceLabel = 'device-a';\nconst client = mqtt.connect('mqtts://api.surfact.com:8883', {\n  username: token,\n  password: '',\n  clientId: 'my-device-12345678901234567890'\n});\nclient.on('connect', () =&gt; {\n  console.log('Connected');\n  // Subscribe to all variables from device-a\n  const topic = `/v1.6/devices/${deviceLabel}/#`;\n  client.subscribe(topic, (err) =&gt; {\n    if (!err) {\n      console.log(`Subscribed to ${topic}`);\n    }\n  });\n});\nclient.on('message', (topic, message) =&gt; {\n  // Extract variable name from topic\n  const parts = topic.split('/');\n  const variable = parts[3] || 'unknown';\n  // Parse the message (could be JSON or plain value)\n  try {\n    const data = JSON.parse(message.toString());\n    console.log(`Variable: ${variable}`);\n    console.log(`Value: ${data.value}`);\n    console.log(`Timestamp: ${data.timestamp}`);\n  } catch (e) {\n    console.log(`Variable: ${variable}`);\n    console.log(`Value: ${message.toString()}`);\n  }\n});\n\n</code></pre>\n<hr />\n<h3 id=\"example-2-subscribe-to-all-variables-from-all-devices\">Example 2: Subscribe to All Variables from All Devices</h3>\n<p><strong>Topic:</strong></p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code>/v1.6/devices/#\n\n</code></pre><p><strong>Equivalent to:</strong></p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code>/v1.6/devices/device-a/temperature\n/v1.6/devices/device-a/pressure\n/v1.6/devices/device-a/humidity\n/v1.6/devices/device-b/temperature\n/v1.6/devices/device-c/pressure\n/v1.6/devices/device-c/humidity\n\n</code></pre><p>This subscribes to <strong>all variables from all devices</strong>. You'll receive updates whenever any variable on any device is updated.</p>\n<p>⚠️ <strong>Warning:</strong> This can generate <strong>extremely high message volumes</strong> in production. Use only for testing or small-scale deployments.</p>\n<p><strong>Command Line:</strong></p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-bash\">mosquitto_sub \\\n  -h \"api.surfact.com\" \\\n  -t \"/v1.6/devices/#\" \\\n  -u \"{{vault:ubidots-api-key}}\" \\\n  -p 8883 \\\n  -q 1 \\\n  -v\n\n</code></pre>\n<p><strong>Python:</strong></p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-python\">import paho.mqtt.client as mqtt\nimport json\ntoken = \"your-surfact-token\"\ndef on_connect(client, userdata, flags, rc):\n    print(f\"Connected with result code {rc}\")\n    # Subscribe to EVERYTHING\n    client.subscribe(\"/v1.6/devices/#\")\n    print(\"⚠️  Subscribed to ALL devices and variables\")\ndef on_message(client, userdata, msg):\n    # Extract device and variable names from topic\n    parts = msg.topic.split('/')\n    device = parts[2] if len(parts) &gt; 2 else \"unknown\"\n    variable = parts[3] if len(parts) &gt; 3 else \"unknown\"\n    # Parse the message\n    try:\n        data = json.loads(msg.payload.decode())\n        print(f\"Device: {device} | Variable: {variable}\")\n        print(f\"Value: {data.get('value', 'N/A')}\")\n    except json.JSONDecodeError:\n        print(f\"Device: {device} | Variable: {variable}\")\n        print(f\"Value: {msg.payload.decode()}\")\nclient = mqtt.Client(client_id=\"my-device-12345678901234567890\")\nclient.username_pw_set(username=token, password=\"\")\nclient.on_connect = on_connect\nclient.on_message = on_message\nclient.connect(\"api.surfact.com\", 8883)\nclient.loop_forever()\n\n</code></pre>\n<p><strong>JavaScript:</strong></p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-javascript\">const mqtt = require('mqtt');\nconst token = 'your-surfact-token';\nconst client = mqtt.connect('mqtts://api.surfact.com:8883', {\n  username: token,\n  password: '',\n  clientId: 'my-device-12345678901234567890'\n});\nclient.on('connect', () =&gt; {\n  console.log('Connected');\n  // Subscribe to EVERYTHING\n  client.subscribe('/v1.6/devices/#', (err) =&gt; {\n    if (!err) {\n      console.log('⚠️  Subscribed to ALL devices and variables');\n    }\n  });\n});\nclient.on('message', (topic, message) =&gt; {\n  // Extract device and variable names from topic\n  const parts = topic.split('/');\n  const device = parts[2] || 'unknown';\n  const variable = parts[3] || 'unknown';\n  // Parse the message\n  try {\n    const data = JSON.parse(message.toString());\n    console.log(`Device: ${device} | Variable: ${variable}`);\n    console.log(`Value: ${data.value}`);\n  } catch (e) {\n    console.log(`Device: ${device} | Variable: ${variable}`);\n    console.log(`Value: ${message.toString()}`);\n  }\n});\n\n</code></pre>\n<hr />\n<h2 id=\"important-notes\">Important Notes</h2>\n<h3 id=\"topic-information\">Topic Information</h3>\n<p>The topic itself contains valuable information about which device and variable sent the update:</p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code>/v1.6/devices/device-a/temperature\n          │         │          │\n          │         │          └─ Variable name\n          │         └─ Device name\n          └─ API version\n\n</code></pre><p><strong>Always parse the topic</strong> in your message handler to identify the source of the data.</p>\n<h3 id=\"message-format\">Message Format</h3>\n<p>Messages received via multi-level wildcard subscriptions can be:</p>\n<ul>\n<li><p><strong>Full JSON objects</strong> (when subscribing to base variable topics)</p>\n</li>\n<li><p><strong>Plain values</strong> (when subscribing to <code>/lv</code> topics)</p>\n</li>\n</ul>\n<p>Your code should handle both formats.</p>\n<hr />\n<h2 id=\"use-cases\">Use Cases</h2>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Wildcard Pattern</th>\n<th>Use Case</th>\n<th>Risk Level</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>/v1.6/devices/device-a/#</code></td>\n<td>Monitor all variables from one device</td>\n<td>✅ Low</td>\n</tr>\n<tr>\n<td><code>/v1.6/devices/device-group-\\\\*/#</code></td>\n<td>Monitor device groups (if using naming convention)</td>\n<td>⚠️ Medium</td>\n</tr>\n<tr>\n<td><code>/v1.6/devices/#</code></td>\n<td>Monitor everything (testing only)</td>\n<td>🚨 High</td>\n</tr>\n</tbody>\n</table>\n</div><hr />\n<h2 id=\"best-practices\">Best Practices</h2>\n<p>✅ <strong>Do:</strong></p>\n<ul>\n<li><p>Use <code>/v1.6/devices/{device}/#</code> for monitoring specific devices</p>\n</li>\n<li><p>Parse the topic to identify the source device and variable</p>\n</li>\n<li><p>Test with small datasets before deploying to production</p>\n</li>\n<li><p>Consider message volume and bandwidth</p>\n</li>\n</ul>\n<p>⚠️ <strong>Don't:</strong></p>\n<ul>\n<li><p>Use <code>/v1.6/devices/#</code> in production with many devices</p>\n</li>\n<li><p>Forget to handle different message formats (JSON vs. plain values)</p>\n</li>\n<li><p>Subscribe to more data than you can process</p>\n</li>\n<li><p>Ignore the topic information—it's essential for routing</p>\n</li>\n</ul>\n<hr />\n<h2 id=\"comparison-single-level-vs-multi-level\">Comparison: Single-Level vs. Multi-Level</h2>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Feature</th>\n<th>Single-Level (<code>+</code>)</th>\n<th>Multi-Level (<code>#</code>)</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><strong>Matches</strong></td>\n<td>Exactly one level</td>\n<td>All remaining levels</td>\n</tr>\n<tr>\n<td><strong>Position</strong></td>\n<td>Any level</td>\n<td>Must be last</td>\n</tr>\n<tr>\n<td><strong>Example</strong></td>\n<td><code>/v1.6/devices/+/temperature</code></td>\n<td><code>/v1.6/devices/device-a/#</code></td>\n</tr>\n<tr>\n<td><strong>Use case</strong></td>\n<td>Specific variable across devices</td>\n<td>All variables from device(s)</td>\n</tr>\n<tr>\n<td><strong>Message volume</strong></td>\n<td>Medium</td>\n<td>High to Very High</td>\n</tr>\n</tbody>\n</table>\n</div><p>Choose single-level wildcards when you know the exact topic structure. Use multi-level wildcards when you need flexibility but be aware of the increased message volume.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"X-Auth-Token"},{"key":"value","value":"<value>"}]},"isInherited":true,"source":{"_postman_id":"9efb6fb4-a1a8-4b6e-8891-51ecb5c85492","id":"9efb6fb4-a1a8-4b6e-8891-51ecb5c85492","name":"Surfact API Platform","type":"collection"}},"urlObject":{"query":[],"variable":[]}},"response":[],"_postman_id":"46ffe1d7-1202-4ac7-8080-81c7ba495e65"}],"id":"42c0bc09-f0ad-44dc-b546-8360197b31f3","description":"<h1 id=\"subscribe\">Subscribe</h1>\n<p>Similar to HTTP GET requests, subscribing lets you receive values from Surfact. The key difference: <strong>you don't have to continuously poll the server</strong>.</p>\n<p>When a variable's value changes, Surfact automatically notifies you. This saves:</p>\n<ul>\n<li><p>Data requests</p>\n</li>\n<li><p>Processing time on your device</p>\n</li>\n<li><p>Battery life</p>\n</li>\n<li><p>Costs</p>\n</li>\n</ul>\n<p>This makes MQTT ideal for controlling actuators and real-time device interactions.</p>\n<hr />\n<h2 id=\"topic-structure\">Topic Structure</h2>\n<p>Subscribe to variables using this topic pattern:</p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code>/v2.0/devices/{DEVICE_LABEL}/{VARIABLE_LABEL}\n/v1.6/devices/{DEVICE_LABEL}/{VARIABLE_LABEL}\n\n</code></pre><h3 id=\"parameters\">Parameters</h3>\n<ul>\n<li><p><code>{DEVICE_LABEL}</code> - Your device's unique label</p>\n</li>\n<li><p><code>{VARIABLE_LABEL}</code> - The variable you want to monitor</p>\n</li>\n</ul>\n<hr />\n<h2 id=\"examples\">Examples</h2>\n<h3 id=\"python-paho-mqtt\">Python (paho-mqtt)</h3>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-python\">import paho.mqtt.client as mqtt\ntoken = \"your-surfact-token\"\ndevice_label = \"smart-door\"\nvariable_label = \"lock-status\"\ndef on_connect(client, userdata, flags, rc):\n    print(f\"Connected with result code {rc}\")\n    # Subscribe to the variable\n    topic = f\"/v2.0/devices/{device_label}/{variable_label}\"\n    client.subscribe(topic)\ndef on_message(client, userdata, msg):\n    print(f\"Received: {msg.payload.decode()} on topic {msg.topic}\")\nclient = mqtt.Client(client_id=\"my-device-12345678901234567890\")\nclient.username_pw_set(username=token, password=\"\")\nclient.on_connect = on_connect\nclient.on_message = on_message\nclient.connect(\"api.surfact.com\", 8883)\nclient.loop_forever()\n\n</code></pre>\n<h3 id=\"javascript-mqttjs\">JavaScript (mqtt.js)</h3>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-javascript\">const mqtt = require('mqtt');\nconst token = 'your-surfact-token';\nconst deviceLabel = 'smart-door';\nconst variableLabel = 'lock-status';\nconst client = mqtt.connect('mqtts://api.surfact.com:8883', {\n  username: token,\n  password: '',\n  clientId: 'my-device-12345678901234567890'\n});\nclient.on('connect', () =&gt; {\n  console.log('Connected');\n  const topic = `/v2.0/devices/${deviceLabel}/${variableLabel}`;\n  client.subscribe(topic, (err) =&gt; {\n    if (!err) {\n      console.log(`Subscribed to ${topic}`);\n    }\n  });\n});\nclient.on('message', (topic, message) =&gt; {\n  console.log(`Received: ${message.toString()} on topic ${topic}`);\n});\n\n</code></pre>\n<hr />\n<h2 id=\"multiple-variables\">Multiple Variables</h2>\n<p>Subscribe to multiple variables by calling subscribe for each topic:</p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-python\">topics = [\n    f\"/v2.0/devices/{device_label}/temperature\",\n    f\"/v2.0/devices/{device_label}/humidity\",\n    f\"/v2.0/devices/{device_label}/pressure\"\n]\nfor topic in topics:\n    client.subscribe(topic)\n\n</code></pre>\n<hr />\n<h2 id=\"wildcards\">Wildcards</h2>\n<p>MQTT supports wildcards for subscribing to multiple variables:</p>\n<ul>\n<li><p><code>+</code> - Single-level wildcard (matches one level)</p>\n</li>\n<li><p><code>#</code> - Multi-level wildcard (matches all remaining levels)</p>\n</li>\n</ul>\n<p><strong>Examples:</strong></p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-python\"># Subscribe to ALL variables for a specific device\nclient.subscribe(f\"/v2.0/devices/{device_label}/+\")\n# Subscribe to a specific variable across ALL devices\nclient.subscribe(f\"/v2.0/devices/+/{variable_label}\")\n# Subscribe to everything under /v2.0/devices/\nclient.subscribe(\"/v2.0/devices/#\")\n\n</code></pre>\n<p>⚠️ <strong>Warning:</strong> Using wildcards (especially <code>#</code>) can result in high message volumes. Use specific topics when possible.</p>\n","_postman_id":"42c0bc09-f0ad-44dc-b546-8360197b31f3","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"X-Auth-Token"},{"key":"value","value":"<value>"}]},"isInherited":true,"source":{"_postman_id":"9efb6fb4-a1a8-4b6e-8891-51ecb5c85492","id":"9efb6fb4-a1a8-4b6e-8891-51ecb5c85492","name":"Surfact API Platform","type":"collection"}}}],"id":"2d68f692-0eaa-479b-a113-0c0e343c1f8f","description":"<h1 id=\"mqtt\">MQTT</h1>\n<p><a href=\"http://mqtt.org/\">MQTT</a> is an Internet of Things connectivity protocol designed as an extremely lightweight publish/subscribe messaging transport. It's ideal for connections with remote locations where a small code footprint is required and/or network bandwidth is at a premium.</p>\n<h2 id=\"why-use-mqtt\">Why Use MQTT?</h2>\n<p>MQTT is especially useful for pushing data from the cloud to your devices.</p>\n<p><strong>Example scenario:</strong> A cloud-controlled door lock.</p>\n<ul>\n<li><p><strong>With HTTP:</strong> The device must continuously make GET requests to check if the \"Door Control Variable\" has changed. This consumes bandwidth, drains battery, and isn't truly real-time.</p>\n</li>\n<li><p><strong>With MQTT:</strong> The device \"listens\" to the cloud and only gets notified when the variable changes. The connection stays open, but data only travels when necessary—saving battery, bandwidth, and enabling real-time control.</p>\n</li>\n</ul>\n<hr />\n<h2 id=\"quality-of-service-qos\">Quality of Service (QoS)</h2>\n<p>QoS guarantees message delivery reliability. There are three levels:</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Level</th>\n<th>Name</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><strong>0</strong></td>\n<td>At most once</td>\n<td>Best-effort delivery. No guarantee the message arrives.</td>\n</tr>\n<tr>\n<td><strong>1</strong></td>\n<td>At least once</td>\n<td>Guarantees delivery at least once. Receiver sends a <code>puback</code> packet. If not received, sender retries.</td>\n</tr>\n<tr>\n<td><strong>2</strong></td>\n<td>Exactly once</td>\n<td>Guarantees the message is received only once. Slowest option (requires two request/response flows).</td>\n</tr>\n</tbody>\n</table>\n</div><p><strong>Surfact Support:</strong> QoS up to <strong>1</strong> (at least once).</p>\n<hr />\n<h2 id=\"last-will-testament-lwt\">Last Will Testament (LWT)</h2>\n<p>LWT messages are sent by the broker when a client connection is interrupted (client goes offline).</p>\n<p><strong>Surfact Support:</strong> LWT is <strong>not supported</strong>.</p>\n<hr />\n<h2 id=\"persistent-sessions\">Persistent Sessions</h2>\n<p>Persistent sessions allow the broker to save client information if the connection is lost, enabling immediate reconnection.</p>\n<p><strong>Surfact Support:</strong> Persistent sessions are <strong>not supported</strong>. Setting the <code>cleanSession</code> flag to <code>false</code> has no effect. After disconnection, the client must re-establish connection settings.</p>\n<hr />\n<h2 id=\"client-id\">Client ID</h2>\n<p>The Client ID is a unique identifier for each MQTT client connecting to the broker. It allows the broker to track the client's state.</p>\n<h3 id=\"requirements\">Requirements</h3>\n<p>To avoid collisions with other Surfact users, your Client ID must be:</p>\n<ul>\n<li><p><strong>Alphanumeric</strong></p>\n</li>\n<li><p><strong>At least 20 characters long</strong></p>\n</li>\n<li><p><strong>Random</strong></p>\n</li>\n</ul>\n<hr />\n<h2 id=\"retain-flag\">Retain Flag</h2>\n<p>A retained message is a standard MQTT message with the <code>retained</code> flag set to <code>true</code>. The broker stores the last retained message and its QoS for that topic. New subscribers immediately receive the retained message upon subscription.</p>\n<h3 id=\"surfact-behavior\">Surfact Behavior</h3>\n<p><strong>By design, every message published to the Surfact broker is marked as retained</strong>, regardless of whether the flag is set. This ensures the last value published to a variable is always available via MQTT subscription.</p>\n<p>Similarly, when data is posted via HTTP, TCP, or UDP, Surfact publishes the last value to the broker to maintain consistency across protocols.</p>\n","_postman_id":"2d68f692-0eaa-479b-a113-0c0e343c1f8f","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"X-Auth-Token"},{"key":"value","value":"<value>"}]},"isInherited":true,"source":{"_postman_id":"9efb6fb4-a1a8-4b6e-8891-51ecb5c85492","id":"9efb6fb4-a1a8-4b6e-8891-51ecb5c85492","name":"Surfact API Platform","type":"collection"}}}],"auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"X-Auth-Token"},{"key":"value","value":"<value>"}]}},"event":[{"listen":"prerequest","script":{"id":"23d4bae7-b585-45a2-b7e0-b6d46d18fe1e","type":"text/javascript","packages":{},"requests":{},"exec":[""]}},{"listen":"test","script":{"id":"1e255ae9-d83a-47c1-93b6-93e95b6dcbbc","type":"text/javascript","packages":{},"requests":{},"exec":[""]}}],"variable":[{"id":"d9fb5f73-e350-4ad1-8197-9a0091370c0e","key":"baseUrl","value":"https://api.surfact.com/api/v1.6"},{"id":"09244e1c-bed3-4bd0-aa14-e588fb731c09","key":"X-Auth-Token","value":""},{"id":"ca945c73-15fc-4f33-883d-63817debe028","key":"ca945c73-15fc-4f33-883d-63817debe028","value":""}]}