EOS IoT Platform API
REST API to access IoT device data on the EOS platform. This documentation guides you through using the API to integrate device data into your applications.
📥 Download the OpenAPI specification and share it with your AI agent to get the full API context.
- EOS Support Team: pietro.parini@sintropy.ai
- URL: https://sintropy.ai
- License: Proprietary
Note: This is a new product (version 1.0.0). We welcome any feedback to help us improve the API. Don't hesitate to share your suggestions or report any issues you run into.
Authentication
All requests must include the x-api-key header with the API key provided at registration.
Example:
curl -H "x-api-key: YOUR_API_KEY" https://p2uyaymt8c.execute-api.eu-south-1.amazonaws.com/v1/integration/devices
Security:
- ⚠️ Never share your API key
- ⚠️ Don't put it in source code
- ✅ Use environment variables to store it
Rate limiting
The API is rate-limited to keep the service stable. The specific limits depend on your usage plan:
Standard plan:
- Rate: 0.5 requests per second
- Burst: 5 concurrent requests
- Quota: 100,000 requests per month
Custom plans: Other plans with different limits are available. Contact support for more information.
⚠️ Important: Be careful not to burn through your whole quota in the first three days of the month. Plan your API usage to spread requests evenly across the entire billing period and avoid running out of quota too early.
Multiple measurements
Some devices can have more than one sensor of the same type. For example, a device may have:
- Two temperature sensors (one internal and one external)
In these cases:
- The measure field will be the same (e.g. "temperature")
- The sensor_type field will differ (e.g. "in100-q1-r-rc0i" vs "sht40-ad1b-r2")
Use the sensorType parameter to filter a specific sensor when needed.
Date format
All dates must be in ISO 8601 format with UTC timezone:
- Format: YYYY-MM-DDTHH:mm:ssZ
- Example: 2026-02-04T15:30:00Z
Historical data granularity
The /devices/{deviceId}/history endpoint supports several granularities:
- raw: Raw data with no aggregation
- 15m: Data aggregated every 15 minutes (average, min, max)
- 1h: Data aggregated hourly (average, min, max)
- 1d: Data aggregated daily (average, min, max)
Pagination
The /devices/{deviceId}/history endpoint supports pagination:
- limit: Maximum number of results (default: 100, max: 100)
- offset: Number of results to skip (default: 0)
- The response includes pagination information in the pagination field
Data availability
Historical data availability depends on the granularity and on the sensor's installation date:
- Data availability start date: Data is available from the sensor's installation date for each device
- Raw data: Available for 30 days from the current date
- High-frequency CSV data files: Available for 30 days from the current date (same retention as raw data)
Note: This feature is only available if you have high-frequency devices (e.g. motor sensors). If your tenant/site has no high-frequency devices, the API will return an error message.
- 15-minute aggregated data (15m): Available for 90 days from the current date
- Hourly aggregated data (1h): Available for 2 years from the current date
- Daily aggregated data (1d): Available permanently (no expiry)
Recommendations:
- Use raw for detailed recent analysis (last 30 days)
- Use the high-frequency CSV files for bulk downloads of recent data (last 30 days)
- Use 15m for medium-term trends (up to 90 days)
- Use 1h for long-term analysis (up to 2 years)
- Use 1d for historical analysis beyond 2 years
Support
For assistance or questions, contact technical support.
HTTP status codes
- 200 OK: Request completed successfully
- 400 Bad Request: Malformed request or missing parameters
- 401 Unauthorized: Missing or invalid API key
- 403 Forbidden: Access denied
- 404 Not Found: Resource not found
- 500 Internal Server Error: Internal server error
Devices
Operations to query the available IoT devices.
These endpoints let you:
- Get the list of devices
- Query the measurements available for each device
List devices
Returns the list of devices available for your API key.
Behavior:
- Without parameters: returns all available devices
- With includeMeasures=true: includes the measurements available for each device
Performance:
- Without includeMeasures: fast query, ideal for long lists
- With includeMeasures=true: slower query, use only when needed
Usage examples:
- Simple list:
GET /devices - With measurements:
GET /devices?includeMeasures=true
Authorization: ApiKeyAuth
Query parameters
includeMeasures boolean · Default: false · Example: includeMeasures=true
If true, includes the measurements available for each device in the available_measures field.
When to use it:
- When you need to know which measurements are available before making data calls
- When you want to show users the available options
When NOT to use it:
- When you only want the device list (faster)
- When you already have information about the available measurements
Responses
- 200 · Device list returned successfully
- 400 · Invalid request. Common causes: missing or malformed parameters, out-of-range values, invalid date format, empty or oversized array
- 401 · Unauthorized, authentication failed. Causes: API key missing from the
x-api-keyheader, invalid or expired API key, API key not linked to a valid Usage Plan - 403 · Access denied, insufficient permissions
- 500 · Internal server error. Retry the request after a few seconds; if the problem persists, contact support and include the
requestIdif available in your logs
get /devices
Data
Operations to access device data.
These endpoints let you:
- Get the latest available value for a device
- Get the latest values from multiple devices in a single call
- Query historical data at different granularities
- Filter by measurement type and sensor
Latest device value
Returns the latest available value for a specific device.
Behavior by parameters:
- Without parameters (
GET /devices/{deviceId}/last): returns all measurements from the latest available timestamp. Format: object withdevice_id,timestampand adataarray. Useful when you want to see all simultaneous measurements - With measure (
GET /devices/{deviceId}/last?measure=temperature): returns only that measurement. If multiple sensors share the samemeasure, all of them are returned. Format: single object or array (if multiple sensors) - With measure and sensorType (
GET /devices/{deviceId}/last?measure=temperature&sensorType=in100-q1-r-rc0i): returns only that specific sensor. Format: single object
Usage examples:
- All measurements:
GET /devices/aa:bb:cc:dd:ee:ff/last - Temperature only:
GET /devices/aa:bb:cc:dd:ee:ff/last?measure=temperature - Specific sensor:
GET /devices/aa:bb:cc:dd:ee:ff/last?measure=temperature&sensorType=in100-q1-r-rc0i
Authorization: ApiKeyAuth
Path parameters
deviceId required string ^[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}$ · Example: aa:bb:cc:dd:ee:ff
Device ID (MAC address in XX:XX:XX:XX:XX:XX format). Separator: colon (:). Case insensitive.
Query parameters
- measure
string· Example:measure=temperature. Filters by measurement type. Accepted values: any measurement type returned by the sensors (e.g.temperature,humidity,pressure,co2,battery_percentage,battery_voltage,rssi,a_current,b_current,c_current,total_current,a_voltage,b_voltage,c_voltage,a_act_power,b_act_power,c_act_power,total_act_power, etc.) or"all"to return all measurements. The value must exactly match themeasurefield returned by the sensors (case-sensitive) - sensorType
string· Example:sensorType=in100-q1-r-rc0i. Filters by sensor type. Examples:in100-q1-r-rc0i(internal temperature sensor),sht40-ad1b-r2(external temperature sensor),dht22(humidity/temperature sensor). Note: must be used together withmeasureto be effective
Responses
- 200 · Latest value(s) returned successfully
- 400 · Invalid request
- 401 · Unauthorized, authentication failed
- 403 · Access denied, insufficient permissions
- 404 · Resource not found. Causes: nonexistent device ID, device not accessible with your API key, no data available for the requested device. Note: if the device exists but has no data, you will still get a 404
- 500 · Internal server error
get /devices/{deviceId}/last
Example response (with measure and sensorType, single object):
{
"timestamp": "2026-02-04T15:30:00Z",
"device_id": "aa:bb:cc:dd:ee:ff",
"sensor_type": "in100-q1-r-rc0i",
"measure": "temperature",
"unit": "C",
"value": 22.5
}
Latest values from multiple devices
Returns the latest values from multiple devices in a single call.
Benefits:
- Reduces the number of HTTP calls needed
- More efficient when reading data from many devices
- Keeps the same filtering logic as
/devices/{deviceId}/last
Limitations:
- Maximum 100 devices per request
- Longer timeout for large lists
Behavior:
- Without measure: returns all measurements for each device
- With measure: returns only that measurement for each device
- With measure and sensorType: returns only that sensor for each device
Usage examples:
- All devices, all measurements:
POST /devices/last/bulkwith{"deviceIds": [...]} - All devices, temperature only:
POST /devices/last/bulkwith{"deviceIds": [...], "measure": "temperature"} - Specific sensor:
POST /devices/last/bulkwith{"deviceIds": [...], "measure": "temperature", "sensorType": "in100-q1-r-rc0i"}
Authorization: ApiKeyAuth
Request Body schema: application/json
- deviceIds
requiredArray of strings [ 1 .. 100 ] items· List of device IDs to query. Minimum: 1 device. Maximum: 100 devices. Format: array of strings (MAC address) - measure
string· Filters by measurement type (optional). If omitted, returns all measurements for each device - sensorType
string· Filters by sensor type (optional). Must be used together withmeasureto be effective
Responses
- 200 · Latest values returned successfully
- 400 · Invalid request
- 401 · Unauthorized, authentication failed
- 403 · Access denied, insufficient permissions
- 500 · Internal server error
post /devices/last/bulk
Example request:
{
"deviceIds": ["aa:bb:cc:dd:ee:ff", "11:22:33:44:55:66", "ff:ee:dd:cc:bb:aa"]
}
Example response:
{
"results": [{}, {}],
"count": 2,
"requested": 2
}
Device historical data
Returns a device's historical data within a specified time range.
Available granularities:
- raw (default): Raw data with no aggregation. Each row is a single measurement. Maximum time precision, more data returned
- 15m: Data aggregated every 15 minutes. Each row contains average, minimum and maximum. Significantly reduces data volume
- 1h: Hourly aggregated data. Each row contains average, minimum and maximum. Even more compact
- 1d: Daily aggregated data. Each row contains the day's average, minimum and maximum. Minimum data volume
Pagination:
- Use limit to control how many results you get (max 100)
- Use offset to move between pages
- The response includes
pagination.hasMoreto tell you whether more data exists
Filters:
- measure: Filters by measurement type
- sensorType: Filters by sensor type (must be used with
measure)
Usage examples:
- Full history:
GET /devices/{id}/history?startDate=...&endDate=... - Temperature only:
GET /devices/{id}/history?startDate=...&endDate=...&measure=temperature - Specific sensor:
GET /devices/{id}/history?startDate=...&endDate=...&measure=temperature&sensorType=in100-q1-r-rc0i - Aggregated data:
GET /devices/{id}/history?startDate=...&endDate=...&granularity=1d
Authorization: ApiKeyAuth
Path parameters
deviceId required string ^[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}$ · Example: aa:bb:cc:dd:ee:ff. Device ID (MAC address)
Query parameters
- startDate
requiredstring <date-time>· Example:startDate=2026-02-04T00:00:00Z. Start date/time of the range (ISO 8601, UTC) - endDate
requiredstring <date-time>· Example:endDate=2026-02-04T23:59:59Z. End date/time of the range (ISO 8601, UTC). Note: must be later thanstartDate - granularity
string· Default:"raw"· Enum:"raw""15m""1h""1d". Granularity of the returned data - measure
string· Example:measure=temperature. Filters by measurement type - sensorType
string· Example:sensorType=in100-q1-r-rc0i. Filters by sensor type (must be used withmeasure) - limit
integer [ 1 .. 100 ]· Default:100· Example:limit=100. Maximum number of results to return - offset
integer >= 0· Default:0· Example:offset=0. Number of results to skip (for pagination)
Responses
- 200 · Historical data returned successfully
- 400 · Invalid request
- 401 · Unauthorized, authentication failed
- 403 · Access denied, insufficient permissions
- 404 · Resource not found
- 500 · Internal server error
get /devices/{deviceId}/history
Example response (granularity=raw):
{
"data": [{}, {}, {}],
"pagination": {
"limit": 100,
"offset": 0,
"total": 96,
"hasMore": true,
"returned": 96
},
"granularity": "raw"
}
High-frequency data
Operations to access the CSV files of high-frequency device data.
These endpoints let you:
- List the available high-frequency CSV data files
- Download the CSV files through pre-signed S3 URLs
- Filter files by date, hour and device
- Monitor daily download quotas
List high-frequency CSV files
Returns a list of the CSV files available for high-frequency device data, with pre-signed S3 URLs for download.
⚠️ Important: This endpoint is only available if you have high-frequency devices (e.g. motor sensors). If your tenant/site has no high-frequency devices, the API will return a
NoHighFrequencyDeviceserror message.
High-frequency data system:
- CSV files are created automatically every hour (at minute 10) for the previous hour
- One file per device per hour (only if data exists)
- Files are stored in S3 and organized by tenant, device, date and hour
- Only devices flagged as
highfrequency = trueare included
Data retention: High-frequency CSV data files are available for 30 days (like raw data).
Download quotas:
- Each tenant has a daily download limit (
backup_hf_daily_download_limit) - The limit is shared across all API keys/users within the tenant
- The quota resets at midnight UTC
- Every pre-signed URL generation counts toward the daily limit
Default behavior (no deviceId and no hour):
- Returns only the latest available file for each device (for the selected date, default: current UTC day)
- Keeps responses small and is ideal for "daily sync" clients
Full-day mode:
- To retrieve all of the day's files for all devices, use
mode=day
Filters:
- date: Filter by a specific date (YYYY-MM-DD). Default: current day
- hour: Filter by a specific hour (0-23)
- deviceId: Filter by a specific device (must belong to your tenant)
- mode:
latest(default) orday
Response format:
- Files are grouped by
device_id, then by hour - Each hour contains a pre-signed S3 URL (valid for 15 minutes)
- Quota information shows the daily limit, usage and remaining downloads
Error cases:
- If the tenant/site has no high-frequency devices: returns a
"NoHighFrequencyDevices"error - If the daily quota is exceeded: returns
429 Too Many Requests - If the device does not belong to the tenant: returns
403 Forbidden
Authorization: ApiKeyAuth
Query parameters
- date
string^\d{4}-\d{2}-\d{2}$· Example:date=2026-02-19. Date to query the high-frequency data files for (YYYY-MM-DD format). Default: current day (UTC) - hour
integer [ 0 .. 23 ]· Example:hour=15. Hour to filter files by (0-23). Example: 15 for 3:00 PM - deviceId
string^[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}$· Example:deviceId=ad:6a:f5:ae:c9:b5. Device ID to filter files by (MAC address format). Note: the device must belong to your tenant - mode
string· Default:"latest"· Enum:"latest""day"· Example:mode=latest. Response mode:latest(default) returns only the latest available file for each device;dayreturns all files for the entire day (can be large)
Responses
- 200 · High-frequency data file list returned successfully
- 400 · Invalid request parameters
- 401 · Unauthorized, authentication failed
- 403 · Access denied, missing permission or device not belonging to the tenant
- 404 · Device not found
- 429 · Daily download quota exceeded
- 500 · Internal server error
get /backup_files_highfrequency
Example response (success with files):
{
"files": {
"ad:6a:f5:ae:c9:b5": {}
},
"quota": {
"dailyLimit": 100,
"usedToday": 3,
"remaining": 97,
"resetAt": "2026-02-20T00:00:00.000Z"
}
}