This document describes the REST API endpoints provided by the TSFile Viewer backend.
TSFile Viewer fully supports both TSFile V4 Table Model and V3/legacy Tree Model formats:
TableSchema with TAG and FIELD columnstablename.tagvalue1.tagvalue2... from table name and TAG column valuessensor_data.device_001.room_Aroot.sensor1)TsFileSequenceReader with QueryExpression API for data readingAll query endpoints work transparently with both models:
devices parameter to filter by table names (for table model queries)measurements parameter to filter by column namesdevice field contains the constructed device identifiertablename.tag1.tag2)root.device1)The backend automatically detects the TSFile model type:
TableSchema entries exist, uses Table Model API (ITsFileReader.query())TableSchema found, automatically switches to Tree Model API (TsFileReader with QueryExpression)This detection is transparent to API consumers - the same endpoints work for both models without any client-side changes.
http://localhost:8080/apiVITE_API_BASE_URL environment variableCurrently, the API does not require authentication. Future versions may add OAuth2 or JWT-based authentication.
{ "data": { ... }, "status": 200 }
{ "status": 400, "error": "Bad Request", "message": "Detailed error message", "timestamp": "2024-01-17T10:30:00Z", "path": "/api/files/upload", "validationErrors": [ { "field": "file", "message": "File must be a .tsfile", "rejectedValue": "test.txt" } ] }
200 OK - Request successful400 Bad Request - Invalid request parameters or validation errors403 Forbidden - Directory path outside whitelist404 Not Found - Resource not found413 Payload Too Large - Upload exceeds size limit500 Internal Server Error - Server-side error504 Gateway Timeout - Query timeout exceededBrowse server directory tree with lazy loading.
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
| root | string | Yes | Root directory path (must be whitelisted) |
| path | string | No | Subdirectory path for lazy loading |
Example Request:
GET /api/files/tree?root=/data/tsfiles&path=2024/01
Example Response:
{ "name": "01", "path": "/data/tsfiles/2024/01", "isDirectory": true, "isLoaded": true, "children": [ { "name": "sensor1.tsfile", "path": "/data/tsfiles/2024/01/sensor1.tsfile", "isDirectory": false, "isLoaded": false, "children": null }, { "name": "sensor2.tsfile", "path": "/data/tsfiles/2024/01/sensor2.tsfile", "isDirectory": false, "isLoaded": false, "children": null } ] }
Error Responses:
403 Forbidden - Path outside whitelist404 Not Found - Directory not foundUpload a TSFile to the server.
Request:
multipart/form-datafile fieldExample Request:
POST /api/files/upload Content-Type: multipart/form-data file: [binary data]
Example Response:
{ "fileId": "f7a3b2c1-4d5e-6f7g-8h9i-0j1k2l3m4n5o", "fileName": "sensor1.tsfile", "fileSize": 1048576, "uploadTime": "2024-01-17T10:30:00Z" }
Error Responses:
400 Bad Request - Invalid file type or corrupted file413 Payload Too Large - File exceeds 100MB limitGet complete metadata for a TSFile.
Path Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
| fileId | string | Yes | Unique file identifier |
Example Request:
GET /api/meta/f7a3b2c1-4d5e-6f7g-8h9i-0j1k2l3m4n5o
Example Response:
{ "fileId": "f7a3b2c1-4d5e-6f7g-8h9i-0j1k2l3m4n5o", "version": "1.0", "timeRange": { "startTime": 1705478400000, "endTime": 1705564800000 }, "deviceCount": 5, "measurementCount": 10, "rowGroupCount": 3, "chunkCount": 15, "measurements": [ { "name": "temperature", "dataType": "FLOAT", "encoding": "GORILLA", "compression": "SNAPPY" }, { "name": "humidity", "dataType": "FLOAT", "encoding": "GORILLA", "compression": "SNAPPY" } ], "rowGroups": [ { "index": 0, "device": "root.sensor1", "startTime": 1705478400000, "endTime": 1705492800000, "chunkCount": 5 } ], "chunks": [ { "measurement": "temperature", "offset": 1024, "size": 4096, "compressionRatio": 0.65 } ] }
Error Responses:
404 Not Found - File not found500 Internal Server Error - Failed to parse TSFileTSFile Viewer supports both Table Model (V4) and Tree Model (V3/legacy) TSFile formats:
The API transparently handles both models using the same endpoints.
Preview TSFile data with filtering and pagination.
Request Body:
{ "fileId": "f7a3b2c1-4d5e-6f7g-8h9i-0j1k2l3m4n5o", "startTime": 1705478400000, "endTime": 1705564800000, "devices": ["root.sensor1", "root.sensor2"], "measurements": ["temperature", "humidity"], "valueRange": { "min": 20.0, "max": 30.0 }, "limit": 100, "offset": 0 }
Request Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
| fileId | string | Yes | Unique file identifier |
| startTime | long | No | Start timestamp (milliseconds) |
| endTime | long | No | End timestamp (milliseconds) |
| devices | string[] | No | Filter by device names (table names in V4) |
| measurements | string[] | No | Filter by measurement/column names |
| valueRange | object | No | Filter by value range (min/max) - requires ALL numeric values in row to be in range |
| limit | int | No | Page size (1-1000, default: 100) |
| offset | int | No | Page offset (default: 0) |
Table Model Example Response:
{ "data": [ { "timestamp": 1705478400000, "device": "sensor_table.sensor_001.room_A", "measurements": { "device_id": "sensor_001", "location": "room_A", "temperature": 25.5, "humidity": 60.0 } } ], "total": 1500, "limit": 100, "offset": 0, "hasMore": true }
Device Identifier Format (Table Model): In Table Model, the device identifier is constructed as: tablename.tagvalue1.tagvalue2...
sensor_table.device_001.room_A where sensor_table is the table name, device_001 is the device_id TAG value, and room_A is the location TAG valueTree Model Example Response:
{ "data": [ { "timestamp": 1705478400000, "device": "root.sensor1", "measurements": { "temperature": 25.5, "humidity": 60.0, "pressure": 1013.2 } } ], "total": 1500, "limit": 100, "offset": 0, "hasMore": true }
Multi-Table Query Example (V4 Table Model):
To query data from a specific table in a multi-table TSFile, use the devices parameter with the table name:
{ "fileId": "abc123", "devices": ["sensor_table"], "measurements": ["temperature", "humidity"], "limit": 100, "offset": 0 }
Pagination Best Practices:
hasMore field indicates if more data is available beyond current pageValue Range Filter Notes:
Error Responses:
400 Bad Request - Invalid filter parameters404 Not Found - File not found504 Gateway Timeout - Query exceeded timeout (30s)Query TSFile data for chart visualization with aggregation and downsampling.
Supports both Table and Tree models with automatic downsampling for large datasets and optional time-window aggregation.
Request Body:
{ "fileId": "f7a3b2c1-4d5e-6f7g-8h9i-0j1k2l3m4n5o", "startTime": 1705478400000, "endTime": 1705564800000, "measurements": ["temperature", "humidity"], "devices": ["root.sensor1"], "aggregation": "AVG", "windowSize": 60000, "maxPoints": 1000 }
Request Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
| fileId | string | Yes | Unique file identifier |
| measurements | string[] | Yes | Measurements/columns to query |
| startTime | long | No | Start timestamp (milliseconds) |
| endTime | long | No | End timestamp (milliseconds) |
| devices | string[] | No | Filter by device/table names |
| aggregation | enum | No | Aggregation type (MIN, MAX, AVG, COUNT) |
| windowSize | int | No | Aggregation window size (milliseconds) |
| maxPoints | int | No | Maximum data points (default: 1000, triggers downsampling) |
Table Model Example Request:
{ "fileId": "table-model-file", "measurements": ["temperature", "humidity", "pressure"], "devices": ["sensor_table"], "startTime": 1705478400000, "endTime": 1705564800000, "aggregation": "AVG", "windowSize": 300000, "maxPoints": 500 }
Tree Model Example Request:
{ "fileId": "tree-model-file", "measurements": ["s1", "s2", "s3"], "devices": ["root.device1", "root.device2"], "startTime": 1705478400000, "endTime": 1705564800000, "maxPoints": 1000 }
Example Response:
{ "series": [ { "name": "temperature", "data": [ [1705478400000, 25.5], [1705478460000, 26.0], [1705478520000, 25.8] ] }, { "name": "humidity", "data": [ [1705478400000, 60.0], [1705478460000, 62.0], [1705478520000, 61.5] ] } ], "timeRange": { "startTime": 1705478400000, "endTime": 1705564800000 }, "totalPoints": 3, "downsampled": false }
Aggregation Types:
MIN - Minimum value in time windowMAX - Maximum value in time windowAVG - Average value in time windowCOUNT - Count of data points in time windowTime-Window Aggregation:
When both aggregation and windowSize are specified, data is aggregated into time windows:
Downsampling:
When totalPoints > maxPoints, the LTTB (Largest Triangle Three Buckets) algorithm is applied to reduce data points while preserving visual trends.
maxPoints (default: 1000)downsampled: true flagVisualization Best Practices:
maxPoints: 1000 to get overviewError Responses:
400 Bad Request - Invalid parameters or empty measurements404 Not Found - File not found504 Gateway Timeout - Query exceeded timeout (30s)These endpoints provide enhanced support for multi-table TSFile scenarios, allowing you to list tables, discover devices, and query data from specific tables with advanced pagination.
Get a list of all tables in the specified TSFile with column information and row counts.
Path Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
| fileId | string | Yes | Unique file identifier |
Example Request:
GET /api/tables/f7a3b2c1-4d5e-6f7g-8h9i-0j1k2l3m4n5o
Example Response:
{ "tables": [ { "tableName": "sensor_data", "columns": ["device_id", "location", "temperature", "humidity"], "tagColumns": ["device_id", "location"], "fieldColumns": ["temperature", "humidity"], "rowCount": 10000 }, { "tableName": "device_status", "columns": ["device_id", "status", "last_update"], "tagColumns": ["device_id"], "fieldColumns": ["status", "last_update"], "rowCount": 500 } ], "totalCount": 2 }
Error Responses:
404 Not Found - File not found403 Forbidden - Access deniedGet a list of unique device identifiers in the specified TSFile.
Path Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
| fileId | string | Yes | Unique file identifier |
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
| tableName | string | No | Filter devices by specific table name |
Example Request:
GET /api/tables/f7a3b2c1-4d5e-6f7g-8h9i-0j1k2l3m4n5o/devices?tableName=sensor_data
Example Response:
{ "devices": [ { "deviceId": "sensor_data.device_001.room_A", "tableName": "sensor_data", "tagValues": ["device_001", "room_A"], "dataPointCount": 5000 }, { "deviceId": "sensor_data.device_002.room_B", "tableName": "sensor_data", "tagValues": ["device_002", "room_B"], "dataPointCount": 4500 } ], "totalCount": 2 }
Device Identifier Format:
tablename.tagvalue1.tagvalue2...tablename (same as table name)Error Responses:
404 Not Found - File not found403 Forbidden - Access deniedQuery data from a specific table with advanced filtering and pagination.
Request Body:
{ "fileId": "f7a3b2c1-4d5e-6f7g-8h9i-0j1k2l3m4n5o", "tableName": "sensor_data", "startTime": 1705478400000, "endTime": 1705564800000, "columns": ["temperature", "humidity"], "valueRange": { "min": 20.0, "max": 30.0 }, "limit": 100, "offset": 0 }
Request Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
| fileId | string | Yes | Unique file identifier |
| tableName | string | Yes | Table name to query |
| startTime | long | No | Start timestamp (milliseconds) |
| endTime | long | No | End timestamp (milliseconds) |
| columns | string[] | No | Specific columns to retrieve |
| valueRange | object | No | Filter by value range (min/max) |
| limit | int | No | Page size (1-10000, default: 100) |
| offset | int | No | Page offset (default: 0) |
Example Response:
{ "tableName": "sensor_data", "columns": ["time", "temperature", "humidity"], "columnTypes": ["TIMESTAMP", "DOUBLE", "INT32"], "rows": [ { "time": 1705478400000, "temperature": 25.5, "humidity": 60 }, { "time": 1705478460000, "temperature": 26.0, "humidity": 62 } ], "total": 10000, "limit": 100, "offset": 0, "hasMore": true }
Pagination Notes:
total: Total number of rows matching the filter criteriahasMore: Indicates if more pages are availableoffset + limit for next page offsetlimit is 10000 for this endpoint (higher than preview API)Error Responses:
400 Bad Request - Invalid parameters or missing required fields404 Not Found - File or table not found403 Forbidden - Access deniedCurrently, no rate limiting is enforced. Future versions may implement rate limiting per IP or user.
The backend implements two levels of caching:
Cache headers are not currently exposed in responses.
All paginated endpoints use limit/offset pagination:
limit: Number of items per page (1-1000)offset: Number of items to skiphasMore: Boolean indicating if more data is availableAll errors follow a consistent format with:
status: HTTP status codeerror: Error type (e.g., “Bad Request”)message: Human-readable error messagetimestamp: ISO 8601 timestamppath: Request path that caused the errorvalidationErrors: Array of field-level validation errors (for 400 responses)# 1. Upload a TSFile curl -X POST http://localhost:8080/api/files/upload \ -F "file=@sensor1.tsfile" # Response: { "fileId": "abc123", ... } # 2. Get metadata curl http://localhost:8080/api/meta/abc123 # 3. Preview data curl -X POST http://localhost:8080/api/data/preview \ -H "Content-Type: application/json" \ -d '{ "fileId": "abc123", "limit": 10, "offset": 0 }' # 4. Query chart data curl -X POST http://localhost:8080/api/data/query \ -H "Content-Type: application/json" \ -d '{ "fileId": "abc123", "measurements": ["temperature"], "aggregation": "AVG", "windowSize": 60000, "maxPoints": 1000 }'
For API issues or questions: