Curl Examples
This page provides copy-paste-ready curl examples for every Smart Connect API endpoint, along with sample responses. For OData filtering, see the OData Filtering reference. All endpoints follow the asynchronous pattern described in the Concepts chapter.
Before proceeding, make sure you have:
- A valid API key generated from the API Key Management — see Authentication & Security
curlinstalled on your system- Familiarity with the asynchronous request pattern — see Concepts
Info
In all examples below, replace <region> with your actual region value, and replace your-api-key-here with the API key you generated from the API Key Management.
Endpoint Overview
The Smart Connect API provides six endpoint pairs. Each pair consists of a POST endpoint to initiate data preparation and a GET endpoint to poll for results and retrieve download URLs.
| Endpoint | POST Path | GET Path | Date Range | OData |
|---|---|---|---|---|
| Device Properties | /v3/devices/properties |
/v3/devices/properties/{request_uuid} |
No | Yes |
| Device Status | /v3/devices/status |
/v3/devices/status/{request_uuid} |
No | Yes |
| Measurements | /v2/measurements |
/v2/measurements/{request_uuid} |
Yes | Yes |
| Alarms | /v3/alarms |
/v3/alarms/{request_uuid} |
Yes | Yes |
| Locations | /v1/locations |
/v1/locations/{request_uuid} |
No | Yes |
| Measuring Objects | /v1/measuring-objects |
/v1/measuring-objects/{request_uuid} |
No | Yes |
- Supported file formats: CSV (default), ORC, PARQUET, AVRO, JSON, TEXTFILE
Tip
If you need the same data multiple times, you can cache the download URL and download the file again without making a new API request. Download URLs are valid for approximately one hour.
Device Properties (v3)
Retrieve metadata about devices, sensors, and channels — including serial numbers, model codes, firmware versions, calibration status, and equipment relationships. This endpoint supports OData filtering.
Basic Request
POST https://data-api.<region>.smartconnect.testo.com/v3/devices/properties
curl -X POST "https://data-api.<region>.smartconnect.testo.com/v3/devices/properties" \
-H "Content-Type: application/json" \
-H "x-custom-api-key: your-api-key-here" \
-d '{
"options": {
"result_file_format": "CSV"
}
}'
Sample response:
{
"status": "Submitted",
"request_uuid": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
}
Request with OData Filtering
Scenario: Find all active loggers, returning only identifying and firmware fields.
curl -X POST "https://data-api.<region>.smartconnect.testo.com/v3/devices/properties" \
-H "Content-Type: application/json" \
-H "x-custom-api-key: your-api-key-here" \
-d '{
"options": {
"result_file_format": "CSV"
},
"odata": {
"$filter": "device_category eq '\''LOGGER'\'' and device_is_active eq '\''true'\''",
"$select": "device_uuid,device_serial_no,device_model_code,device_firmware_version,sensor_uuid,sensor_serial_no",
"$orderby": "device_serial_no asc"
}
}'
Poll for Results
GET https://data-api.<region>.smartconnect.testo.com/v3/devices/properties/{request_uuid}
curl -X GET "https://data-api.<region>.smartconnect.testo.com/v3/devices/properties/3fa85f64-5717-4562-b3fc-2c963f66afa6" \
-H "x-custom-api-key: your-api-key-here"
While processing:
{
"status": "In Progress"
}
When completed:
{
"status": "Completed",
"data_urls": [
"https://tds-eu-i-data-storage-query-results.s3.amazonaws.com/devices-properties/3fa85f64-5717-4562-b3fc-2c963f66afa6.csv?..."
],
"metadata_url": "https://tds-eu-i-data-storage-query-results.s3.amazonaws.com/devices-properties/3fa85f64-5717-4562-b3fc-2c963f66afa6.csv.metadata?..."
}
Download Result
curl -o devices-properties.csv "https://tds-eu-i-data-storage-query-results.s3.amazonaws.com/devices-properties/3fa85f64-5717-4562-b3fc-2c963f66afa6.csv?..."
Note
Download URLs are pre-signed S3 URLs. They do not require the x-custom-api-key header and are valid for approximately one hour.
Response Fields
See the API Reference for the full list of fields contained in the downloaded file (x-file-content on the 200 response of each GET endpoint).
Device Status (v3)
Retrieve the current status of devices — including connection type, battery level, radio signal strength, firmware version, and communication timestamps. This endpoint supports OData filtering.
Basic Request
POST https://data-api.<region>.smartconnect.testo.com/v3/devices/status
curl -X POST "https://data-api.<region>.smartconnect.testo.com/v3/devices/status" \
-H "Content-Type: application/json" \
-H "x-custom-api-key: your-api-key-here" \
-d '{
"options": {
"result_file_format": "CSV"
}
}'
Sample response:
{
"status": "Submitted",
"request_uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
Request with OData Filtering
Scenario: Find all Wi-Fi connected devices with battery level below 20% to prioritize maintenance.
curl -X POST "https://data-api.<region>.smartconnect.testo.com/v3/devices/status" \
-H "Content-Type: application/json" \
-H "x-custom-api-key: your-api-key-here" \
-d '{
"options": {
"result_file_format": "CSV"
},
"odata": {
"$filter": "connection_type eq '\''CT_WIFI'\'' and battery_level_percent lt 20",
"$select": "device_uuid,serial_no,connection_type,battery_level_percent,last_communication",
"$orderby": "battery_level_percent asc"
}
}'
Poll for Results
curl -X GET "https://data-api.<region>.smartconnect.testo.com/v3/devices/status/a1b2c3d4-e5f6-7890-abcd-ef1234567890" \
-H "x-custom-api-key: your-api-key-here"
When completed:
{
"status": "Completed",
"data_urls": [
"https://tds-eu-i-data-storage-query-results.s3.amazonaws.com/devices-status/a1b2c3d4-e5f6-7890-abcd-ef1234567890.csv?..."
],
"metadata_url": "https://tds-eu-i-data-storage-query-results.s3.amazonaws.com/devices-status/a1b2c3d4-e5f6-7890-abcd-ef1234567890.csv.metadata?..."
}
Response Fields
See the API Reference for the full list of fields contained in the downloaded file (x-file-content on the 200 response of each GET endpoint).
Measurements (v2)
Retrieve measurement data for a specified time range — including measurement values, timestamps, physical properties, and device/sensor identifiers. This endpoint supports OData filtering.
Basic Request with Date Range
POST https://data-api.<region>.smartconnect.testo.com/v2/measurements
curl -X POST "https://data-api.<region>.smartconnect.testo.com/v2/measurements" \
-H "Content-Type: application/json" \
-H "x-custom-api-key: your-api-key-here" \
-d '{
"date_time_from": "2025-04-01T00:00:00Z",
"date_time_until": "2025-04-07T23:59:59Z",
"options": {
"result_file_format": "CSV"
}
}'
Note
If date_time_from is omitted, it defaults to 1 hour before the current time. If date_time_until is omitted, it defaults to 1 hour after date_time_from.
Sample response:
{
"status": "Submitted",
"request_uuid": "5f330649-9cf2-4d3d-8c96-9e4b2d960678"
}
Request with Parquet Format
curl -X POST "https://data-api.<region>.smartconnect.testo.com/v2/measurements" \
-H "Content-Type: application/json" \
-H "x-custom-api-key: your-api-key-here" \
-d '{
"date_time_from": "2025-04-01T00:00:00Z",
"date_time_until": "2025-04-07T23:59:59Z",
"options": {
"result_file_format": "PARQUET"
}
}'
Note
The number of result files may differ depending on the file format used. PARQUET format is recommended for data analysis workflows with tools like Pandas or Apache Spark.
Request with OData Filtering + Date Range
Scenario: Retrieve only temperature measurements from the past week, sorted by most recent first.
curl -X POST "https://data-api.<region>.smartconnect.testo.com/v2/measurements" \
-H "Content-Type: application/json" \
-H "x-custom-api-key: your-api-key-here" \
-d '{
"date_time_from": "2025-04-01T00:00:00Z",
"date_time_until": "2025-04-07T23:59:59Z",
"options": {
"result_file_format": "CSV"
},
"odata": {
"$filter": "physical_property_name eq '\''Temperature'\''",
"$select": "uuid,sensor_uuid,serial_no,timestamp,measurement,physical_property_name,physical_unit",
"$orderby": "timestamp desc"
}
}'
Poll for Results
curl -X GET "https://data-api.<region>.smartconnect.testo.com/v2/measurements/5f330649-9cf2-4d3d-8c96-9e4b2d960678" \
-H "x-custom-api-key: your-api-key-here"
While processing:
{
"status": "In Progress"
}
When completed:
{
"status": "Completed",
"data_urls": [
"https://tds-eu-i-data-storage-query-results.s3.amazonaws.com/measurements/5f330649-9cf2-4d3d-8c96-9e4b2d960678.csv?..."
],
"metadata_url": "https://tds-eu-i-data-storage-query-results.s3.amazonaws.com/measurements/5f330649-9cf2-4d3d-8c96-9e4b2d960678.csv.metadata?..."
}
Response Fields
See the API Reference for the full list of fields contained in the downloaded file (x-file-content on the 200 response of each GET endpoint).
Alarms (v3)
Retrieve alarm data for a specified time range — including alarm reason, severity, status, and the measured values that triggered the alarm. This endpoint supports OData filtering.
Basic Request with Date Range
POST https://data-api.<region>.smartconnect.testo.com/v3/alarms
curl -X POST "https://data-api.<region>.smartconnect.testo.com/v3/alarms" \
-H "Content-Type: application/json" \
-H "x-custom-api-key: your-api-key-here" \
-d '{
"date_time_from": "2025-04-01T00:00:00Z",
"date_time_until": "2025-04-15T23:59:59Z",
"options": {
"result_file_format": "CSV"
}
}'
Sample response:
{
"status": "Submitted",
"request_uuid": "fbf29fed-e3e2-46fb-a304-ee099e849044"
}
Request with OData Filtering + Date Range
Scenario: Retrieve only active alarms with Warning severity during a specific week, sorted by most recent first.
curl -X POST "https://data-api.<region>.smartconnect.testo.com/v3/alarms" \
-H "Content-Type: application/json" \
-H "x-custom-api-key: your-api-key-here" \
-d '{
"date_time_from": "2025-04-07T00:00:00Z",
"date_time_until": "2025-04-14T23:59:59Z",
"options": {
"result_file_format": "CSV"
},
"odata": {
"$filter": "alarm_status eq '\''Alarm'\'' and alarm_severity eq '\''Warning'\''",
"$select": "uuid,alarm_reason,alarm_status,alarm_severity,alarm_time,alarm_value,physical_unit,serial_no",
"$orderby": "alarm_time desc"
}
}'
Poll for Results
curl -X GET "https://data-api.<region>.smartconnect.testo.com/v3/alarms/fbf29fed-e3e2-46fb-a304-ee099e849044" \
-H "x-custom-api-key: your-api-key-here"
When completed:
{
"status": "Completed",
"data_urls": [
"https://tds-eu-i-data-storage-query-results.s3.amazonaws.com/alarms/fbf29fed-e3e2-46fb-a304-ee099e849044.csv?..."
],
"metadata_url": "https://tds-eu-i-data-storage-query-results.s3.amazonaws.com/alarms/fbf29fed-e3e2-46fb-a304-ee099e849044.csv.metadata?..."
}
Response Fields
See the API Reference for the full list of fields contained in the downloaded file (x-file-content on the 200 response of each GET endpoint).
Locations (v1)
Retrieve information about registered locations — including customer sites, measurement sites, and their hierarchical relationships. This endpoint supports OData filtering.
Basic Request
POST https://data-api.<region>.smartconnect.testo.com/v1/locations
curl -X POST "https://data-api.<region>.smartconnect.testo.com/v1/locations" \
-H "Content-Type: application/json" \
-H "x-custom-api-key: your-api-key-here" \
-d '{
"options": {
"result_file_format": "CSV"
}
}'
Sample response:
{
"status": "Submitted",
"request_uuid": "c8d7e6f5-a4b3-2c1d-0e9f-8a7b6c5d4e3f"
}
Request with OData Filtering
Scenario: Find all measurement site locations, sorted alphabetically by name.
curl -X POST "https://data-api.<region>.smartconnect.testo.com/v1/locations" \
-H "Content-Type: application/json" \
-H "x-custom-api-key: your-api-key-here" \
-d '{
"options": {
"result_file_format": "CSV"
},
"odata": {
"$filter": "location_type eq '\''Measurement site'\''",
"$select": "location_uuid,name,location_type,location_subtype,parent_uuid",
"$orderby": "name asc"
}
}'
Poll for Results
curl -X GET "https://data-api.<region>.smartconnect.testo.com/v1/locations/c8d7e6f5-a4b3-2c1d-0e9f-8a7b6c5d4e3f" \
-H "x-custom-api-key: your-api-key-here"
When completed:
{
"status": "Completed",
"data_urls": [
"https://tds-eu-i-data-storage-query-results.s3.amazonaws.com/locations/c8d7e6f5-a4b3-2c1d-0e9f-8a7b6c5d4e3f.csv?..."
],
"metadata_url": "https://tds-eu-i-data-storage-query-results.s3.amazonaws.com/locations/c8d7e6f5-a4b3-2c1d-0e9f-8a7b6c5d4e3f.csv.metadata?..."
}
Response Fields
See the API Reference for the full list of fields contained in the downloaded file (x-file-content on the 200 response of each GET endpoint).
Measuring Objects (v1)
Retrieve detailed information about measuring objects — including product family, customer site, and configuration data such as alarm configurations, channel assignments, and measuring instructions. This endpoint supports OData filtering.
Basic Request
POST https://data-api.<region>.smartconnect.testo.com/v1/measuring-objects
curl -X POST "https://data-api.<region>.smartconnect.testo.com/v1/measuring-objects" \
-H "Content-Type: application/json" \
-H "x-custom-api-key: your-api-key-here" \
-d '{
"options": {
"result_file_format": "JSON"
}
}'
Tip
JSON format may be more convenient for this endpoint, as the measurement_alarm_configuration, channel_assignments, and measuring_instructions fields contain JSON-encoded strings.
Sample response:
{
"status": "Submitted",
"request_uuid": "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f9a"
}
Request with OData Filtering
Scenario: Retrieve all measuring objects for the "savr" product family.
curl -X POST "https://data-api.<region>.smartconnect.testo.com/v1/measuring-objects" \
-H "Content-Type: application/json" \
-H "x-custom-api-key: your-api-key-here" \
-d '{
"options": {
"result_file_format": "JSON"
},
"odata": {
"$filter": "product_family_id eq '\''savr'\''",
"$select": "mo_uuid,customer_uuid,product_family_id,customer_site,measurement_alarm_configuration"
}
}'
Poll for Results
curl -X GET "https://data-api.<region>.smartconnect.testo.com/v1/measuring-objects/d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f9a" \
-H "x-custom-api-key: your-api-key-here"
When completed:
{
"status": "Completed",
"data_urls": [
"https://tds-eu-i-data-storage-query-results.s3.amazonaws.com/measuring-objects/d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f9a.json?..."
],
"metadata_url": "https://tds-eu-i-data-storage-query-results.s3.amazonaws.com/measuring-objects/d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f9a.json.metadata?..."
}
Response Fields
See the API Reference for the full list of fields contained in the downloaded file (x-file-content on the 200 response of each GET endpoint).
Error Responses
401 Unauthorized
Returned when the API key is missing, invalid, or expired.
curl -X POST "https://data-api.<region>.smartconnect.testo.com/v2/measurements" \
-H "Content-Type: application/json" \
-d '{
"options": { "result_file_format": "CSV" }
}'
{
"message": "Unauthorized"
}
400 Bad Request
Returned when the request body is malformed or contains invalid OData syntax.
curl -X POST "https://data-api.<region>.smartconnect.testo.com/v3/alarms" \
-H "Content-Type: application/json" \
-H "x-custom-api-key: your-api-key-here" \
-d '{
"odata": {
"$filter": "invalid_field === true"
}
}'
{
"status": "Error",
"message": "Bad request: invalid filter expression"
}
500 Internal Server Error
Returned when an unexpected server-side error occurs.
{
"status": "Error",
"message": "An unexpected error occurred. Please try again later."
}
Tips and Best Practices
- Use
$selectto minimize download size: Request only the fields you need to reduce file size and download time. - Cache download URLs: If you need the same data multiple times, reuse the download URL instead of making a new API request. URLs are valid for approximately one hour.
- Use smaller date ranges: For measurements and alarms, requesting smaller time windows reduces processing time and result file sizes.
- Consider PARQUET format for analysis: If you are using data analysis tools like Pandas, Apache Spark, or similar frameworks, PARQUET format provides efficient compression and columnar storage.
- Implement exponential backoff for polling: Instead of polling at a fixed interval, start with a short interval (e.g., 5 seconds) and increase it progressively (10s, 20s, etc.) to avoid unnecessary requests.
- Deduplicate on
uuidfields: The Smart Connect API follows an at-least-once delivery policy. Duplicate records can occur, so plan to deduplicate results using theuuidfield.
What Next?
We recommend exploring the API Reference for the complete schema documentation, including all available fields and their detailed descriptions. If you are not yet familiar with the asynchronous request model, read the Concepts chapter.