System

Service discovery, health, diagnostics and updates.

22 endpoints · Plakar Control Plane v0.19 · Base URL, authentication and errors

Describe the deployment

GET /api/v1/
No authentication
Returns the version and, to a caller who may read the control plane, the deployment quota and usage.

Response 200 OK application/json

  • enrolled boolean
  • license object nullable
    • expires_at string<date-time>
    • identity_id string<uuid>
    • issued_at string<date-time>
    • mode string nullable
    • organization_id string<uuid>
    • plan string
    • quota_hard integer<int64>
    • quota_soft integer<int64>
  • name string
  • replication object nullable
    • lag_seconds number<double> nullable
    • last_sync_at string<date-time> nullable
    • primary_url string nullable
    • role string
  • stored_bytes integer nullable
    Max: 1.8446744073709552e+19
  • version string

Errors

  • 400 Bad Request (validation or deserialization error)
  • 500 Internal Server Error (panics)

Every error returns the standard error body.

Request

curl 'https://pcp.example.com/api/v1/'

Response 200

{
  "enrolled": true,
  "license": {
    "expires_at": "2026-01-01T00:00:00Z",
    "identity_id": "3f1e4a2c-9b7d-4e0f-8a11-2c5d6e7f8a90",
    "issued_at": "2026-01-01T00:00:00Z",
    "mode": "string",
    "organization_id": "3f1e4a2c-9b7d-4e0f-8a11-2c5d6e7f8a90",
    "plan": "string",
    "quota_hard": 0,
    "quota_soft": 0
  },
  "name": "string",
  "replication": {
    "lag_seconds": 0,
    "last_sync_at": "2026-01-01T00:00:00Z",
    "primary_url": "string",
    "role": "string"
  },
  "stored_bytes": 0,
  "version": "string"
}

Get the appliance hardware specs

GET /api/v1/appliance/specs
No authentication
Returns the CPU, memory, disks and data filesystem of the host, as reported by the orkestrator. Anonymous until the instance is enrolled, then a badge is required. The CPU, memory and disks are only returned to a caller who may read the control plane. Answers 501 when the orkestrator does not provide them.

Response 200 OK application/json

  • cpu object nullable
    • count integer
    • model string nullable
  • data object
    • free_bytes integer
      Max: 1.8446744073709552e+19
    • fs_type string
    • persistent boolean
    • size_bytes integer
      Max: 1.8446744073709552e+19
  • disks array[object] nullable
    • model string nullable
    • name string
    • size_bytes integer
      Max: 1.8446744073709552e+19
  • memory object nullable
    • available_bytes integer
      Max: 1.8446744073709552e+19
    • total_bytes integer
      Max: 1.8446744073709552e+19
  • warnings array[string]

Errors

  • 400 Bad Request (validation or deserialization error)
  • 500 Internal Server Error (panics)

Every error returns the standard error body.

Request

curl 'https://pcp.example.com/api/v1/appliance/specs'

Response 200

{
  "cpu": {
    "count": 0,
    "model": "string"
  },
  "data": {
    "free_bytes": 0,
    "fs_type": "string",
    "persistent": true,
    "size_bytes": 0
  },
  "disks": [
    {
      "model": "string",
      "name": "string",
      "size_bytes": 0
    }
  ],
  "memory": {
    "available_bytes": 0,
    "total_bytes": 0
  },
  "warnings": [
    "string"
  ]
}

Download a database dump

GET /api/v1/database/dump
Badge

Query parameters

  • format string
    Dump encoding.
    Allowed: sql, gzip, gz, zip Default: "sql"

Response 200 The database dump application/gzip

Errors

  • 400 Bad Request (validation or deserialization error)
  • 401 Missing, invalid or expired credentials
  • 403 The caller may not do this
  • 500 Internal Server Error (panics)

Every error returns the standard error body.

Request

curl 'https://pcp.example.com/api/v1/database/dump' \
  -H 'Authorization: Bearer <badge>'

Get the debug log state

GET /api/v1/debuglog
Badge

Response 200 OK application/json

  • enabled boolean

Errors

  • 400 Bad Request (validation or deserialization error)
  • 401 Missing, invalid or expired credentials
  • 403 The caller may not do this
  • 500 Internal Server Error (panics)

Every error returns the standard error body.

Request

curl 'https://pcp.example.com/api/v1/debuglog' \
  -H 'Authorization: Bearer <badge>'

Response 200

{
  "enabled": true
}

Turn the debug log on or off

PUT /api/v1/debuglog
Badge

Request body application/json required

  • enabled boolean
  • revert_after_seconds integer

Response 200 OK application/json

  • enabled boolean

Errors

  • 400 Bad Request (validation or deserialization error)
  • 401 Missing, invalid or expired credentials
  • 403 The caller may not do this
  • 500 Internal Server Error (panics)

Every error returns the standard error body.

Request

curl -X PUT 'https://pcp.example.com/api/v1/debuglog' \
  -H 'Authorization: Bearer <badge>' \
  -H 'Content-Type: application/json' \
  -d '{
  "enabled": true,
  "revert_after_seconds": 0
}'

Response 200

{
  "enabled": true
}

Check whether an update is available

GET /api/v1/has-update
Badge

Response 200 OK application/json

  • current_version string
  • description string
  • has_update boolean
  • next_version string

Errors

  • 400 Bad Request (validation or deserialization error)
  • 401 Missing, invalid or expired credentials
  • 403 The caller may not do this
  • 500 Internal Server Error (panics)

Every error returns the standard error body.

Request

curl 'https://pcp.example.com/api/v1/has-update' \
  -H 'Authorization: Bearer <badge>'

Response 200

{
  "current_version": "string",
  "description": "string",
  "has_update": true,
  "next_version": "string"
}

Ping the control plane

POST /api/v1/janitor/ping
No authentication
Always answers. The janitor’s ping task polls it.

Response 200 OK application/json

  • pong boolean

Errors

  • 400 Bad Request (validation or deserialization error)
  • 500 Internal Server Error (panics)

Every error returns the standard error body.

Request

curl -X POST 'https://pcp.example.com/api/v1/janitor/ping'

Response 200

{
  "pong": true
}

Replace the instance license

PUT /api/v1/license
Badge
Installs a freshly issued offline license. It must verify against the builtin offline keys and be minted for the enrolled organization. Owner only.

Request body application/json required

  • license string required

Response 200 OK application/json

  • expires_at string<date-time>
  • identity_id string<uuid>
  • issued_at string<date-time>
  • mode string nullable
  • organization_id string<uuid>
  • plan string
  • quota_hard integer<int64>
  • quota_soft integer<int64>

Errors

  • 400 Bad Request (validation or deserialization error)
  • 401 Missing, invalid or expired credentials
  • 403 The caller may not do this
  • 500 Internal Server Error (panics)

Every error returns the standard error body.

Request

curl -X PUT 'https://pcp.example.com/api/v1/license' \
  -H 'Authorization: Bearer <badge>' \
  -H 'Content-Type: application/json' \
  -d '{
  "license": "string"
}'

Response 200

{
  "expires_at": "2026-01-01T00:00:00Z",
  "identity_id": "3f1e4a2c-9b7d-4e0f-8a11-2c5d6e7f8a90",
  "issued_at": "2026-01-01T00:00:00Z",
  "mode": "string",
  "organization_id": "3f1e4a2c-9b7d-4e0f-8a11-2c5d6e7f8a90",
  "plan": "string",
  "quota_hard": 0,
  "quota_soft": 0
}

Download the daemon log for a day

GET /api/v1/logs
Badge

Query parameters

  • date string<date-time>
    Day whose log to return. Defaults to today.

Response 200 The gzipped daemon log application/gzip

Errors

  • 400 Bad Request (validation or deserialization error)
  • 401 Missing, invalid or expired credentials
  • 403 The caller may not do this
  • 500 Internal Server Error (panics)

Every error returns the standard error body.

Request

curl 'https://pcp.example.com/api/v1/logs' \
  -H 'Authorization: Bearer <badge>'

Enroll a replica

POST /api/v1/replication/enroll
No authentication
Exchanges the replication enrollment key in the body for a per-replica bearer token, returned once. Refused with 409 when the replica’s schema version is not the primary’s.

Request body application/json required

  • enrollment_key string required
  • name string required
  • public_key string required
  • schema_version integer
  • version string required

Response 200 OK application/json

  • replica_id string<uuid>
  • schema_version integer
  • token string
  • version string

Errors

  • 400 Bad Request (validation or deserialization error)
  • 500 Internal Server Error (panics)

Every error returns the standard error body.

Request

curl -X POST 'https://pcp.example.com/api/v1/replication/enroll' \
  -H 'Content-Type: application/json' \
  -d '{
  "enrollment_key": "string",
  "name": "string",
  "public_key": "string",
  "schema_version": 0,
  "version": "string"
}'

Response 200

{
  "replica_id": "3f1e4a2c-9b7d-4e0f-8a11-2c5d6e7f8a90",
  "schema_version": 0,
  "token": "string",
  "version": "string"
}

Generate a replication enrollment key

POST /api/v1/replication/enrollment-key/generate
Badge
Writes a fresh key into the replication settings section and returns the section. Read and clear it through the settings endpoints.

Response 200 OK application/json

  • alerting object nullable
    • email string
  • auth object nullable
    • api_key_rotation_grace_hours integer
    • api_key_rotation_ttl_days integer
    • badge_ttl_seconds integer
  • edge object nullable
    • enrollment_key string
  • logs object nullable
    • retention_days integer nullable
  • mailer object nullable
    • from_address string
    • host string
    • password string
    • port integer
    • tls boolean
    • username string
  • packages object nullable
    • repository_url string
  • replication object nullable
    • enrollment_key string
  • retention object nullable
    • min_versions integer nullable
  • security object nullable
    • mfa_enforced boolean
  • sso object nullable
    • providers array[object]
      • domains array[string]
      • provider string
  • vector object nullable
    • address string
  • webhook object nullable
    • auth_type string
    • enabled boolean
    • events map[array[string]]
    • secret string
    • url string

Errors

  • 400 Bad Request (validation or deserialization error)
  • 401 Missing, invalid or expired credentials
  • 403 The caller may not do this
  • 500 Internal Server Error (panics)

Every error returns the standard error body.

Request

curl -X POST 'https://pcp.example.com/api/v1/replication/enrollment-key/generate' \
  -H 'Authorization: Bearer <badge>'

Response 200

{
  "alerting": {
    "email": "string"
  },
  "auth": {
    "api_key_rotation_grace_hours": 0,
    "api_key_rotation_ttl_days": 0,
    "badge_ttl_seconds": 0
  },
  "edge": {
    "enrollment_key": "string"
  },
  "logs": {
    "retention_days": 0
  },
  "mailer": {
    "from_address": "string",
    "host": "string",
    "password": "string",
    "port": 0,
    "tls": true,
    "username": "string"
  },
  "packages": {
    "repository_url": "string"
  },
  "replication": {
    "enrollment_key": "string"
  },
  "retention": {
    "min_versions": 0
  },
  "security": {
    "mfa_enforced": true
  },
  "sso": {
    "providers": [
      {
        "domains": [
          "string"
        ],
        "provider": "string"
      }
    ]
  },
  "vector": {
    "address": "string"
  },
  "webhook": {
    "auth_type": "string",
    "enabled": true,
    "events": {
      "key": [
        "string"
      ]
    },
    "secret": "string",
    "url": "string"
  }
}

Promote this replica

POST /api/v1/replication/promote
Badge
Turns this passive slave into the active control plane: binds the instance identity to this instance’s key and stamps the promotion. One-way. The daemon must then be restarted to boot active. Refused with 409 when not enrolled, never swept, or already promoted.

Response 200 OK application/json

  • promoted_at string<date-time>
  • report string
  • restart_required boolean

Errors

  • 400 Bad Request (validation or deserialization error)
  • 401 Missing, invalid or expired credentials
  • 403 The caller may not do this
  • 500 Internal Server Error (panics)

Every error returns the standard error body.

Request

curl -X POST 'https://pcp.example.com/api/v1/replication/promote' \
  -H 'Authorization: Bearer <badge>'

Response 200

{
  "promoted_at": "2026-01-01T00:00:00Z",
  "report": "string",
  "restart_required": true
}

List the enrolled replicas

GET /api/v1/replication/replicas
Badge

Query parameters

  • offset integer
    Number of items to skip.
    Default: 0
  • limit integer
    Maximum number of items to return.
    Default: 100 Min: 1 Max: 100

Response 200 OK application/json

  • items array[object]
    • created_at string<date-time>
    • id string<uuid>
    • last_seen string<date-time> nullable
    • name string
    • public_key string
    • schema_version integer
    • version string
  • total integer

Errors

  • 400 Bad Request (validation or deserialization error)
  • 401 Missing, invalid or expired credentials
  • 403 The caller may not do this
  • 500 Internal Server Error (panics)

Every error returns the standard error body.

Request

curl 'https://pcp.example.com/api/v1/replication/replicas' \
  -H 'Authorization: Bearer <badge>'

Response 200

{
  "items": [
    {
      "created_at": "2026-01-01T00:00:00Z",
      "id": "3f1e4a2c-9b7d-4e0f-8a11-2c5d6e7f8a90",
      "last_seen": "2026-01-01T00:00:00Z",
      "name": "string",
      "public_key": "string",
      "schema_version": 0,
      "version": "string"
    }
  ],
  "total": 0
}

Revoke a replica

DELETE /api/v1/replication/replicas/{replica_id}
Badge
The replica’s token stops authenticating at once; the slave itself is untouched.

Path parameters

  • replica_id string required

Response 204 No Content

No response body.

Errors

  • 400 Bad Request (validation or deserialization error)
  • 401 Missing, invalid or expired credentials
  • 403 The caller may not do this
  • 500 Internal Server Error (panics)

Every error returns the standard error body.

Request

curl -X DELETE 'https://pcp.example.com/api/v1/replication/replicas/{replica_id}' \
  -H 'Authorization: Bearer <badge>'

List the replicated tables

GET /api/v1/replication/tables
replica
The sweep’s table of contents: every replicated table with its key columns, and the primary’s schema version.

Response 200 OK application/json

  • tables array[object]
    • keys array[string]
    • name string
  • version integer

Errors

  • 400 Bad Request (validation or deserialization error)
  • 401 Missing, invalid or expired credentials
  • 403 The caller may not do this
  • 500 Internal Server Error (panics)

Every error returns the standard error body.

Request

curl 'https://pcp.example.com/api/v1/replication/tables'

Response 200

{
  "tables": [
    {
      "keys": [
        "string"
      ],
      "name": "string"
    }
  ],
  "version": 0
}

Read a page of a replicated table

GET /api/v1/replication/tables/{name}
replica
Rows as JSON objects, ordered by key. next_offset is set while another page follows.

Path parameters

  • name string required

Query parameters

  • offset integer
    Number of items to skip.
    Default: 0
  • limit integer
    Maximum number of items to return.
    Default: 500 Min: 1 Max: 500

Response 200 OK application/json

  • next_offset integer nullable
  • rows array

Errors

  • 400 Bad Request (validation or deserialization error)
  • 401 Missing, invalid or expired credentials
  • 403 The caller may not do this
  • 500 Internal Server Error (panics)

Every error returns the standard error body.

Request

curl 'https://pcp.example.com/api/v1/replication/tables/{name}'

Response 200

{
  "next_offset": 0,
  "rows": [
    {}
  ]
}

Get the safe mode state

GET /api/v1/safe-mode
Badge

Response 200 OK application/json

  • by string nullable
  • enabled boolean
  • reason string nullable
  • since string<date-time> nullable

Errors

  • 400 Bad Request (validation or deserialization error)
  • 401 Missing, invalid or expired credentials
  • 403 The caller may not do this
  • 500 Internal Server Error (panics)

Every error returns the standard error body.

Request

curl 'https://pcp.example.com/api/v1/safe-mode' \
  -H 'Authorization: Bearer <badge>'

Response 200

{
  "by": "string",
  "enabled": true,
  "reason": "string",
  "since": "2026-01-01T00:00:00Z"
}

Turn safe mode on or off

PUT /api/v1/safe-mode
Badge

Request body application/json required

  • enabled boolean
  • reason string
    Max length: 512

Response 200 OK application/json

  • by string nullable
  • enabled boolean
  • reason string nullable
  • since string<date-time> nullable

Errors

  • 400 Bad Request (validation or deserialization error)
  • 401 Missing, invalid or expired credentials
  • 403 The caller may not do this
  • 500 Internal Server Error (panics)

Every error returns the standard error body.

Request

curl -X PUT 'https://pcp.example.com/api/v1/safe-mode' \
  -H 'Authorization: Bearer <badge>' \
  -H 'Content-Type: application/json' \
  -d '{
  "enabled": true,
  "reason": "string"
}'

Response 200

{
  "by": "string",
  "enabled": true,
  "reason": "string",
  "since": "2026-01-01T00:00:00Z"
}

Update the control plane to the latest version

POST /api/v1/update
Badge

Request body application/json required

  • next_version string

Response 200 OK application/json

  • task_id string<uuid>

Errors

  • 400 Bad Request (validation or deserialization error)
  • 401 Missing, invalid or expired credentials
  • 403 The caller may not do this
  • 500 Internal Server Error (panics)

Every error returns the standard error body.

Request

curl -X POST 'https://pcp.example.com/api/v1/update' \
  -H 'Authorization: Bearer <badge>' \
  -H 'Content-Type: application/json' \
  -d '{
  "next_version": "string"
}'

Response 200

{
  "task_id": "3f1e4a2c-9b7d-4e0f-8a11-2c5d6e7f8a90"
}

Check liveness

GET /health
No authentication

Response 200 OK

No response body.

Errors

  • 400 Bad Request (validation or deserialization error)
  • 500 Internal Server Error (panics)

Every error returns the standard error body.

Request

curl 'https://pcp.example.com/health'

Check readiness

GET /health/ready
No authentication
Answers 503 while the database does not.

Response 200 Ready application/json

  • status string

Errors

  • 400 Bad Request (validation or deserialization error)
  • 500 Internal Server Error (panics)
  • 503 Not ready

Every error returns the standard error body.

Request

curl 'https://pcp.example.com/health/ready'

Response 200

{
  "status": "string"
}

Check replication

GET /health/replication
No authentication
Reports the replication role and sync freshness.

Response 200 OK application/json

Errors

  • 400 Bad Request (validation or deserialization error)
  • 500 Internal Server Error (panics)

Every error returns the standard error body.

Request

curl 'https://pcp.example.com/health/replication'

Response 200

{}