Data Maintenancev7.0.20
The housekeeping side of the appliance database — how long each row-retention table keeps its data, how the dated partitions of the high-volume log tables are listed and pruned, and how the per-service tuning values (“dvars”) are read and written.
The appliance database does its own housekeeping only up to a point: row-retention tables expire automatically, the partitioned log tables are pruned by hand, and the daemons’ tuning values sit behind a super-admin gate. These endpoints are where all three are read and adjusted.
These endpoints belong to the system functional area; an MCP or OAuth token needs the mcp:system scope, and the calling user needs the permission shown on each endpoint. Most endpoints here require permission:system; the per-service tuning endpoints (/api/daemon/*) are super-admin only and require permission:sa.
Two cross-cutting points apply to the whole chapter:
- Retention vs. partitions are two different mechanisms. Row-retention tables (disk, latency, interface, ports, and the alert/speedtest/discovery janitors) expire old rows automatically against the per-table retention policy. The four high-volume partitioned log tables (syslog, event log, EVE, and walk history) do not auto-expire in this release — they are pruned only by an operator through the partition-management endpoints, by an explicit number of weeks.
- Response envelope. The retention and partition endpoints wrap their payload in a
{status, hasError, message}object, wheremessagecarries the actual data (or an error string whenhasErroristrue). The per-service tuning endpoints return bare JSON objects instead. Each endpoint below shows its real shape.
Data retention
The data-retention policy drives the “Database Retention” card in the appliance UI: one row per managed table, each with a retention value (in days) that the database janitor uses to expire old rows. Only row-retention tables appear here — the partitioned log tables are not part of this policy and are managed separately (see Partition management).
List the retention policy
GET/api/getRetentionPolicysystem
Returns every managed table together with its current retention value and the table’s total on-disk size in bytes. Use this to render or audit the retention configuration.
Response 200
{
"status": 201,
"hasError": false,
"message": [
{ "id": 1, "table": "disk", "retention": 30, "size": 41992192 },
{ "id": 2, "table": "latency", "retention": 30, "size": 10780672 }
]
}
The status field in the body reads 201 on success and false on error — it is a body field, not the HTTP status code (which is always 200). When an error occurs the body is {"status": false, "hasError": true, "message": "<error text>"}.
Example
curl -sS https://APPLIANCE/api/getRetentionPolicy \
-H "Authorization: Bearer $TOKEN"
Update retention values
POST/api/setRetentionPolicysystem
Updates the retention (in days) for one or more managed tables. Send an array of {id, retention} objects under data; each id must match an existing policy row and each retention must be at least 1. The whole submission is rejected if any row fails validation.
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
data | array | yes | Array of policy rows to update. |
data[].id | integer | yes | Policy row id (≥ 1), from the list endpoint. |
data[].retention | integer | yes | Days to retain (≥ 1). |
Response 200
{ "status": 201, "hasError": false, "message": "ok" }
Errors
| Status | Body | When |
|---|---|---|
200 | {"status":false,"hasError":true,"message":"ID and Retention required, greater than 0."} | An id or retention was below 1. |
200 | {"status":false,"hasError":true,"message":"Didnt get the data i wanted."} | data was not an array. |
Example
curl -sS -X POST https://APPLIANCE/api/setRetentionPolicy \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"data":[{"id":1,"retention":60},{"id":2,"retention":45}]}'
Partition management
The high-volume log tables (syslog, event log, EVE, and walk history) are stored as weekly date-range partitions of a parent table. These endpoints let an operator inspect the partition layout, prune old partitions by age, move data between tablespaces, and inspect or change the per-table rotation schedule. Pruning is the only way these tables shed data this release — there is no automatic expiry.
Every partition endpoint accepts both a short and a long form of its table/partition argument for backward compatibility (table or tableName; partition or partitionName; tablespace or tablespaceName; schedule or cronSchedule). Supply either — the long form takes precedence when both are present.
List partitioned tables
GET/api/getPartitionedTablessystem
Returns the names of every partitioned parent table, the starting point for any partition-management workflow.
Response 200
{ "status": 200, "hasError": false, "message": ["syslog_log", "eventlog_log", "eve_log", "walks_log"] }
Example
curl -sS https://APPLIANCE/api/getPartitionedTables \
-H "Authorization: Bearer $TOKEN"
List a table’s partitions
POST/api/getTablePartitionssystem
Lists every partition of a single table, with a human-readable size, the covered date range, whether it is the live (_latest) partition, and its tablespace.
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
table / tableName | string | yes | Parent table name (one of either field). |
Response 200
{
"status": 200,
"hasError": false,
"message": [
{
"partition_name": "syslog_log_2026_06_07",
"size": "128.4 MB",
"size_bytes": 134638592,
"date_range": "From 2026-06-07 to 2026-06-14",
"is_latest": false,
"tablespace": "default"
}
]
}
Errors
| Status | Body | When |
|---|---|---|
422 | {"status":false,"hasError":true,"message":"Validation failed","errors":{...}} | Neither table nor tableName was supplied. |
Example
curl -sS -X POST https://APPLIANCE/api/getTablePartitions \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"tableName":"syslog_log"}'
Rotate a partition
POST/api/rotatePartitionsystem
Rolls the table’s live _latest partition over to a dated partition and creates a fresh _latest to receive new rows. This is housekeeping only — rotation never deletes data.
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
table / tableName | string | yes | Parent table name. |
Response 200
{ "status": 200, "hasError": false, "message": "Partition rotated for syslog_log" }
Errors
| Status | Body | When |
|---|---|---|
422 | {"status":false,"hasError":true,"message":"Validation failed","errors":{...}} | Table name missing. |
400 | {"status":false,"hasError":true,"message":"Invalid table name"} | Table is not a recognized partitioned table. |
Example
curl -sS -X POST https://APPLIANCE/api/rotatePartition \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"tableName":"syslog_log"}'
Delete partitions older than N weeks
POST/api/deleteOldPartitionssystem
Drops every dated partition of a table older than the explicit weeks retention window. This is the operator-driven prune path for the partitioned log tables — there is no automatic expiry, so this (or Delete a partition below) is how these tables free disk.
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
table / tableName | string | yes | Parent table name. |
weeks | integer | yes | Keep this many weeks; drop anything older. Minimum 1. |
Response 200
{
"status": 200,
"hasError": false,
"message": "Deleted 3 partition(s) older than 8 weeks",
"details": { "deleted_count": 3, "retention_date": "2026-04-20" }
}
Errors
| Status | Body | When |
|---|---|---|
422 | {"status":false,"hasError":true,"message":"Validation failed","errors":{...}} | weeks missing/<1 or table name missing. |
400 | {"status":false,"hasError":true,"message":"Invalid table name"} | Unrecognized table. |
This permanently drops whole partitions and every row they contain. The data cannot be recovered except from a backup. Confirm the weeks value before calling.
Example
curl -sS -X POST https://APPLIANCE/api/deleteOldPartitions \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"tableName":"syslog_log","weeks":8}'
Delete a partition
POST/api/deletePartitionsystem
Drops one named partition. Use this for surgical removal when Delete partitions older than N weeks is too coarse.
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
partition / partitionName | string | yes | Exact partition name, e.g. syslog_log_2026_04_05. |
Response 200
{ "status": 200, "hasError": false, "message": "Partition syslog_log_2026_04_05 deleted" }
Errors
| Status | Body | When |
|---|---|---|
422 | {"status":false,"hasError":true,"message":"Validation failed","errors":{...}} | Partition name missing. |
400 | {"status":false,"hasError":true,"message":"Invalid partition name"} | Name failed the service-layer safety check. |
This permanently drops the named partition and all of its rows. There is no undo.
Example
curl -sS -X POST https://APPLIANCE/api/deletePartition \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"partitionName":"syslog_log_2026_04_05"}'
List available tablespaces
GET/api/getAvailableTablespacessystem
Lists the PostgreSQL tablespaces partitions can be moved to. If the database has no extra tablespaces a synthetic default entry is returned so the UI always has at least one target.
Response 200
{
"status": 200,
"hasError": false,
"message": [
{ "name": "default", "location": "system", "size": "N/A" }
]
}
Example
curl -sS https://APPLIANCE/api/getAvailableTablespaces \
-H "Authorization: Bearer $TOKEN"
Get a table’s tablespace
POST/api/getTableTablespacesystem
Returns the tablespace a table currently lives in. A table on the cluster default returns the string "default".
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
table / tableName | string | yes | Parent table name. |
Response 200
{ "status": 200, "hasError": false, "message": "default" }
Errors
| Status | Body | When |
|---|---|---|
422 | {"status":false,"hasError":true,"message":"Validation failed","errors":{...}} | Table name missing. |
400 | {"status":false,"hasError":true,"message":"Invalid table name"} | Unrecognized table. |
Example
curl -sS -X POST https://APPLIANCE/api/getTableTablespace \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"tableName":"syslog_log"}'
Move a table to a tablespace
POST/api/moveTableToTablespacesystem
Moves a table (and, by default, its indexes) to another tablespace — for example, relocating bulk log data to a larger or cheaper volume. The move rewrites the table and holds a lock while it runs, so schedule it during a maintenance window.
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
table / tableName | string | yes | Parent table name. |
tablespace / tablespaceName | string | yes | Target tablespace name. |
includeIndexes | boolean | no | Move the table’s indexes too. Defaults to true. |
Response 200
{ "status": 200, "hasError": false, "message": "Moved syslog_log to tablespace fast_ssd" }
Errors
| Status | Body | When |
|---|---|---|
422 | {"status":false,"hasError":true,"message":"Validation failed","errors":{...}} | Table or tablespace name missing. |
400 | {"status":false,"hasError":true,"message":"Invalid table name or tablespace name"} | Service-layer safety check failed. |
Example
curl -sS -X POST https://APPLIANCE/api/moveTableToTablespace \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"tableName":"syslog_log","tablespaceName":"fast_ssd","includeIndexes":true}'
Get a table’s rotation schedule
POST/api/getTableCronSchedulesystem
Returns the cron expression that drives automatic weekly partition rotation for a table.
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
table / tableName | string | yes | Parent table name. |
Response 200
{ "status": 200, "hasError": false, "message": { "schedule": "0 0 * * 0", "jobid": 7 } }
message is whatever the scheduling service returns for the table (the cron expression plus the pg_cron job id). It is null when the table has no rotation job.
Example
curl -sS -X POST https://APPLIANCE/api/getTableCronSchedule \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"tableName":"syslog_log"}'
Update a table’s rotation schedule
POST/api/updateTableCronSchedulesystem
Sets the cron expression for a table’s automatic partition rotation. The schedule controls rotation only (rolling _latest to a dated partition) — it never deletes data.
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
table / tableName | string | yes | Parent table name. |
schedule / cronSchedule | string | yes | Standard 5-field cron expression, e.g. 0 0 * * 0. |
Response 200
{ "status": 200, "hasError": false, "message": "Schedule updated for syslog_log", "jobid": 7 }
Errors
| Status | Body | When |
|---|---|---|
422 | {"status":false,"hasError":true,"message":"Validation failed","errors":{...}} | Table name or schedule missing. |
400 | {"status":false,"hasError":true,"message":"Invalid cron schedule format"} | Cron expression rejected by the service. |
Example
curl -sS -X POST https://APPLIANCE/api/updateTableCronSchedule \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"tableName":"syslog_log","cronSchedule":"0 0 * * 0"}'
Daemon configuration
Each background service on the appliance carries a set of tuning values (“dvars”) plus a flag controlling whether it starts automatically. These endpoints read and write those values and let an operator turn a service’s autostart on or off. They are super-admin only.
Unlike the rest of this chapter, the daemon endpoints require permission:sa, not permission:system. They expose low-level service tuning that can affect appliance stability.
Get a service’s configuration
GET/api/daemon/{identifier}sa
Returns a single service together with its full list of tuning values. The identifier may be the numeric service id or the service name.
Path parameters
| Name | Type | Notes |
|---|---|---|
identifier | integer or string | Numeric service id, or the service name. |
Response 200
{
"id": 12,
"name": "emailmond",
"start_auto": true,
"config": [
{ "var": "interval", "value": "60" },
{ "var": "authpass", "value": { "__encrypted__": true } }
]
}
Secret tuning values (such as a mail relay password) are never returned in clear text. They are masked on read as {"__encrypted__": true}. On write, replay that exact sentinel — or leave the field blank — to keep the stored secret unchanged; only a fresh plaintext value replaces it.
Errors
| Status | Body | When |
|---|---|---|
404 | {"message":"Failed to find daemon"} | No service matches the identifier. |
Example
curl -sS https://APPLIANCE/api/daemon/emailmond \
-H "Authorization: Bearer $TOKEN"
Update a service’s configuration
POST/api/daemon/{id}/configsa
Replaces the full set of tuning values for a service, then signals the running service to reload them. Send the complete config array — it overwrites the existing values entirely.
Path parameters
| Name | Type | Notes |
|---|---|---|
id | integer | Numeric service id. |
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
config | array | yes | Full replacement list of tuning values. |
config[].var | string | yes | Tuning value name. |
config[].value | string|object | no | New value. For a secret var, send {"__encrypted__": true} (or leave blank) to keep the current secret. |
A fresh plaintext value supplied for a secret var is encrypted before storage. Replaying the {"__encrypted__": true} sentinel, or sending an empty value, preserves the stored ciphertext rather than overwriting it.
Response 200
{ "message": "Configuration updated successfully" }
This overwrites every tuning value for the service and triggers a live reload. Omitting a value that previously existed removes it. Submit the complete, intended set.
Errors
| Status | Body | When |
|---|---|---|
200 | {"message":"Configuration saved, but the daemon could not be live-reloaded: ...","reload_failed":true} | Values saved, but the running service could not be reloaded (commonly because it is not running). |
500 | {"message":"Failed to update daemon configuration"} | Validation or save error. |
Example
curl -sS -X POST https://APPLIANCE/api/daemon/12/config \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"config":[{"var":"interval","value":"30"},{"var":"authpass","value":{"__encrypted__":true}}]}'
Set a service’s autostart
POST/api/daemon/{id}/startsa
Turns a service’s automatic startup on or off. The supervisor picks the change up on its next cycle; the running service itself is not reloaded by this call.
Path parameters
| Name | Type | Notes |
|---|---|---|
id | integer | Numeric service id. |
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
start_auto | boolean | yes | true to autostart the service, false to leave it stopped. |
Response 200
{ "message": "Start auto setting updated successfully" }
Errors
| Status | Body | When |
|---|---|---|
500 | {"message":"Failed to update start auto setting"} | Validation or save error. |
Example
curl -sS -X POST https://APPLIANCE/api/daemon/12/start \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"start_auto":true}'