{"openapi":"3.1.0","info":{"title":"sensapp","description":"","license":{"name":""},"version":"0.3.0"},"paths":{"/":{"get":{"tags":["SensApp"],"operationId":"frontpage","responses":{"200":{"description":"SensApp Frontpage","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/api/v1/admin/vacuum":{"post":{"tags":["Admin"],"summary":"Database Vacuuming","description":"Cleans up and optimizes the database by removing unused data and reclaiming space.\n(only if supported by the underlying storage engine).","operationId":"vacuum_database","responses":{"200":{"description":"Database vacuum completed successfully","content":{"text/plain":{"schema":{"type":"string"}}}},"500":{"description":"Failed to vacuum database","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/api/v1/prometheus_remote_read":{"post":{"tags":["Prometheus"],"summary":"Prometheus Remote Read API.","description":"Allows you to read data from SensApp using Prometheus remote read protocol.\n\nIt follows the [Prometheus Remote Read specification](https://prometheus.io/docs/prometheus/latest/querying/remote_read_api/).","operationId":"prometheus_remote_read","parameters":[{"name":"content-encoding","in":"header","description":"Content encoding, must be snappy","required":true,"schema":{"type":"string","format":"snappy"}},{"name":"content-type","in":"header","description":"Content type, must be application/x-protobuf","required":true,"schema":{"type":"string","format":"application/x-protobuf"}},{"name":"x-prometheus-remote-read-version","in":"header","description":"Prometheus Remote Read version, must be 0.1.0","required":true,"schema":{"type":"string","format":"0.1.0"}}],"requestBody":{"description":"Prometheus Remote Read endpoint. [Reference](https://prometheus.io/docs/prometheus/latest/querying/remote_read_api/)","content":{"application/x-protobuf":{}}},"responses":{"200":{"description":"Read Response","content":{"application/x-protobuf":{}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppError"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppError"}}}}}}},"/api/v1/prometheus_remote_write":{"post":{"tags":["Prometheus"],"summary":"Prometheus Remote Write API.","description":"Allows you to write data from Prometheus to SensApp.\n\nIt follows the [Prometheus Remote Write specification](https://prometheus.io/docs/concepts/remote_write_spec/).","operationId":"publish_prometheus","parameters":[{"name":"content-encoding","in":"header","description":"Content encoding, must be snappy","required":true,"schema":{"type":"string","format":"snappy"}},{"name":"content-type","in":"header","description":"Content type, must be application/x-protobuf","required":true,"schema":{"type":"string","format":"application/x-protobuf"}},{"name":"x-prometheus-remote-write-version","in":"header","description":"Prometheus Remote Write version, must be 0.1.0","required":true,"schema":{"type":"string","format":"0.1.0"}}],"requestBody":{"description":"Prometheus Remote Write endpoint. [Reference](https://prometheus.io/docs/concepts/remote_write_spec/)","content":{"application/x-protobuf":{}}},"responses":{"204":{"description":"No Content"},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppError"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppError"}}}}}}},"/api/v1/query":{"get":{"tags":["SensApp"],"summary":"Simple PromQL query endpoint.","description":"Parses a PromQL expression and returns matching time series data.\nOnly simple selectors (VectorSelector and MatrixSelector) are supported.\n\n# Examples\n\n- Simple metric: `GET /api/v1/query?query=my_metric`\n- With labels: `GET /api/v1/query?query=my_metric{env=\"prod\"}`\n- Range query: `GET /api/v1/query?query=my_metric[5m]`\n- With format: `GET /api/v1/query?query=my_metric&format=csv`","operationId":"simple_promql_query","parameters":[{"name":"query","in":"query","description":"PromQL query string (e.g., 'my_metric{label=\"value\"}' or 'my_metric[5m]')","required":true,"schema":{"type":"string"}},{"name":"format","in":"query","description":"Output format: senml (default), csv, jsonl, or arrow","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Query results in requested format","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid or unsupported PromQL query"},"500":{"description":"Internal server error"}}}},"/api/v2/write":{"post":{"tags":["InfluxDB"],"summary":"InfluxDB Compatible Write API.","description":"Allows you to write data from InfluxDB or Telegraf to SensApp.\n[More information.](https://github.com/SINTEF/sensapp/blob/main/docs/INFLUX_DB.md)","operationId":"publish_influxdb","parameters":[{"name":"bucket","in":"query","description":"Bucket name","required":true,"schema":{"type":"string"},"example":"sensapp"},{"name":"org","in":"query","description":"Organization name","required":false,"schema":{"type":"string"},"example":"sensapp"},{"name":"org_id","in":"query","description":"Organization ID","required":false,"schema":{"type":"string"}},{"name":"precision","in":"query","description":"Precision of the timestamps. One of ns, us, ms, s","required":false,"schema":{"type":"string"}}],"requestBody":{"description":"InfluxDB Line Protocol endpoint. [Reference](https://docs.influxdata.com/influxdb/v2/reference/syntax/line-protocol/).","content":{"text/plain":{"schema":{"type":"string"},"example":"cpu,host=A,region=west usage_system=64.2 1590488773254420000"}},"required":true},"responses":{"204":{"description":"No Content"},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppError"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppError"}}}}}}},"/health/live":{"get":{"tags":["Health"],"summary":"Liveness check","description":"Checks if the service is running.\nThis endpoint always returns 200 OK if the server is able to respond.","operationId":"liveness","responses":{"200":{"description":"Service is alive","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}}}}}},"/health/ready":{"get":{"tags":["Health"],"summary":"Readiness check","description":"Checks if the service is ready to accept traffic.\nThis includes checking if the database connection is working","operationId":"readiness","responses":{"200":{"description":"Service is ready","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReadinessResponse"}}}},"503":{"description":"Service is not ready","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReadinessResponse"}}}}}}},"/metrics":{"get":{"tags":["SensApp"],"summary":"List unique metrics (measurement types) with aggregated information in DCAT catalog format.","operationId":"list_metrics","parameters":[{"name":"name","in":"query","description":"Filter metrics by name (substring match)","required":false,"schema":{"type":"string"}},{"name":"name_regex","in":"query","description":"Filter metrics by name using regex pattern","required":false,"schema":{"type":"string"}},{"name":"type","in":"query","description":"Filter metrics by sensor type (float, integer, string, boolean, location, json, blob, numeric)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Metrics catalog in DCAT format","content":{"application/json":{"schema":{}}}}}}},"/prometheus/metrics":{"get":{"tags":["Observability"],"operationId":"prometheus_metrics","responses":{"200":{"description":"Prometheus-compatible metrics","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/publish":{"post":{"tags":["SensApp"],"summary":"SensApp native data ingestion API supporting multiple formats.","description":"Accepts sensor data in one of the following formats:\n- **SenML JSON** (RFC 8428): `Content-Type: application/json`\n- **CSV**: `Content-Type: text/csv` or `application/csv`\n- **Apache Arrow IPC**: `Content-Type: application/vnd.apache.arrow.file`\n\nIf no Content-Type header is provided, defaults to CSV format.","operationId":"publish_sensors_data","requestBody":{"description":"Sensor data in SenML JSON, CSV, or Apache Arrow format","content":{"text/plain":{"schema":{"type":"string"}}},"required":true},"responses":{"200":{"description":"Data ingested successfully","content":{"text/plain":{"schema":{"type":"string"}}}},"400":{"description":"Bad Request - invalid data format","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppError"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppError"}}}}}}},"/series":{"get":{"tags":["SensApp"],"summary":"List all series (time series) in DCAT catalog format.","operationId":"list_series","parameters":[{"name":"metric","in":"query","description":"Filter series by metric name","required":false,"schema":{"type":"string"}},{"name":"selector","in":"query","description":"PromQL-style label selector (e.g., '{env=\"prod\",region=~\"us.*\"}')","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Time series catalog in DCAT format","content":{"application/json":{"schema":{}}}}}}},"/series/{series_uuid}":{"get":{"tags":["SensApp"],"summary":"Get series data in various formats based on query parameter.","operationId":"get_series_data","parameters":[{"name":"series_uuid","in":"path","description":"UUID of the series","required":true,"schema":{"type":"string"}},{"name":"format","in":"query","description":"Output format: senml, csv, or jsonl (default: senml)","required":false,"schema":{"type":"string"}},{"name":"start","in":"query","description":"Start datetime in ISO 8601 format (e.g., '2024-01-15T10:30:00Z')","required":false,"schema":{"type":"string"}},{"name":"end","in":"query","description":"End datetime in ISO 8601 format (e.g., '2024-01-15T11:00:00Z')","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Maximum number of samples (default: 10,000,000)","required":false,"schema":{"type":"integer","minimum":0}}],"responses":{"200":{"description":"Series data in requested format","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid format"},"404":{"description":"Series not found"}}}}},"components":{"schemas":{"AppError":{"oneOf":[{"type":"object","required":["InternalServerError"],"properties":{"InternalServerError":{"type":"string"}},"example":"Internal Server Error"},{"type":"object","required":["BadRequest"],"properties":{"BadRequest":{"type":"string"}},"example":"Bad Request"},{"type":"object","required":["NotFound"],"properties":{"NotFound":{"type":"string"}},"example":"Not Found"},{"type":"object","required":["Unauthorized"],"properties":{"Unauthorized":{"type":"string"}},"example":"Unauthorized"},{"type":"object","required":["Forbidden"],"properties":{"Forbidden":{"type":"string"}},"example":"Forbidden"},{"type":"object","required":["Storage"],"properties":{"Storage":{"type":"string"}},"example":"Storage Error"}]},"HealthResponse":{"type":"object","required":["status"],"properties":{"status":{"type":"string"}}},"ReadinessResponse":{"type":"object","required":["status","database"],"properties":{"database":{"type":"string"},"error":{"type":["string","null"]},"status":{"type":"string"}}}}},"tags":[{"name":"SensApp","description":"SensApp API"},{"name":"InfluxDB","description":"InfluxDB Write API"},{"name":"Observability","description":"Prometheus-compatible service metrics"},{"name":"Prometheus","description":"Prometheus Remote Write and Read API"},{"name":"Admin","description":"Administrative operations"},{"name":"Health","description":"Health check endpoints"}]}