Synadia Insights

API

Insights exposes a programmatic API over NATS request/reply using NATS micro. The API starts automatically whenever a sink connection is available and provides the same query capabilities that power the web UI.

Any NATS client connected to the same server (or cluster) can issue requests to these endpoints. This enables automation, integration with external tooling, and headless operation without the web UI.

Service Info

The API registers as a NATS micro service named insights with version 0.0.1. You can discover it using the standard micro service discovery subjects ($SRV.INFO, $SRV.PING, etc.).

Subject Hierarchy

All API subjects use the $INS prefix and follow a $INS.{domain}.{action} convention:

DomainSubjectDescription
db$INS.db.querySQL query execution
db$INS.db.backupDatabase backup
checks$INS.checks.listList audit checks
checks$INS.checks.infoFull metadata for one check
checks$INS.checks.findingsRun a check and return rows

The first token after $INS identifies the domain, the second the action. That makes subjects predictable and easy to authorize with NATS subject permissions (for example, grant $INS.db.> for all database operations).

Versioning

The API doesn't currently encode a version in the subject hierarchy. When breaking changes happen, consumers should include an Insights-Api-Version header (for example, Insights-Api-Version: 2). Requests without the header get current behavior.

Endpoints

Query: $INS.db.query

Execute arbitrary read-only SQL queries against the DuckDB database.

Request:

{
  "sql": "SELECT * FROM hx.server_ident LIMIT 10",
  "params": []
}
FieldTypeRequiredDescription
sqlstringyesSQL query to execute. Must be read-only (SELECT, WITH, EXPLAIN)
paramsarraynoPositional parameters for parameterized queries

Response (JSON, default):

[
  { "name": "server-1", "cluster": "us-east", "version": "2.10.0" },
  { "name": "server-2", "cluster": "us-west", "version": "2.10.0" }
]

An array of objects, one per row, keyed by column name.

Response (CSV):

Set the Accept: text/csv header to receive results as CSV.

Errors:

CodeCondition
400Invalid JSON, missing SQL, or non-read-only query
500Internal server error

Example using nats CLI:

nats req '$INS.db.query' '{"sql": "SELECT count(*) as n FROM hx.server_ident"}'

Checks List: $INS.checks.list

Returns all audit checks grouped by category, including configurable parameters.

Request: Empty payload.

Response:

[
  {
    "label": "Server Health",
    "checks": [
      {
        "code": "SERVER_003",
        "name": "High CPU Usage",
        "description": "Server CPU usage exceeds threshold",
        "scope": "server",
        "optimization": false,
        "params": [
          {
            "name": "cpu_percent",
            "default": 90.0,
            "resolved": 90.0,
            "description": "CPU usage threshold percentage"
          }
        ]
      }
    ]
  }
]

Checks Info: $INS.checks.info

Return full metadata for a single check, including its description, severity, scope, and configurable parameters with default and resolved (currently in-effect) values.

Request:

{ "code": "SERVER_003" }
FieldTypeRequiredDescription
codestringyesCheck code (e.g., SERVER_003)

Response:

{
  "code": "SERVER_003",
  "name": "High CPU Usage",
  "description": "Server CPU usage exceeds threshold",
  "scope": "server",
  "severity": "warning",
  "category": "Performance",
  "optimization": false,
  "params": [
    {
      "name": "cpu_percent",
      "default": 90.0,
      "resolved": 90.0,
      "description": "CPU usage threshold percentage"
    }
  ]
}

Errors:

CodeCondition
400Missing check code
404Unknown check code
500Internal server error

Checks Findings: $INS.checks.findings

Execute a specific check by code and return matching results.

Request:

{
  "code": "SERVER_003",
  "time": {
    "duration": "1h"
  },
  "page": 1
}
FieldTypeRequiredDescription
codestringyesCheck code (e.g., SERVER_003)
timeobjectnoTime parameters with duration
pageintnoPage number for pagination

Response (JSON, default):

{
  "rows": [
    {
      "code": "SERVER_003",
      "severity": "warning",
      "entity": "server-1",
      "entity_pk": "NABC123",
      "check_name": "High CPU Usage",
      "cpu_percent": 92.3
    }
  ],
  "page_info": {
    "page": 1,
    "total_pages": 1,
    "total_rows": 2
  }
}

Response (CSV): Set Accept: text/csv header.

Errors:

CodeCondition
400Missing check code or invalid duration
404Unknown check code
500Internal server error

Backup: $INS.db.backup

Create a transactionally consistent DuckDB backup. The backup captures all tables in the hx schema, pinned to a consistent epoch to avoid partial data from concurrent indexing.

Request:

{
  "start_epoch": "2024-01-01T00:00:00Z",
  "end_epoch": "2024-01-02T00:00:00Z",
  "upload": true,
  "retain": false
}
FieldTypeRequiredDescription
start_epochstring (RFC 3339)noStart of epoch range to include. Omit for full backup
end_epochstring (RFC 3339)noEnd of epoch range to include. Omit for full backup
uploadboolnoUpload the backup to a NATS object store (insights-backups bucket)
retainboolnoWhen upload is true, keep the local file after uploading. Default removes it

All fields are optional. With an empty payload {}, a full backup is created locally.

Response:

{
  "filename": "insights-backup-20240115-093045.db",
  "size": 52428800,
  "duration": "1.234s",
  "tables": 24,
  "object_name": "insights-backup-20240115-093045.db",
  "bucket": "insights-backups"
}
FieldDescription
filenameLocal filename (empty when uploaded without retain)
sizeBackup file size in bytes
durationTime taken to create the backup
tablesNumber of tables backed up
object_nameObject store key (present when upload is true)
bucketObject store bucket name (present when upload is true)

Only one backup can run at a time. A concurrent request returns a 409 error.

Errors:

CodeCondition
400Invalid request JSON
409Backup already in progress
500Internal server error

The object store TTL is controlled by the backup.object-store-ttl configuration option.

Error Handling

All endpoints return errors using the NATS micro error format:

  • Code. A string error code (HTTP-style: 400, 404, 500, and so on).
  • Description. A human-readable error message.
  • Data. Optional additional context (JSON bytes).

Internal errors get masked with a generic 500 / "internal server error" response, so implementation details don't leak.

Content Negotiation

The db.query and checks.findings endpoints support content negotiation via the NATS message Accept header:

  • application/json (default). Results as a JSON array/object.
  • text/csv. Results as CSV with a header row.
Previous
CLI