Getting Data: add Node.js SDK query examples#91
Conversation
|
@vitorfdl Not 100% if the best option was to add it to the existing getting data page, but I decided to do that instead of grouping it with the TagoIO SDK documentation or making a separate page just for it. |
vitorfdl
left a comment
There was a problem hiding this comment.
PR Review — getting-data.md
Overall, the direction is good. The main issue is that the page is trying to be both:
- REST API reference
- Node.js SDK guide
- Query behavior reference
- Troubleshooting checklist
That can work, but the current ordering makes the REST API section feel incomplete compared to the SDK section. Since this is documentation, not a tutorial, I’d recommend restructuring it as a reference page with clear parallel sections for REST and SDK usage.
General alignment with TagoIO communication guidelines
The tone is mostly aligned with TagoIO’s documentation style: direct, useful, and practical.
Good examples:
“The SDK uses plural field names (
variables,groups,ids,values). The REST API uses singular forms.”
This is very helpful. It addresses a real source of confusion without overexplaining.
“The API returns 15 records by default, ordered newest-first. Use
qtyandskipto control the page size and offset.”
This is clear and actionable.
The page also does a good job of respecting the user’s time. It explains common pitfalls directly instead of making readers infer behavior from examples.
Where it could better match TagoIO’s voice
Some sections could be made more approachable by adding short context before technical tables.
For example, the Query types section jumps directly into query categories. A short intro would help:
Use query types when you do not need raw records. They let you retrieve a specific record, calculate a summary, or group data into time buckets.This keeps the documentation clear without turning it into a tutorial.
Formatting and ordering of information
The page is well-formatted, but the information hierarchy needs adjustment.
Right now, the page is ordered like this:
- REST API
- Node.js SDK
- Filtering
- Pagination and ordering
- Query types
- Profile-level queries
- Common pitfalls
- Rate limits
The problem is that most examples after the REST section are SDK-only. That makes the page title, “Getting Data,” feel broader than the actual content.
A user looking for REST examples for filters, date ranges, pagination, or query types would need to translate the SDK examples back into query parameters.
Suggested structure
I’d recommend this structure:
# Getting Data
## Overview
Explain that device data can be read through:
- REST API
- Node.js SDK using a Device token
- Node.js SDK using a Profile/Analysis token
## Before you start
- Regional endpoint
- Token type
- Default result limit
- Response order
## REST API
### Endpoint
### Headers
### Query parameters
### Examples
- Get latest data
- Filter by variable
- Filter by date range
- Pagination
- Query type
- Aggregate query
## Node.js SDK
### Install the SDK
### Read data with a Device token
### Read data with a Profile token
### Read data inside an Analysis
## Filters
Explain concepts once, then show REST + SDK examples where useful:
- Variable
- Value
- Group
- Data ID
- Date range
## Query types
- First and last
- Summary
- Aggregate
- Conditional
## Common pitfalls
## Rate limits
## Related documentationThis keeps the page reference-oriented while making it easier to compare REST and SDK usage.
Ease of understanding
The documentation is generally easy to understand for developers. The examples are practical and the wording is clear.
What works well
- The difference between REST singular fields and SDK plural fields is called out early.
- Device token vs Profile/Analysis token is explained clearly.
- Filtering examples are simple and realistic.
- The date range section includes accepted formats.
- The pagination section explains
qtyandskipwell. - The “Common pitfalls” section is useful and should stay.
What could be improved
1. Add a short overview at the top
The page starts with the regional endpoint note, then jumps straight into REST API. A brief overview would help users choose the right access method.
Suggested addition after the frontmatter:
Use this page when you need to read data stored in a TagoIO device.
You can retrieve device data in three common ways:
- **REST API with a Device token** — useful for direct device-scoped requests.
- **Node.js SDK with the `Device` class** — useful in scripts that work with one device.
- **Node.js SDK with the `Resources` class** — useful when an Analysis or server-side application needs to read data from multiple devices.This gives users a mental model before they see code.
2. Clarify token naming
The page uses:
Profile/Analysis token (
Resourcesclass)
Then later:
With a profile token
The official docs still commonly use Account Token in several places. The draft links to /profiles/account-token.md, so the wording should probably be consistent.
Suggested:
- **Account/Profile token** (`Resources` class): read data from any device your token can access. Use this in server-side applications that manage multiple devices.
- **Analysis token** (`Resources` class): read data from an Analysis using its runtime permissions.Or, if the product team has standardized on “Profile token,” use that everywhere and make sure the linked page title matches.
3. Clarify Resources usage inside Analysis
This part may confuse readers:
const { Resources } = require("@tago-io/sdk");
const data = await Resources.devices.getDeviceData("DEVICE_ID", {
...
});Earlier, Resources is shown as a class instantiated with a token:
const resources = new Resources({ token: "YOUR_PROFILE_TOKEN" });If both patterns are valid, add one sentence explaining the difference:
Inside an Analysis, `Resources` can be used directly because the SDK reads the Analysis runtime token automatically.If the static usage is not valid in the current SDK version, this needs correction before merging.
4. Explain what a “data record” is
The page uses “record” throughout. It would help to define it once.
Suggested:
A data record is one stored data point, such as one temperature reading with its `variable`, `value`, and `time`.This is especially useful for users coming from dashboards rather than APIs.
Unnecessary or excessive technical information
The page is not overly technical overall. Most details are useful. The main issue is where some details appear.
1. The REST query parameter table may be too generic
The table is useful, but some descriptions are too short to be helpful.
Current:
| `query` | string | Predefined query type |Suggested:
| `query` | string | Applies a predefined query, such as `last_value`, `avg`, `aggregate`, or `conditional` |Current:
| `details` | bool | Include internal metadata on each record |This may be inaccurate or unclear. The official API docs describe details as including additional fields such as created_at. I’d avoid “internal metadata” because users may confuse it with the data point metadata field.
Suggested:
| `details` | boolean | Include additional fields in each record, such as `created_at` |Also confirm whether the REST API uses details or detail. The draft uses details, and the current API reference uses details, but the older docs mention detail. If details is the correct current parameter, this page can help standardize it.
2. Date formats may need a caveat
The accepted date formats are useful, but “Human-readable” can be ambiguous.
Current:
| Human-readable | `2026-05-19 00:00:00` |Suggested:
| Date and time string | `2026-05-19 00:00:00` |Also, relative dates should explain what they are relative to:
Relative dates are calculated from the time of the request.3. Aggregation section is useful but needs one more constraint
This section explains the required fields clearly:
- `function`: `avg`, `sum`, `min`, or `max`
- `interval`: `minute`, `hour`, `day`, `month`, `quarter`, or `year`I’d add that start_date and end_date should be used for aggregate queries, even if only one is technically required.
Suggested:
For predictable results, always include `start_date` and `end_date` with aggregate queries.This is practical guidance without overcomplicating the reference.
4. Common pitfalls section is valuable, but could include REST/SDK naming mismatch
Add this item:
- **REST and SDK parameter names are different.** The REST API uses query parameters such as `variable`, `value`, and `group`. The Node.js SDK uses `variables`, `values`, and `groups`.This is probably one of the most important pitfalls on the page.
REST API section needs more examples
The REST API section currently includes:
- Headers
- Endpoint
- Query parameter table
- Response example
But it does not show any actual request examples with query parameters.
Since the page title is “Getting Data,” and the REST API section appears first, we should include at least a few common examples.
Suggested additions:
### Get the latest records
```http
GET https://api.<region>.tago.io/data?qty=15
Authorization: Your-Device-TokenFilter by variable
GET https://api.<region>.tago.io/data?variable=temperature
Authorization: Your-Device-TokenFilter by multiple variables
GET https://api.<region>.tago.io/data?variable[]=temperature&variable[]=humidity
Authorization: Your-Device-TokenFilter by date range
GET https://api.<region>.tago.io/data?variable=temperature&start_date=2026-05-19T00:00:00.000Z&end_date=2026-05-20T23:59:59.000Z&qty=100
Authorization: Your-Device-TokenGet the last value
GET https://api.<region>.tago.io/data?variable=temperature&query=last_value
Authorization: Your-Device-Token
This would make the REST section feel complete instead of acting only as an intro to the SDK.
---
## SDK section comments
The SDK section is strong, but it could be tightened.
### Current
```md
The SDK uses plural field names (`variables`, `groups`, `ids`, `values`). The REST API uses singular forms.
Keep this. It is one of the best lines in the doc.
Access patterns
Current:
Two access patterns are available:Suggested:
The SDK can read device data in two common ways:Reason: “Access patterns” is accurate, but a little abstract.
Device token description
Current:
Use this in analyses or scripts scoped to a single device.
This may need verification. Device tokens are useful in scripts scoped to one device, but inside Analysis, users often use Environment Variables or Analysis context. I’d make it slightly safer:
Use this when your script only needs to read data from one device.Profile-level queries
The heading “Profile-level queries” may be too product-internal.
Suggested:
### Reading data from another deviceor:
### Reading data with `Resources`Since this is SDK documentation, I prefer:
### Reading data with `Resources`Then explain that Resources is the right choice when the code needs to access devices by ID.
Query types section
This section is useful, but the hierarchy could be clearer.
Current:
### Query types
#### First and last
#### Summary
#### Aggregate
#### ConditionalThis is good. I’d keep the structure, but add a short explanation before each category.
First and last
Good section. The note is useful:
These queries return at most one record. Do not combine them with `qty > 1`.Suggested small change:
These queries return at most one record, so `qty` is ignored or should not be used.Only use this if confirmed. Otherwise keep the current wording.
Summary
The summary table is good.
Potential issue:
Use `avg` or `sum` to compute the average or total over a date window.If min, max, and count can also be scoped by date window, this sentence could accidentally imply they cannot.
Suggested:
You can combine summary queries with filters such as `variables`, `groups`, `start_date`, and `end_date`. For `avg` and `sum`, include a date window.Conditional
This is clear. I’d only add that value is the threshold.
Suggested:
For conditional queries, `value` is the threshold used by the comparison function.Documentation vs tutorial
This page mostly works as documentation, but a few sections feel tutorial-like because they include step-by-step implementation decisions.
Examples:
// Page 1
const page1 = ...
// Page 2
const page2 = ...This is acceptable because pagination benefits from examples. But overall, the page should stay reference-first.
To keep it documentation-oriented:
- Use concise explanations.
- Keep examples small.
- Avoid long walkthroughs.
- Group examples by concept.
- Add links to deeper docs instead of explaining every related concept inline.
Links to related documentation
These are the links I’d include or adjust.
Already linked and should stay
-
Device Token
Use in REST Headers and SDK access pattern sections.
https://docs.tago.io/docs/tagoio/devices/device-token -
Grouping Variables
Use in “By group.”
https://docs.tago.io/docs/tagoio/devices/grouping-variables -
Account Token / Profile Token
Use in theResourcessection.
https://docs.tago.io/docs/tagoio/profiles/account-token -
Analysis
Use in the tokenlessResourcessection.
https://docs.tago.io/docs/tagoio/analysis/ -
Access Management
Use when explaining required permissions for Analysis runtime access.
https://docs.tago.io/docs/tagoio/tagorun/access-management/ -
Defining permissions
Use in the permission setup note.
https://docs.tago.io/docs/tagoio/tagorun/access-management/defining-permissions -
Creating a policy
Use in the permission setup note.
https://docs.tago.io/docs/tagoio/tagorun/access-management/creating-a-policy -
Rate Limits
Use in the Rate limits section.
https://docs.tago.io/docs/tagoio/profiles/services/rate-limits-hard-limits
Links I’d add
-
RESTful API overview
Use near the regional endpoint note or REST API heading.
https://docs.tago.io/docs/tagoio/getting-started/restful-api -
API Overview
Use for response format, tokens, and regional endpoints.
https://docs.tago.io/docs/tagoio/api/api_overview -
Get Data API reference
Use near the REST endpoint or query parameters table.
https://docs.tago.io/docs/api/get-data -
Devices overview
Use if adding a short explanation of what device data is.
https://docs.tago.io/docs/tagoio/devices/ -
Sending Data
Useful as a related doc because users reading data often need to understand the data record structure created when sending data.
https://docs.tago.io/docs/tagoio/devices/sending-data -
Usage Policy
Use if the Rate Limits section mentions broader account usage limits.
https://docs.tago.io/docs/tagoio/profiles/services/usage-policy
Suggested “Related documentation” section
## Related documentation
- [Device Token](/docs/tagoio/devices/device-token/) — authorize device-scoped data requests.
- [Account Token](/docs/tagoio/profiles/account-token/) — authorize account/profile-level requests.
- [RESTful API overview](/docs/tagoio/getting-started/restful-api/) — understand TagoIO API tokens and request structure.
- [Get Data API reference](/docs/api/get-data/) — view the full API reference for the `/data` endpoint.
- [Sending Data](/docs/tagoio/devices/sending-data/) — understand the structure of data records stored in a device.
- [Grouping Variables](/docs/tagoio/devices/grouping-variables/) — use groups to retrieve related records together.
- [Analysis](/docs/tagoio/analysis/) — run scripts inside TagoIO.
- [Access Management](/docs/tagoio/tagorun/access-management/) — control which resources an Analysis or Run user can access.
- [Rate Limits](/docs/tagoio/profiles/services/rate-limits-hard-limits/) — understand request limits for API usage.Specific inline-style comments
Frontmatter description
Current:
description: "How to read device data through the REST API and the Node.js SDK, including filters, date ranges, pagination, query types, and aggregations."This is good. I’d keep it.
Optional shorter version:
description: "Read device data with the REST API and Node.js SDK using filters, date ranges, pagination, query types, and aggregations."Regional endpoint info block
Current:
When making a request to the TagoIO API, you must also specify the appropriate regional endpoint.Good. I’d keep it.
Suggested small improvement:
When making a request to the TagoIO API, use the endpoint for your account region.Reason: Shorter and slightly more direct.
REST headers
Current:
Authorization: Your-Device-TokenNeed to confirm whether the correct header should be Authorization or Device-Token.
The API docs mention multiple token header options, including Device-Token and Authentication. The current Getting Data doc uses Authorization. If Authorization is accepted for device data, this is fine. If not, this should be corrected before merge.
Suggested if both are accepted:
Include your device token in the request header.
```http
Authorization: Your-Device-TokenYou can also use the token header format described in the API Overview.
But avoid adding this unless it is confirmed. Too many token options can confuse users.
---
### REST query parameter table
Current:
```md
| `qty` | number | Maximum records to return (default 15) |
Suggested:
| `qty` | number | Maximum number of records to return. Default is `15`. |Current:
| `skip` | number | Records to skip, used for pagination |Suggested:
| `skip` | number | Number of records to skip before returning results. Used for pagination. |Current:
| `group` | string | Filter by group label |Suggested:
| `group` | string or array | Filter by group identifier |Need to confirm whether REST supports array syntax for group. The API reference lists groups, but this draft says REST uses singular forms. This should be verified.
Response section
The response example is good, but it only shows value records. Since last_location is discussed later, consider adding a location record or keep the response simple.
If kept simple, maybe add:
Returned records may also include fields such as `location`, `metadata`, `group`, `device`, or `created_at`, depending on the stored data and query parameters.This helps users understand why their actual response may differ.
Node.js SDK install block
Good and necessary.
Maybe add a link to SDK documentation if available:
See the [SDK documentation](/docs/tagoio/analysis/sdk/) for more SDK usage details.Filtering by group
Current:
[`groups`](/docs/tagoio/devices/grouping-variables.md) is a free-form label attached to data records at write time.Suggested:
A [`group`](/docs/tagoio/devices/grouping-variables/) is a free-form identifier attached to data records at write time.Reason: The concept is “group”; groups is the SDK parameter name.
Date range tip
Current:
When the date window holds more than 15 records, set `qty` to retrieve them all.This may be risky. If the date window holds thousands of records, “retrieve them all” may encourage inefficient queries or hit limits.
Suggested:
When the date window contains more than 15 records, set `qty` or use pagination to retrieve more results.This is safer and more scalable.
Pagination and ordering
Current:
The API returns 15 records by default, ordered newest-first.Good.
Suggested:
The API returns 15 records by default, ordered from newest to oldest.This is slightly more plain.
Combining filters
Good section. Keep it.
Could add one sentence:
When filters are combined, the API only returns records that match all conditions.This clarifies behavior.
Common pitfalls
This section is excellent and should remain near the end.
Suggested additions:
- **REST and SDK parameter names differ.** REST uses query parameters such as `variable`, `value`, and `group`; the SDK uses `variables`, `values`, and `groups`.
- **Large date windows need pagination.** Increasing `qty` helps, but large exports should be paginated to avoid slow or incomplete requests.
- **Aggregations have stricter rate limits.** Aggregate queries may have lower request limits than standard data queries. Check Rate Limits before using them in high-frequency dashboards or scripts.The last point is important because the rate limit docs show a separate route for aggregate queries.
Possible technical issues to verify before merge
I’d verify these points before approving:
-
REST parameter names
- The draft says REST uses singular forms:
variable,value,group,id. - The current API reference lists
variables,values, andgroups. - If both are supported, document the recommended format.
- If only one is current, align the table and examples.
- The draft says REST uses singular forms:
-
detailsvsdetail- The draft uses
details. - Some older docs mention
detail. - The API reference uses
details. - Confirm and standardize.
- The draft uses
-
Token header
- Confirm whether
Authorization: Your-Device-Tokenis the preferred format for this endpoint. - If the platform prefers
Device-TokenorAuthentication, update the header example.
- Confirm whether
-
Static
Resourcesusage inside Analysis- Confirm that
Resources.devices.getDeviceData(...)without instantiation is valid in the current SDK. - If not, update the example.
- Confirm that
-
interval: "quarter"- Confirm
quarteris supported for aggregate queries. - If yes, keep it. If not, remove it.
- Confirm
-
start_daterequirements- Confirm which query types require
start_date. - The draft says
avg,sum, andconditionalrequire it. That may be correct, but should be verified.
- Confirm which query types require
Recommended concise rewrite for the opening
I’d add this before ## REST API:
Use this page to read data stored in a TagoIO device.
You can retrieve data with:
- **REST API** — useful for direct HTTP requests using a device token.
- **Node.js SDK with `Device`** — useful when your script works with one device.
- **Node.js SDK with `Resources`** — useful when your application or Analysis needs to read data from devices by ID.
By default, data requests return 15 records ordered from newest to oldest. Use filters, date ranges, pagination, or query types to retrieve the exact data you need.This gives the page a clearer entry point and sets expectations early.
Final recommendation
I’d request changes before merging.
The content is useful and technically valuable, but I’d like to see these updates first:
- Add a short overview that explains the three ways to read data.
- Add REST examples for common filters and query types.
- Verify REST parameter names, token header, and
detailsnaming. - Make the REST and SDK sections more parallel.
- Add a related documentation section.
- Soften “retrieve them all” language in the date range tip and recommend pagination for larger windows.
Once those are addressed, this page will be a strong reference for users reading device data through both the API and SDK.
| { | ||
| "id": "547e42847dbf3af122c02582", | ||
| "location": { | ||
| "coordinates": [41.878876, -87.635915], | ||
| "type": "Point" | ||
| }, | ||
| "time": "2014-12-02T22:51:48.005Z", | ||
| "variable": "location" | ||
| }, |
There was a problem hiding this comment.
Why did you remove the example that includes location?
| ```bash | ||
| npm install @tago-io/sdk | ||
| ``` | ||
| https://api.<region>.tago.io/data?variable=temperature |
There was a problem hiding this comment.
It’s okay to add JavaScript examples, but why did we remove the cURL examples?
| ## REST API | ||
|
|
||
| Include your device token in the Authorization header. | ||
| ### Headers | ||
|
|
||
| Include your [device token](/docs/tagoio/devices/device-token.md) in the Authorization header. |
There was a problem hiding this comment.
The REST API section should link to the API docs for both Device-level and Profile-level endpoints.
Those pages explain the details much better than this doc.
Summary
Expands
getting-data.mdwith a full Node.js SDK section covering filters, date ranges, pagination, all query types, aggregations, and common pitfalls. Adds a link from the Node.js SDK page to the expanded doc.Why
The existing page was REST-only with no SDK examples. Power users were hitting support for things like aggregate queries, conditional filters, and pagination patterns that should be self-serve.
There was some back and forth on where to put this content. First pass was a standalone
devices/advanced-data-queries.mdpage, then it moved toanalysis/sdk/to sit alongside the Node.js and Python SDK docs. Both felt off — the new page was a fourth item next to the two SDK reference pages and didn't belong there, and a separate device page duplicated context that already lives ingetting-data.md. Merging into the existing page keeps device data queries in one place.Test plan
getting-data.mdwith both REST API and Node.js SDK sections visibleRisk (CIA)
Likelihood: ⚪ None | Impact: ⚪ None | Exposure: ⚪ None
Docs-only change, no behavior or API surface affected.
Closes #87