Analytics API
HTTP API reference for the QueryPilot Analytics management endpoints.
Overview
Analytics (binary querypilot-analytics) serves an HTTP management API on the [server] api_bind address, default 127.0.0.1:8080. The shipped deployment configs move it to port 18080. The API is unauthenticated; keep it on loopback or a private network (see Security).
The examples below assume the default 127.0.0.1:8080. Errors return JSON with an error field.
Health and status
GET /api/health
Liveness check. The shipped container healthcheck probes this endpoint.
curl http://127.0.0.1:8080/api/health{ "status": "ok" }GET /api/status
Server status: replication phase and position, the active snapshot strategy, table count, and live snapshot progress. replication.phase is stopped when the replicator is not running, otherwise a phase such as snapshotting or streaming. parquet_readers and parquet_writers appear only for the parquet strategies and show the resolved (post auto-detect) counts. The snapshot object appears only while snapshotting; snapshots lists per-table live progress and is empty when no snapshots are in flight.
curl http://127.0.0.1:8080/api/status{
"status": "ok",
"replication": {
"phase": "streaming",
"position": "0/1A2B3C4D",
"snapshot_strategy": "appender"
},
"tables_count": 3
}GET /api/snapshot/:table
Live snapshot progress for one table, mirroring what the periodic progress log emits (rows done, estimated total, throughput, phase). Returns 404 when no snapshot is in flight for that table. Useful for polling one table without scanning the full /api/status response.
curl http://127.0.0.1:8080/api/snapshot/ordersTables
GET /api/tables
List tables in the replication filter, sorted.
curl http://127.0.0.1:8080/api/tables{ "tables": ["orders", "users"] }POST /api/tables
Add a table to replication at runtime. The table is added to the filter, then snapshotted; the call waits for the snapshot to complete, up to 300 seconds. Responses:
200withadded: trueand a row count on success200withadded: falsewhen the table is already replicated400when the table has no primary key (CDC requires one for UPDATE and DELETE support); the table is removed from the filter again504when the snapshot exceeds the 300 second timeout; the table stays in the filter but may not have complete data
curl -X POST http://127.0.0.1:8080/api/tables \
-H 'Content-Type: application/json' \
-d '{"table": "products"}'{
"status": "ok",
"table": "products",
"added": true,
"message": "Table snapshotted successfully (150000 rows)"
}DELETE /api/tables/:name
Remove a table from the replication filter. Returns 404 if the table is not in the filter. The DuckDB table and its data are left in place; only future CDC events stop applying.
curl -X DELETE http://127.0.0.1:8080/api/tables/products{
"status": "ok",
"table": "products",
"removed": true
}Configuration
GET /api/config/status
Report the config file path, load time, last reload attempt, the current log level, and which keys are reloadable versus restart-only.
curl http://127.0.0.1:8080/api/config/status{
"config_file": "/etc/sqp/querypilot-analytics.toml",
"loaded_at": "2026-07-18T11:00:00Z",
"current": { "log_level": "info" },
"reloadable": ["logging.level"],
"requires_restart": [
"server.bind",
"server.api_bind",
"duckdb.database_path",
"duckdb.memory_limit",
"duckdb.threads",
"replicator.*"
]
}POST /api/config/reload
Re-read the config file from disk. Only logging.level is applied at runtime; every other change requires a restart. A file that fails to parse, or an invalid log filter, returns 400 and leaves the running config untouched.
curl -X POST http://127.0.0.1:8080/api/config/reload{
"success": true,
"reloaded_at": "2026-07-18T12:00:00Z",
"changes": {
"log_level_changed": true,
"new_log_level": "debug"
}
}