The module lifecycle stage: Generally available version

The module has requirements for installation

Authentication

Endpoints requiring authentication must be called with the X-Auth-Token HTTP request header containing an API token.

Metrics

Sending metrics

The following protocol is supported for sending metrics: Prometheus Remote-Write.

Example request:

POST /api/v1/push

This endpoint accepts an HTTP POST request. The request data is encoded using Protocol Buffers and compressed with Snappy. The protobuf message definition can be found in the pkg/mimirpb/mimir.proto file. The HTTP request must contain the X-Prometheus-Remote-Write-Version header with version 0.1.0.

Authentication required…

Viewing metrics

General format

Instant queries for metrics

This endpoint evaluates an instant query at a single point in time.

Example request:

GET /prometheus/api/v1/query

POST /prometheus/api/v1/query

Authentication required…

URL query parameters:

  • query=<string>: Prometheus expression query string.
  • time=<rfc3339 | unix_timestamp>: evaluation timestamp. Optional.
  • timeout=<duration>: evaluation timeout. Optional. Defaults to the value of the -query.timeout flag.

If the time parameter is omitted, the current server time is used.

You can URL-encode the query parameters directly in the request body using the POST method and the Content-Type: application/x-www-form-urlencoded header. This is useful when specifying large queries that may exceed the URL length limit.

Format of the data section in the query result:

{
  "resultType": "matrix" | "vector" | "scalar" | "string",
  "result": <value>
}

<value> refers to the query result data, the format of which depends on resultType. See expression query result formats.

Example:

Example request evaluating the expression up at the time 2015-07-01T20:10:51.781Z:

$ curl -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/prometheus/api/v1/query?query=up&time=2015-07-01T20:10:51.781Z'

Response:

{
   "status" : "success",
   "data" : {
      "resultType" : "vector",
      "result" : [
         {
            "metric" : {
               "__name__" : "up",
               "job" : "prometheus",
               "instance" : "localhost:9090"
            },
            "value": [ 1435781451.781, "1" ]
         },
         {
            "metric" : {
               "__name__" : "up",
               "job" : "node",
               "instance" : "localhost:9100"
            },
            "value" : [ 1435781451.781, "0" ]
         }
      ]
   }
}
Range queries

This endpoint evaluates an expression query over a range of time:

GET /prometheus/api/v1/query_range POST /prometheus/api/v1/query_range

Authentication required.

URL parameters:

  • query=<string>: Prometheus expression string.
  • start=<rfc3339 | unix_timestamp>: start timestamp.
  • end=<rfc3339 | unix_timestamp>: end timestamp.
  • step=<duration | float>: query resolution step width (duration format or number of seconds as a float).
  • timeout=<duration>: evaluation timeout. Optional.

Example:

Example request with the expression up over a 30-second range with 15-second resolution:

$ curl -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/prometheus/api/v1/query_range?query=up&start=2015-07-01T20:10:30.781Z&end=2015-07-01T20:11:00.781Z&step=15s'

Response:

{
   "status" : "success",
   "data" : {
      "resultType" : "matrix",
      "result" : [
         {
            "metric" : {
               "__name__" : "up",
               "job" : "prometheus",
               "instance" : "localhost:9090"
            },
            "values" : [
               [ 1435781430.781, "1" ],
               [ 1435781445.781, "1" ],
               [ 1435781460.781, "1" ]
            ]
         },
         {
            "metric" : {
               "__name__" : "up",
               "job" : "node",
               "instance" : "localhost:9091"
            },
            "values" : [
               [ 1435781430.781, "0" ],
               [ 1435781445.781, "0" ],
               [ 1435781460.781, "1" ]
            ]
         }
      ]
   }
}

Querying metadata

Deckhouse Optics provides several APIs for querying metadata about time series and their labels.

Finding series by label set

This endpoint returns a list of time series matching a certain label set:

GET /prometheus/api/v1/series POST /prometheus/api/v1/series

Authentication required…

URL parameters:

  • match[]=<series_selector>: repeated argument for the series selector that selects the returned series. At least one match[] argument must be provided.
  • start=<rfc3339 | unix_timestamp>: start timestamp.
  • end=<rfc3339 | unix_timestamp>: end timestamp.
  • limit=<number>: maximum number of returned series. Default is 0, meaning no limit.

Example:

$ curl -H "X-Auth-Token: <API-token>" \
    -g 'https://api.dop.example.com/prometheus/api/v1/series?' \
    --data-urlencode 'match[]=up' \
    --data-urlencode 'match[]=process_start_time_seconds{job="prometheus"}'

Response:

{
   "status" : "success",
   "data" : [
      { "__name__" : "up", "job" : "prometheus", "instance" : "localhost:9090" },
      { "__name__" : "up", "job" : "node", "instance" : "localhost:9091" },
      { "__name__" : "process_start_time_seconds", "job" : "prometheus", "instance" : "localhost:9090" }
   ]
}

Getting label names

This endpoint returns a list of label names:

GET /prometheus/api/v1/labels POST /prometheus/api/v1/labels

Authentication required…

Example:

$ curl -H "X-Auth-Token: <API-token>" \
    'https://api.dop.example.com/prometheus/api/v1/labels'

Response:

{
    "status": "success",
    "data": [
        "__name__",
        "call",
        "code",
        "config",
        "dialer_name",
        "endpoint",
        "event",
        "goversion",
        "handler",
        "instance",
        "interval",
        "job",
        "le",
        "listener_name",
        "name",
        "quantile",
        "reason",
        "role",
        "scrape_job",
        "slice",
        "version"
    ]
}

Getting label values

This endpoint returns a list of values for the specified label name:

GET /prometheus/api/v1/label/<label_name>/values

Authentication required…

Example:

Example request for values of the job label:

$ curl -H "X-Auth-Token: <API-token>" \
    https://api.dop.example.com/prometheus/api/v1/label/job/values

Response:

{
   "status" : "success",
   "data" : [
      "node",
      "prometheus"
   ]
}

Expression query result formats

Expression queries may return the following values in the result property of the data section. The <sample_value> placeholders are used to represent numeric values. Since JSON does not support special floating-point values such as NaN, Inf, and -Inf, sample data is transferred as quoted string values instead of numbers.

The "histogram" and "histograms" keys only appear if the response contains experimental native histograms. The <histogram> placeholder is explained in a separate section below.

Range vectors

Range vectors are returned as result type matrix. The corresponding result property has the following format:

[
  {
    "metric": { "<label_name>": "<label_value>", ... },
    "values": [ [ <unix_time>, "<sample_value>" ], ... ],
    "histograms": [ [ <unix_time>, <histogram> ], ... ]
  },
  ...
]

Each series may include a values key, a histograms key, or both. For each timestamp there will be only one sample — either of type float or of type histogram.

Series are returned sorted by metrics. Functions such as sort and sort_by_label do not affect range vectors.

Instant vectors

Instant vectors are returned as result type vector. The corresponding result property has the following format:

[
  {
    "metric": { "<label_name>": "<label_value>", ... },
    "value": [ <unix_time>, "<sample_value>" ],
    "histogram": [ <unix_time>, <histogram> ]
  },
  ...
]

Each series may contain a value key or a histogram key, but not both.

Series are not guaranteed to be in any particular order unless a function such as sort or sort_by_label was used.

Scalars

Scalar results are returned as result type scalar. The corresponding result property has the following format:

[ <unix_time>, "<scalar_value>" ]

Strings

String results are returned as result type string. The corresponding result property has the following format:

[ <unix_time>, "<string_value>" ]

Logs

Sending logs

POST /loki/api/v1/push

Authentication required…

This endpoint is used to send logs to Deckhouse Optics. By default, the POST body should be Snappy-compressed Protocol Buffer message:

These POST requests require the Content-Type: application/x-protobuf HTTP header.

Alternatively, if the Content-Type header is set to application/json, you can send the POST body in JSON format:

{
  "streams": [
    {
      "stream": {
        "label": "value"
      },
      "values": [
          [ "<Unix Timestamp in nanoseconds>", "<log line>" ],
          [ "<Unix Timestamp in nanoseconds>", "<log line>" ]
      ]
    }
  ]
}

You can set the Content-Encoding: gzip request header to send compressed JSON.

You can also attach structured metadata to each log line by adding a JSON object at the end of the log array. This object must not contain nested objects, and must contain only string keys and values. It must be specified immediately after the log line:

Example:

"values": [
    [ "<Unix Timestamp in nanoseconds>", "<log line>", {"trace_id": "0242ac120002", "user_id": "superUser123"}]
]

Examples:

Example cURL command to send a stream with the label foo=bar2 and a single log line "fizzbuzz" using JSON encoding:

curl -H "Content-Type: application/json" \
  -H "X-Auth-Token: <API-token>" \
  -s -X POST "https://api.dop.example.com/loki/api/v1/push" \
  --data-raw '{"streams": [{ "stream": { "foo": "bar2" }, "values": [ [ "1570818238000000000", "fizzbuzz" ] ] }]}'

Viewing logs

Instant queries for logs

GET /loki/api/v1/query

Authentication required…

This endpoint allows you to execute log queries for a specific point in time. Instant queries are used only for querying logs with LogQL metric queries and will return a 400 (Bad Request) error when used with log queries.

URL query parameters:

  • query: LogQL query. Queries with invalid LogQL syntax will return an error.
  • limit: Maximum number of entries to return. Default is 100. Only applies to queries that return log lines.
  • time: Query evaluation time as a Unix Timestamp in nanoseconds (or another format). Default is the current time.
  • direction: Determines the sort order of logs. Supported values: forward or backward. Default is backward.

Response format:

{
  "status": "success",
  "data": {
    "resultType": "vector" | "streams",
    "result": [<vector value>] | [<stream value>],
    "stats": [<statistics>]
  }
}

Where vector value has the format:

{
  "metric": {
    <label key-value pairs>
  },
  "value": [
    <number: second Unix Timestamp>,
    <string: value>
  ]
}

and stream value has the format:

{
  "stream": {
    <label key-value pairs>
  },
  "values": [
    [
      <string: nanosecond Unix Timestamp>,
      <string: log line>
    ],
    ...
  ]
}

Entries in the values array are sorted by timestamp. The most recent entry is first when using direction=backward. The oldest entry is first when using direction=forward.

Example:

curl -G -s -H 'X-Auth-Token: <API-token>'  "https://api.dop.example.com/loki/api/v1/query" \
  --data-urlencode 'query=sum(rate({job="varlogs"}[10m])) by (level)' | jq

Response:

{
  "status": "success",
  "data": {
    "resultType": "vector",
    "result": [
      {
        "metric": {},
        "value": [
          1588889221,
          "1267.1266666666666"
        ]
      },
      {
        "metric": {
          "level": "warn"
        },
        "value": [
          1588889221,
          "37.77166666666667"
        ]
      },
      {
        "metric": {
          "level": "info"
        },
        "value": [
          1588889221,
          "37.69"
        ]
      }
    ],
    "stats": {
      ...
    }
  }
}

Range query

GET /loki/api/v1/query_range

Authentication required…

This endpoint allows you to query logs within a specific time range. It applies to both log queries and LogQL metric queries.

URL query parameters:

  • query: LogQL query to execute.
  • limit: Maximum number of entries to return. Default is 100. Only applies to query types that return a stream (log lines).
  • start: Start time of the query as a Unix Timestamp in nanoseconds or another supported format. Default is one hour ago. Loki returns results with a timestamp greater than or equal to this value.
  • end: End time of the query, also as a Unix Timestamp in nanoseconds or another supported format. Default is the current time. Loki returns results with a timestamp less than this value.
  • since: Duration used to calculate the start relative to the end. If the end value is in the future, the start time is calculated as this duration before the current moment. Any specified value of the start parameter takes precedence over since.
  • step: Query resolution step in duration format or a floating-point number representing seconds. Duration implies Prometheus-format strings such as [0-9]+[smhdwy]. For example, 5m means a duration of 5 minutes. Default is a dynamic value based on start and end. Applies to queries that return a matrix response.
  • interval: Returns entries at no less than the specified interval, which can be set as a duration or a floating-point number of seconds. Works only for queries returning a stream. Not to be confused with the step parameter, see explanation below.
  • direction: Determines the sort order of logs. Supported values are forward (ascending) or backward (descending). Default is backward.

Response format:

{
  "status": "success",
  "data": {
    "resultType": "matrix" | "streams",
    "result": [<matrix value>] | [<stream value>],
    "stats" : [<statistics>]
  }
}

Where <matrix value> has the format:

{
  "metric": {
    <label key-value pairs>
  },
  "values": [
    [
      <number: second Unix Timestamp>,
      <string: value>
    ],
    ...
  ]
}

and <stream value> has the format:

{
  "stream": {
    <label key-value pairs>
  },
  "values": [
    [
      <string: nanosecond Unix Timestamp>,
      <string: log line>
    ],
    ...
  ]
}

Entries in the values array are sorted by timestamp: when using direction=backward, the most recent entry comes first; when using forward, the oldest entry comes first.

Examples:

curl -G -s -H 'X-Auth-Token: <API-token>' "https://api.dop.example.com/loki/api/v1/query_range" \
  --data-urlencode 'query=sum(rate({job="varlogs"}[10m])) by (level)' \
  --data-urlencode 'step=300' | jq

Response:

{
  "status": "success",
  "data": {
    "resultType": "matrix",
    "result": [
      {
       "metric": {
          "level": "info"
        },
        "values": [
          [
            1588889221,
            "137.95"
          ],
          [
            1588889221,
            "467.115"
          ],
          [
            1588889221,
            "658.8516666666667"
          ]
        ]
      },
      {
        "metric": {
          "level": "warn"
        },
        "values": [
          [
            1588889221,
            "137.27833333333334"
          ],
          [
            1588889221,
            "467.69"
          ],
          [
            1588889221,
            "660.6933333333334"
          ]
        ]
      }
    ],
    "stats": {
      ...
    }
  }
}

Query labels

GET /loki/api/v1/labels

Authentication required…

This endpoint returns a list of known labels within a time range.

URL query parameters:

  • start: Start time of the query as a Unix Timestamp in nanoseconds. Default is 6 hours ago.
  • end: End time, also as a Unix Timestamp in nanoseconds. Default is the current time.
  • since: Duration used to calculate the start relative to the end.
  • query: Log stream selector that selects the streams for which to display labels. Example: {app="myapp", environment="dev"}

Response format:

{
  "status": "success",
  "data": [
    <label string>,
    ...
  ]
}

Example:

curl -G -s -H"X-Auth-Token: <API-token>"  "https://api.dop.example.com/loki/api/v1/labels" | jq

Response:

{
  "status": "success",
  "data": [
    "foo",
    "bar",
    "baz"
  ]
}

Query label values

GET /loki/api/v1/label/<name>/values

Authentication required…

This endpoint returns a list of possible values for the label <name> within a time range.

URL query parameters:

  • start: Start time.
  • end: End time.
  • since: Duration used to calculate the start relative to the end.
  • query: Log selector for selecting streams and returning label values.

Example:

curl -G -s -H"X-Auth-Token: <API-token>"  "https://api.dop.example.com/loki/api/v1/label/foo/values" | jq

Response:

{
  "status": "success",
  "data": [
    "cat",
    "dog",
    "axolotl"
  ]
}

Traces

Sending traces

Deckhouse Optics supports receiving traces via several protocols.

Authentication required… (permission Traces: write).

OTLP HTTP

POST /otlp/v1/traces

POST /v1/traces

Send traces using the OpenTelemetry (OTLP) protocol over HTTP. The request body must contain data in OTLP JSON or OTLP Protobuf format.

Example:

curl -X POST "https://api.dop.example.com/otlp/v1/traces" \
  -H "X-Auth-Token: <API-token>" \
  -H "Content-Type: application/json" \
  --data-raw '{
    "resourceSpans": [{
      "resource": {
        "attributes": [{"key": "service.name", "value": {"stringValue": "my-service"}}]
      },
      "scopeSpans": [{
        "spans": [{
          "traceId": "5b8efff798038103d269b633813fc60c",
          "spanId": "eee19b7ec3c1b174",
          "name": "example-span",
          "kind": 1,
          "startTimeUnixNano": "1544712660000000000",
          "endTimeUnixNano": "1544712661000000000",
          "attributes": [{"key": "http.method", "value": {"stringValue": "GET"}}],
          "status": {}
        }]
      }]
    }]
  }'

OTLP gRPC

opentelemetry.proto.collector.trace.v1.TraceService/Export

Send traces using the OpenTelemetry (OTLP) protocol over gRPC.

Example:

grpcurl -H "X-Auth-Token: <API-token>" \
  -d '{"resourceSpans": [...]}' \
  api.dop.example.com:443 \
  opentelemetry.proto.collector.trace.v1.TraceService/Export

Jaeger Thrift HTTP

POST /jaeger/api/traces

Send traces using the Jaeger Thrift protocol over HTTP.

Zipkin

POST /zipkin/spans

Send traces using the Zipkin protocol.

Viewing traces

Authentication required… (permission Traces: read).

Getting a trace by identifier

GET /tempo/api/traces/{traceID}

GET /tempo/api/v2/traces/{traceID}

Returns a trace by its identifier. The v2 version returns the result in OTLP format.

Example:

curl -H "X-Auth-Token: <API-token>" \
  "https://api.dop.example.com/tempo/api/traces/5b8efff798038103d269b633813fc60c"

Searching traces

GET /tempo/api/search

GET /tempo/api/v2/search

Searches for traces based on specified parameters.

URL query parameters:

  • q=<string>: TraceQL query string. Optional.
  • tags=<string>: filter by tags in key=value format. Optional.
  • minDuration=<duration>: minimum trace duration (e.g., 1s, 100ms). Optional.
  • maxDuration=<duration>: maximum trace duration. Optional.
  • limit=<int>: maximum number of results. Optional.
  • start=<int>: start time (in seconds since Unix epoch). Optional.
  • end=<int>: end time (in seconds since Unix epoch). Optional.

Example:

curl -H "X-Auth-Token: <API-token>" \
  "https://api.dop.example.com/tempo/api/search?q=%7Bspan.http.status_code+%3E%3D+400%7D&limit=20"

Build information

GET /tempo/api/status/buildinfo

Returns version and build information for the Tempo component.

Example:

curl -H "X-Auth-Token: <API-token>" \
  "https://api.dop.example.com/tempo/api/status/buildinfo"

Triggers

Trigger parameters

  • metadata.name: trigger name, must be unique (not used by another project trigger or global trigger), lowercase Latin letters and - are allowed
  • metadata.generation: trigger version
  • metadata.resourceVersion: global trigger version
  • metadata.creationTimestamp: trigger creation date/time
  • metadata.annotations: list of trigger annotations in name-value format. Currently the trigger category annotation metadata.deckhouse.io/category is supported
  • spec.alertMetadata.annotations: arbitrary list of trigger annotations in name-value format.
  • spec.alertMetadata.additionalLabels: arbitrary list of trigger labels in name-value format.
  • spec.delays.firing: delay before trigger fires (1s, 1m, etc.)
  • spec.delays.resolving: duration of firing after resolution (1s, 1m, etc.)
  • spec.expression: trigger expression, must be a valid Prometheus expression.
  • spec.thresholds: array of firing thresholds, at least one is required.
    • valueExpression: threshold value or expression
    • operator: operator, allowed values: Equal | GreaterThan | LessThan | LessThanOrEqual | GreaterThanOrEqual | NotEqual
    • severity: severity level, allowed values: Critical | Info | Warning | Setup

Getting the list of project triggers

This endpoint returns the list of project triggers (not including global triggers).

GET /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/alertingrules

URL path parameters:

  • space_name: workspace name. Required
  • project_name: project name. Required

Authentication required… The token must have “API management” and “Triggers and recording rules” permissions

Example request:

$ curl -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/alertingrules'

Example response:

{
    "apiVersion": "observability.deckhouse.io/v1alpha1",
    "kind": "List",
    "metadata":
    {},
    "items":
    [
        {
            "apiVersion": "observability.deckhouse.io/v1alpha1",
            "kind": "ObservabilityMetricsAlertingRule",
            "metadata":
            {
                "creationTimestamp": "2024-12-11T10:38:23Z",
                "generation": 1,
                "annotations":
                {
                    "metadata.deckhouse.io/category": "Main"
                },
                "name": "rule-name",
                "resourceVersion": 1
            },
            "spec":
            {
                "alertMetadata":
                {
                    "annotations":
                    {
                        "summary": "{{ $labels.instance }} pgbouncer '{{ $labels.conf }}' configuration incomplete"
                    },
                    "additionalLabels":
                    {
                        "additional_label": "value"
                    }
                },
                "delays":
                {
                    "firing": "1m",
                    "resolving": "0s"
                },
                "expression": "job:request_latency_seconds:mean5m{job=\"myjob\"}",
                "thresholds":
                [
                    {
                        "valueExpression": "0.5",
                        "operator": "GreaterThan",
                        "severity": "Warning"
                    }
                ]
            }
        }
    ]
}

Getting a trigger

This endpoint returns a trigger by name.

GET /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/alertingrules/:name

URL path parameters:

  • space_name: workspace name. Required
  • project_name: project name. Required
  • name: trigger name. Required

Authentication required… The token must have “API management” and “Triggers and recording rules” permissions

Example request:

$ curl -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/alertingrules/:name'

Example response:

{
    "apiVersion": "observability.deckhouse.io/v1alpha1",
    "kind": "ObservabilityMetricsAlertingRule",
    "metadata":
    {
        "creationTimestamp": "2024-12-11T10:42:56Z",
        "generation": 1,
        "annotations":
        {
            "metadata.deckhouse.io/category": "Main"
        },
        "name": "test1",
        "resourceVersion": 1
    },
    "spec":
    {
        "alertMetadata":
        {
            "annotations":
            {
                "summary": "{{ $labels.instance }} pgbouncer '{{ $labels.conf }}' configuration incomplete"
            },
            "additionalLabels":
            {
                "testlabel": "value"
            }
        },
        "delays":
        {
            "firing": "1m",
            "resolving": "0s"
        },
        "expression": "job:request_latency_seconds:mean5m{job=\"myjob\"}",
        "thresholds":
        [
            {
                "valueExpression": "0.5",
                "operator": "GreaterThan",
                "severity": "Warning"
            }
        ]
    }
}

Creating a trigger

This endpoint creates a new trigger.

POST /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/alertingrules/

URL path parameters:

  • space_name: workspace name. Required
  • project_name: project name. Required

Authentication required… The token must have “API management” and “Triggers and recording rules” permissions

Example request:

$ curl -X POST -H "Content-Type: application/json" -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/alertingrules/' -d \
'
{
    "kind": "ObservabilityMetricsAlertingRule",
    "metadata":
    {
        "annotations":
        {
            "metadata.deckhouse.io/category": "critical"
        },
        "name": "some-name"
    },
    "spec":
    {
        "alertMetadata":
        {
            "annotations":
            {
                "summary": "some description summary"
            },
            "additionalLabels":
            {
                "testlabel": "value"
            }
        },
        "delays":
        {
            "firing": "1s",
            "resolving": "1s"
        },
        "expression": "vector(10)",
        "thresholds":
        [
            {
                "valueExpression": "0.5",
                "operator": "GreaterThan",
                "severity": "critical"
            }
        ]
    }
}
'  

Example response:

{
    "apiVersion": "observability.deckhouse.io/v1alpha1",
    "kind": "ObservabilityMetricsAlertingRule",
    "metadata":
    {
        "creationTimestamp": "2024-12-11T10:48:11Z",
        "generation": 1,
        "annotations":
        {
            "metadata.deckhouse.io/category": "critical"
        },
        "name": "some-name",
        "resourceVersion": 1
    },
    "spec":
    {
        "alertMetadata":
        {
            "annotations":
            {
                "summary": "some description summary"
            },
            "additionalLabels":
            {
                "testlabel": "value"
            }
        },
        "delays":
        {
            "firing": "1s",
            "resolving": "1s"
        },
        "expression": "vector(10)",
        "thresholds":
        [
            {
                "valueExpression": "0.5",
                "operator": "GreaterThan",
                "severity": "Critical"
            }
        ]
    }
}

Updating a trigger

This endpoint updates an existing trigger.

PUT api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/alertingrules/:name

URL path parameters:

  • space_name: workspace name. Required
  • project_name: project name. Required
  • name: trigger name

Authentication required… The token must have “API management” and “Triggers and recording rules” permissions

Example request:

$ curl -X PUT -H "Content-Type: application/json" -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/alertingrules/:name' -d \
'
{
    "kind": "ObservabilityMetricsAlertingRule",
    "metadata":
    {
        "annotations":
        {
            "metadata.deckhouse.io/category": "critical"
        }
    },
    "spec":
    {
        "alertMetadata":
        {
            "annotations":
            {
                "summary": "{{ $labels.instance }} pgbouncer '{{ $labels.conf }}' configuration incomplete"
            },
            "additionalLabels":
            {
                "somelabel": "value"
            }
        },
        "delays":
        {
            "firing": "2s",
            "resolving": "3s"
        },
        "expression": "vector(10)",
        "thresholds":
        [
            {
                "valueExpression": "0.5",
                "operator": "GreaterThan",
                "severity": "critical"
            }
        ]
    }
}
'  

Example response:

{
    "apiVersion": "observability.deckhouse.io/v1alpha1",
    "kind": "ObservabilityMetricsAlertingRule",
    "metadata":
    {
        "creationTimestamp": "2024-12-13T06:16:03Z",
        "generation": 1,
        "annotations":
        {
            "metadata.deckhouse.io/category": "critical"
        },
        "name": "test1",
        "resourceVersion": 1
    },
    "spec":
    {
        "alertMetadata":
        {
            "annotations":
            {
                "summary": "{{ $labels.instance }} pgbouncer '{{ $labels.conf }}' configuration incomplete"
            },
            "additionalLabels":
            {
                "somelabel": "value"
            }
        },
        "delays":
        {
            "firing": "2s",
            "resolving": "3s"
        },
        "expression": "vector(10)",
        "thresholds":
        [
            {
                "valueExpression": "0.5",
                "operator": "GreaterThan",
                "severity": "Critical"
            }
        ]
    }
}

Deleting a trigger

This endpoint deletes an existing trigger.

DELETE /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/alertingrules/:name

URL path parameters:

  • space_name: workspace name. Required
  • project_name: project name. Required
  • name: trigger name

Authentication required… The token must have “API management” and “Triggers and recording rules” permissions

Example request:

$ curl -X DELETE -H "Content-Type: application/json" -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/alertingrules/:name'

Errors when creating or updating triggers

If the request to create or update a trigger contains invalid data, the response will have a 4xx status with an error message:

{"error":"Validation failed: Name has already been taken"}

Recording Rules

Recording rule parameters

  • metadata.name: metric name, must be unique (not used by another project metric or global metric), lowercase Latin letters and - are allowed
  • metadata.generation: metric version
  • metadata.resourceVersion: global metric version
  • metadata.creationTimestamp: metric creation date/time
  • metadata.annotations: list of metric annotations in name-value format. Currently the metric category annotation metadata.deckhouse.io/category is supported
  • spec.expression: metric expression, must be a valid Prometheus expression.
  • spec.alertMetadata.targetMetric: metric parameters
    • name: metric name, lowercase Latin letters and : are allowed, example: some:metric, must be unique.
    • additionalLabels: arbitrary list of metric labels in name-value format.

Getting the list of project recording rules

This endpoint returns the list of project recording rules (not including global metrics).

GET /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/recordingrules

URL path parameters:

  • space_name: workspace name. Required
  • project_name: project name. Required

Authentication required… The token must have “API management” and “Triggers and recording rules” permissions

Example request:

$ curl -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/recordingrules'

Example response:

{
    "apiVersion": "v1",
    "kind": "List",
    "metadata": {},
    "items":
    [
        {
            "apiVersion": "observability.deckhouse.io/v1alpha1",
            "kind": "ObservabilityMetricsRecordingRule",
            "spec":
            {
                "expression": "vector(10)",
                "targetMetric":
                {
                    "name": "test:vector",
                    "additionalLabels":
                    {
                        "test": "test",
                        "author": "test"
                    }
                }
            },
            "metadata":
            {
                "creationTimestamp": "2024-12-13T06:24:30Z",
                "generation": 1,
                "annotations":
                {
                    "metadata.deckhouse.io/category": "Main"
                },
                "name": "test-vector-1",
                "resourceVersion": 1
            }
        }
    ]
}

Getting a recording rule

This endpoint returns a recording rule by name.

GET /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/recordingrules/:name

URL path parameters:

  • space_name: workspace name. Required
  • project_name: project name. Required
  • name: recording rule name. Required

Authentication required… The token must have “API management” and “Triggers and recording rules” permissions

Example request:

$ curl -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/recordingrules/:name'

Example response:

{
    "apiVersion": "observability.deckhouse.io/v1alpha1",
    "kind": "ObservabilityMetricsRecordingRule",
    "spec":
    {
        "expression": "vector(10)",
        "targetMetric":
        {
            "name": "test:vector",
            "additionalLabels":
            {
                "test": "test",
                "author": "test"
            }
        }
    },
    "metadata":
    {
        "creationTimestamp": "2024-12-13T06:37:39Z",
        "generation": 1,
        "annotations":
        {
            "metadata.deckhouse.io/category": "Main"
        },
        "name": "test-vector-1",
        "resourceVersion": 1
    }
}

Creating a recording rule

This endpoint creates a new recording rule.

POST /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/recordingrules

URL path parameters:

  • space_name: workspace name. Required
  • project_name: project name. Required

Authentication required… The token must have “API management” and “Triggers and recording rules” permissions

Example request:

$ curl -X POST -H "Content-Type: application/json" -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/recordingrules' -d \
'
{
    "kind": "ObservabilityMetricsRecordingRule",
    "metadata":
    {
        "annotations":
        {
            "metadata.deckhouse.io/category": "recording"
        },
        "name": "some-name"
    },
    "spec":
    {
        "targetMetric":
        {
            "name": "metric:rule:name",
            "additionalLabels":
            {
                "testlabel": "value"
            }
        },
        "expression": "vector(10)"
    }
}
'  

Example response:

{
    "apiVersion": "observability.deckhouse.io/v1alpha1",
    "kind": "ObservabilityMetricsRecordingRule",
    "spec":
    {
        "expression": "vector(10)",
        "targetMetric":
        {
            "name": "metric:rule:name",
            "additionalLabels":
            {
                "testlabel": "value"
            }
        }
    },
    "metadata":
    {
        "creationTimestamp": "2024-12-13T06:40:08Z",
        "generation": 1,
        "annotations":
        {
            "metadata.deckhouse.io/category": "recording"
        },
        "name": "some-name",
        "resourceVersion": 1
    }
}

Updating a recording rule

This endpoint updates an existing recording rule.

PUT /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/recordingrules/:name

URL path parameters:

  • space_name: workspace name. Required
  • project_name: project name. Required
  • name: recording rule name

Authentication required… The token must have “API management” and “Triggers and recording rules” permissions

Example request:

$ curl -X PUT -H "Content-Type: application/json" -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/recordingrules/:name' -d \
'
{
    "kind": "ObservabilityMetricsRecordingRule",
    "metadata":
    {
        "annotations":
        {
            "metadata.deckhouse.io/category": "recording updated"
        },
        "name": "test-vector-1"
    },
    "spec":
    {
        "targetMetric":
        {
            "name": "metric:rule:name:updated",
            "additionalLabels":
            {
                "testlabel": "value"
            }
        },
        "expression": "vector(11)"
    }
}
'  

Example response:

{
    "apiVersion": "observability.deckhouse.io/v1alpha1",
    "kind": "ObservabilityMetricsRecordingRule",
    "spec":
    {
        "expression": "vector(11)",
        "targetMetric":
        {
            "name": "metric:rule:name:updated",
            "additionalLabels":
            {
                "testlabel": "value"
            }
        }
    },
    "metadata":
    {
        "creationTimestamp": "2024-12-13T06:42:35Z",
        "generation": 1,
        "annotations":
        {
            "metadata.deckhouse.io/category": "recording updated"
        },
        "name": "test-vector-1",
        "resourceVersion": 1
    }
}

Deleting a recording rule

This endpoint deletes an existing metric.

DELETE /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/recordingrules/:name

URL path parameters:

  • space_name: workspace name. Required
  • project_name: project name. Required
  • name: metric name

Authentication required… The token must have “API management” and “Triggers and recording rules” permissions

Example request:

$ curl -X DELETE -H "Content-Type: application/json" -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/recordingrules/:name'

Errors when creating or updating metrics

If the request to create or update a metric contains invalid data, the response will have a 4xx status with an error message:

{"error":"Validation failed: Name has already been taken"}

Web-monitoring Sites

Site parameters

  • metadata.name: site display name, must be unique within the project
  • metadata.generation: site version
  • metadata.resourceVersion: global site version
  • metadata.creationTimestamp: site creation date/time
  • spec.host: domain name or IP address to monitor (e.g. example.com)
  • spec.uiEditable: whether the site may be edited through the DOP UI. Optional boolean, defaults to true. When set to false the UI marks the site as API-managed: the “edit” action is disabled and a badge is shown, while creation, update via API and deletion (both UI and API) remain available. The field is omitted from API responses when it is at its default value (true); only sites with uiEditable: false include the field. The webmon-cli utility forwards the value verbatim from YAML (uiEditable at unit-defaults or per-target level) and omits the field when YAML does not set it — so existing values stored in DOP are preserved across sync runs.
  • spec.period: probe interval, string in format \d+(s|m), maximum 60 seconds (a multihttp probe may set its own period up to 5m). Examples: "20s", "45s", "1m"
  • spec.ping: enable ICMP ping probe (true/false)
  • spec.probeAllResolvedIPs: probe all resolved IPs instead of just the first one (true/false)
  • spec.hosts: array of specific IP addresses to probe instead of DNS resolution (optional)
  • spec.zones: array of zone names where the site should be monitored. If not specified — monitored from all zones
  • spec.siteLabels: Prometheus labels added to all metrics for this site
  • spec.checkLabels: labels for all checks (e.g. alert=yes, severity=critical, severity_level=1). Checks alert by default; set alert=no to turn that off. A check without a severity alerts without one — set it here, on the probe or on the check if the alert routing needs it
  • spec.requestDefaults: default HTTP request settings. Inherited by HTTP probes only (TCP/DNS probes ignore site-level request).
    • scheme: "http" or "https"
    • timeout: string, format \d+(ms|s|m), max 300s
    • headers: array of {name, value} — both fields are required strings; name must be non-empty; value may be an empty string but must be a String (no nil, no missing key, no non-string types)
    • Probe-specific keys (port, method, path, basicAuth, data, disableHttp2ForHttps) are not allowed at this level
  • spec.probes: array of probe definitions
    • name: probe name
    • probeType: http, tcp, dns or multihttp
    • period: probe-specific interval override (optional). Effective period must be >= every check’s responseTime.max. For multihttp the effective period must be between 30s and 5m
    • request/tcp/dns/multihttp: probe configuration depending on type
      • request.method (HTTP): GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE (case-normalized to uppercase)
      • request.scheme (HTTP): "http" or "https"
      • request.timeout / tcp.timeout / dns.timeout: string, format \d+(ms|s|m), max 300s
      • request.disableHttp2ForHttps (HTTP): string "true" or "false" (must be quoted)
      • dns.type: A, AAAA, CNAME, MX, NS, TXT, SOA, SRV, PTR, CAA (case-normalized to uppercase)
      • port (HTTP/TCP): integer 1..65535
    • checks: array of check definitions
      • name: check name

      • Check fields by probe type:

        probeType Allowed check fields
        http status, responseTime, bodyMatch, bodySize, contentType, location, sslBasicConstraintsValid, certValidDays, sslValidDays, headers, cookies, jsonPath
        tcp connected, responseTime, sslBasicConstraintsValid, certValidDays, sslValidDays
        dns gotAnswer, answerMatch, responseTime
        multihttp (step checks) same as http
      • responseTime.max: string, format \d+(ms|s|m) (no h)

      • jsonPath: array of {expression, condition, value} assertions over the JSON response body. condition is one of exists, equals, notEquals, contains, notContains, startsWith, endsWith, matches, gt, gte, lt, lte; value is required for every condition except exists and must be numeric for gt/gte/lt/lte

    • multihttp (only for probeType: multihttp): a multi-step HTTP scenario — an ordered list of requests sharing a cookie session, with variables extracted from responses and substituted into the following steps. Such a probe has no probe-level checks; every step carries its own. At least one check across the steps is required
      • timeout: scenario deadline, format \d+(ms|s|m), must not exceed the probe period (defaults to the period)
      • cookies: share cookies between steps (true/false, default true)
      • logVariables: log extracted variable values in agent logs (true/false, default false — only names are logged)
      • disableHttp2ForHttps: keep the HTTPS requests of every step on HTTP/1.1 — the string "true"/"false" like request.disableHttp2ForHttps; scenario-wide because the steps share one HTTP client
      • steps: array of 1..10 steps:
        • name: step name, unique within the probe
        • url: absolute http(s):// URL or a path starting with / (resolved against the site host with the step scheme/port, otherwise the site’s requestDefaults, otherwise http). Sent as written — it must already be percent-encoded and carries the query parameters itself (there is no separate query list). url, headers values and basicAuth may carry [[ rndStr ]] / [[ .Site ]] templates, rendered once by the agent when the config loads
        • scheme: http or https a path url is completed with; a validation error next to an absolute url
        • port: 1..65535 a path url is completed with; a validation error next to an absolute url
        • method: HTTP method (default GET)
        • headers: array of {name, value}
        • basicAuth: {username, password} of this step; an explicit Authorization header takes precedence over it
        • data: request body (string)
        • timeout: step timeout, must not exceed the scenario timeout
        • followRedirects: follow redirects (true/false, default false)
        • variables: up to 10 extractors {name, type, expression, attribute}; type is jsonPath, regex (first capture group or the whole match), header, cookie or cssSelector (attribute selects an element attribute instead of its text). A failed extraction fails the step
        • checks: step checks (see the table above); checkLabels are not allowed on them — alert labels of a scenario are set on the probe, and the scenario alerts as a whole (GogomoniaScenarioFailed)
      • ${name} references to variables of previous steps are allowed in url, headers values, data and in check values (status, bodyMatch, contentType, location, headers/cookies values, jsonPath expression and value). ${name} inserts the value verbatim; ${name|urlencode} percent-encodes it per RFC 3986 (everything but A-Za-z0-9-._~, space → %20) — use it for variables inside URLs. Any other filter is a validation error
      • The scenario stops at the first failed step (transport error, failed extraction or any failed check); the remaining steps are reported as failed
      • Agents older than 0.3.0 ignore multihttp probes; agents older than 0.5.0 do not receive scenarios that use step basicAuth, scheme, port, disableHttp2ForHttps or ${name|urlencode}

Getting the list of project web-monitoring sites

GET /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/webmonitoringsites

URL path parameters:

  • space_name: workspace name. Required
  • project_name: project name. Required

Authentication required… The token must have “API management” and “Web-monitoring” permissions

Example request:

$ curl -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/webmonitoringsites'

Example response:

{
    "apiVersion": "v1",
    "kind": "List",
    "metadata": {},
    "items": [
        {
            "apiVersion": "observability.deckhouse.io/v1alpha1",
            "kind": "ObservabilityWebMonitoringSite",
            "metadata": {
                "creationTimestamp": "2026-02-20T10:00:00Z",
                "generation": 1,
                "name": "api-example-com",
                "resourceVersion": "1"
            },
            "spec": {
                "host": "api.example.com",
                "period": "20s",
                "ping": true,
                "probeAllResolvedIPs": false,
                "hosts": ["93.184.216.34"],
                "zones": ["world"],
                "siteLabels": {"project": "myproj"},
                "checkLabels": {"alert": "yes"},
                "probes": [
                    {
                        "name": "https-main",
                        "probeType": "http",
                        "request": {"scheme": "https", "path": "/healthz"},
                        "checks": [
                            {"name": "status-200", "status": [200]},
                            {"name": "response-time", "responseTime": {"max": "5s"}}
                        ]
                    }
                ]
            }
        }
    ]
}

Getting a web-monitoring site

GET /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/webmonitoringsites/:name

URL path parameters:

  • space_name: workspace name. Required
  • project_name: project name. Required
  • name: site name. Required

Authentication required… The token must have “API management” and “Web-monitoring” permissions

Example request:

$ curl -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/webmonitoringsites/api-example-com'

Creating a web-monitoring site

POST /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/webmonitoringsites

URL path parameters:

  • space_name: workspace name. Required
  • project_name: project name. Required

Authentication required… The token must have “API management” and “Web-monitoring” permissions

Example request:

$ curl -X POST -H "X-Auth-Token: <API-token>" \
  -H "Content-Type: application/json" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/webmonitoringsites' \
  -d '{
    "apiVersion": "observability.deckhouse.io/v1alpha1",
    "kind": "ObservabilityWebMonitoringSite",
    "metadata": {"name": "api-example-com"},
    "spec": {
        "host": "api.example.com",
        "period": "20s",
        "ping": true,
        "zones": ["world"],
        "probes": [
            {
                "name": "https-main",
                "probeType": "http",
                "request": {"scheme": "https", "path": "/healthz"},
                "checks": [
                    {"name": "status-200", "status": [200]}
                ]
            }
        ]
    }
}'

Example request with a multi-step scenario (probeType: multihttp): the login step extracts a token and a session cookie, the following steps use them; the probe alerts as a whole with severity=critical:

$ curl -X POST -H "X-Auth-Token: <API-token>" \
  -H "Content-Type: application/json" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/webmonitoringsites' \
  -d '{
    "apiVersion": "observability.deckhouse.io/v1alpha1",
    "kind": "ObservabilityWebMonitoringSite",
    "metadata": {"name": "shop-checkout"},
    "spec": {
        "host": "shop.example.com",
        "period": "30s",
        "ping": false,
        "allZones": true,
        "checkLabels": {"severity": "critical", "severity_level": "1"},
        "requestDefaults": {"scheme": "https"},
        "probes": [
            {
                "name": "checkout_flow",
                "probeType": "multihttp",
                "period": "60s",
                "multihttp": {
                    "timeout": "50s",
                    "cookies": true,
                    "logVariables": false,
                    "steps": [
                        {
                            "name": "login",
                            "url": "/api/login",
                            "method": "POST",
                            "headers": [{"name": "Content-Type", "value": "application/json"}],
                            "data": "{\"user\":\"monitor\",\"password\":\"secret\"}",
                            "variables": [
                                {"name": "token", "type": "jsonPath", "expression": "$.access_token"},
                                {"name": "sid", "type": "cookie", "expression": "session_id"}
                            ],
                            "checks": [
                                {"name": "status_200", "status": [200]},
                                {"name": "has_token", "jsonPath": [{"expression": "$.access_token", "condition": "exists"}]}
                            ]
                        },
                        {
                            "name": "profile",
                            "url": "/api/me?sid=${sid|urlencode}",
                            "headers": [{"name": "Authorization", "value": "Bearer ${token}"}],
                            "followRedirects": true,
                            "checks": [
                                {"name": "status_200", "status": [200], "responseTime": {"max": "2s"}},
                                {"name": "user_id", "jsonPath": [{"expression": "$.id", "condition": "gt", "value": "0"}]}
                            ]
                        },
                        {
                            "name": "landing",
                            "url": "/",
                            "variables": [
                                {"name": "csrf", "type": "cssSelector", "expression": "meta[name=csrf-token]", "attribute": "content"}
                            ],
                            "checks": [
                                {"name": "status_200", "status": [200], "bodyMatch": "/${sid}/"}
                            ]
                        }
                    ]
                }
            }
        ]
    }
}'

Updating a web-monitoring site

PUT /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/webmonitoringsites/:name

URL path parameters:

  • space_name: workspace name. Required
  • project_name: project name. Required
  • name: site name. Required

Authentication required… The token must have “API management” and “Web-monitoring” permissions

The request body format is the same as for creating a site, and it is read the same way: the body is the whole desired state of the site. A site field omitted from spec gets the value a newly created site gets — period 30s, ping false, probeAllResolvedIPs false, empty hosts, siteLabels, checkLabels and requestDefaults. An omitted or empty zones list switches the site to all zones and drops its zone bindings; allZones carries no information of its own. This is what lets a value removed from a webmon-cli YAML file leave DOP on the next sync.

Probes and checks are matched by name: a probe or check whose name is already on the site is updated in place, one that is missing from the request is deleted, and a new name is created. Every field of a matched probe or check is taken from the request, so a field omitted from the body is reset — period, siteLabels and checkLabels included.

Two keys are the exception, because an absent key there means “leave as is”: omit uiEditable and the site keeps its stored flag (git ownership is declared once, not resent with every sync); omit probes and the whole probe tree is left untouched, omit checks on a probe and that probe keeps its checks. Send an empty probes array to remove every probe (only allowed when ping is enabled).

Deleting a web-monitoring site

DELETE /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/webmonitoringsites/:name

URL path parameters:

  • space_name: workspace name. Required
  • project_name: project name. Required
  • name: site name. Required

Authentication required… The token must have “API management” and “Web-monitoring” permissions

Example request:

$ curl -X DELETE -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/webmonitoringsites/api-example-com'

Returns 204 No Content on success.

Hardware Inventory

This is a read-only API for the hardware inventory of bare-metal servers. The Storage Topology and OS Storage Stack sections of the web interface are not exposed through it.

The API covers the servers of one project that have the bare_metal type, are not blacklisted, are not archived, and have been synchronized with the inventory. Archiving a project permanently deletes all of its inventory data: components, installations, slots, datacenters, racks and placements, including the placements of SNMP network devices in those datacenters (the devices themselves are kept). Unarchiving does not bring the data back — the inventory reappears only after the next synchronization, and placements have to be created again.

All endpoints require the permission_api_cmdb_read permission. It can only be granted to a project-scoped token, and it cannot be combined with metrics, logs or traces on the same token, so the inventory needs a token of its own. The write permission does not imply the read one, and there are no write routes yet.

Inventory parameters

List endpoints return their items in a wrapper with pagination:

{
    "apiVersion": "v1",
    "kind": "List",
    "metadata": { "page": 1, "perPage": 50, "totalItems": 128, "totalPages": 3 },
    "items": []
}

The change history of a server is the one list endpoint without pagination: its metadata carries limit and returned instead.

Server (ObservabilityHost):

  • metadata.name: server name as the agent reports it
  • metadata.creationTimestamp: date/time the server record was created
  • spec.hostType: server type, always bare_metal here
  • spec.health.scanTime: date/time of the last inventory scan
  • spec.health.scanStale: true when the last scan is older than two hours or has never happened
  • spec.health.partial: true when the last scan did not cover the whole configuration
  • spec.health.synced: true when the server is synchronized with the inventory
  • spec.system.uuid, spec.system.serial: system UUID and serial number from SMBIOS
  • spec.location: current placement — datacenter, rack, rackUStart, rackUHeight, rackFace. null when the server is not placed
  • spec.singletons: units that exist in a single copy — system, baseboard, bios, chassis. Their fields are passed through from what the agent read out of SMBIOS, so the exact set depends on the server; manufacturer or vendor, product or version, and serial are the usual ones. Only in the response of a single server
  • spec.summary: configuration totals — cpuTotal, cpuPopulated, memoryTotal, memoryPopulated, memoryBytes, disksTotal, disksBytes, nicsTotal, gpusTotal. Only in the response of a single server

Component (ObservabilityHardwareComponent):

  • metadata.name: component key, unique within the project
  • spec.componentType: component kind — cpu, memory, disk, controller, nic, gpu, psu, pci
  • spec.componentKey, spec.manufacturer, spec.model, spec.serialNumber, spec.partNumber: identification of the unit. manufacturer is empty for disks — a disk reports either a generic vendor string or none at all, so the brand is part of model
  • spec.wwn, spec.macAddress, spec.capacityBytes, spec.transport, spec.rotational: fields of specific kinds — WWN and interface for disks, MAC for network cards
  • spec.lifecycleState: present, suspect_missing or removed
  • spec.hostName, spec.slotType, spec.slotKey: where the component is installed now
  • spec.lastSeenAt: date/time the component was last seen in a scan
  • spec.installations: the full history of installations — hostName, slotType, slotKey, installedAt, removedAt. Only in the response of a component by key

Slot (ObservabilityHardwareSlot):

  • spec.slotType: slot kind — cpu_socket, memory_slot, storage_location, system_slot, psu_slot
  • spec.slotKey: slot key
  • spec.occupied: true when a component is installed in the slot
  • spec.componentKey: key of the component in the slot
  • spec.lastSeenAt: date/time the slot was last seen in a scan

Change event (ObservabilityHardwareTimelineEvent):

  • spec.eventType: installed or removed
  • spec.componentKey, spec.componentType: the component the event is about
  • spec.hostName, spec.slotType, spec.slotKey: where it happened
  • spec.occurredAt: date/time of the event

Datacenter (ObservabilityDatacenter) and rack (ObservabilityEquipmentRack):

  • spec.address, spec.description, spec.racksCount: datacenter fields
  • spec.racks: names of the racks. Only in the response of a single datacenter
  • spec.datacenter, spec.uHeight, spec.occupiedUnits: rack fields
  • spec.placements: what is placed in the rack — hostName, rackUStart, rackUHeight, rackFace. Only in the response of a single rack

Note that motherboard, bios and chassis are not component kinds: they are stored with the server as single units and are available in spec.singletons, not through the component endpoints.

Getting the list of project servers

This endpoint returns the list of bare-metal servers of the project.

GET /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/inventory/hosts

URL path parameters:

  • space_name: workspace name. Required
  • project_name: project name. Required

URL query parameters:

  • host: substring of the server name, at least 2 characters, case-insensitive. Optional
  • hostSerial: substring of the system serial number from SMBIOS, at least 2 characters. Optional
  • hostUuid: substring of the system UUID from SMBIOS, at least 2 characters. Optional
  • hostIdentity: substring of the system serial number or UUID, at least 2 characters. Optional
  • motherboardSerial: substring of the motherboard serial number, at least 2 characters. Optional
  • chassisSerial: substring of the chassis serial number, at least 2 characters. Optional
  • datacenter: exact datacenter name. Only the current placement is considered. Optional
  • rack: exact rack name. Requires datacenter, because rack names are unique only within a datacenter; on its own it returns 400 invalid_parameter. Optional
  • historical: true also returns the servers whose last scan is older than two hours or has never happened. Defaults to false. Optional
  • partial: true returns only the servers whose last scan did not cover the whole configuration. Optional
  • kind: component kind — cpu, memory, disk, controller, nic, gpu, psu, pci. Optional
  • serial: substring of the component serial number, at least 2 characters. Optional
  • manufacturer: substring of the component manufacturer, at least 2 characters. Empty for disks — the brand is part of model. Optional
  • model: substring of the component model, at least 2 characters. Optional
  • key: substring of the component key, at least 2 characters. Optional
  • wwn: substring of the WWN, at least 2 characters. Only together with kind=disk, otherwise 400 wwn_not_applicable. Optional
  • mac: substring of the MAC address, at least 2 characters. Only together with kind=nic, otherwise 400 mac_not_applicable. Optional
  • transport: disk interface — nvme, sas, sata, scsi, virtio, unknown. Only together with kind=disk. Optional
  • rotational: true for hard drives, false for SSD and NVMe. Only together with kind=disk. Components whose value is not set match neither. Optional
  • state: component state — present (default), suspect_missing, removed. Optional
  • page: page number, an integer from 1. Defaults to 1. Optional
  • perPage: page size, an integer from 1 to 100. Defaults to 50. Optional

Hardware parameters select servers by what is installed in them: ?kind=disk&model=MZ7LH returns the servers holding such a disk. Several parameters are combined with AND.

Authentication required… The token must have the “Hardware inventory” read permission

Example request:

$ curl -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/inventory/hosts?host=web-&perPage=50'

Example response:

{
    "apiVersion": "v1",
    "kind": "List",
    "metadata": { "page": 1, "perPage": 50, "totalItems": 128, "totalPages": 3 },
    "items":
    [
        {
            "apiVersion": "observability.deckhouse.io/v1alpha1",
            "kind": "ObservabilityHost",
            "metadata":
            {
                "name": "web-01.example.com",
                "creationTimestamp": "2026-03-01T10:00:00Z"
            },
            "spec":
            {
                "hostType": "bare_metal",
                "health": { "scanTime": "2026-07-29T11:00:00Z", "scanStale": false, "partial": false, "synced": true },
                "system": { "uuid": "4c4c4544-0033-3510-8053-b8c04f434332", "serial": "ABC123" },
                "location": { "datacenter": "dc-msk-1", "rack": "R12", "rackUStart": 20, "rackUHeight": 2, "rackFace": "front" }
            }
        }
    ]
}

Getting a server

This endpoint returns one server by name, together with its single units and configuration totals.

GET /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/inventory/hosts/:name

URL path parameters:

  • space_name: workspace name. Required
  • project_name: project name. Required
  • name: server name, exact match. Required

Authentication required… The token must have the “Hardware inventory” read permission

Example request:

$ curl -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/inventory/hosts/web-01.example.com'

Example response:

{
    "apiVersion": "observability.deckhouse.io/v1alpha1",
    "kind": "ObservabilityHost",
    "metadata":
    {
        "name": "web-01.example.com",
        "creationTimestamp": "2026-03-01T10:00:00Z"
    },
    "spec":
    {
        "hostType": "bare_metal",
        "health": { "scanTime": "2026-07-29T11:00:00Z", "scanStale": false, "partial": false, "synced": true },
        "system": { "uuid": "4c4c4544-0033-3510-8053-b8c04f434332", "serial": "ABC123" },
        "singletons":
        {
            "system": { "manufacturer": "Dell Inc.", "product": "PowerEdge R650", "serial": "ABC123" },
            "baseboard": { "manufacturer": "Dell Inc.", "product": "0K2TT4", "serial": "MB-77219" },
            "bios": { "vendor": "Dell Inc.", "version": "1.10.2" },
            "chassis": { "manufacturer": "Dell Inc.", "serial": "CH-40188" }
        },
        "summary":
        {
            "cpuTotal": 2, "cpuPopulated": 2,
            "memoryTotal": 16, "memoryPopulated": 8, "memoryBytes": 274877906944,
            "disksTotal": 2, "disksBytes": 3840755982336,
            "nicsTotal": 1, "gpusTotal": 0
        },
        "location": { "datacenter": "dc-msk-1", "rack": "R12", "rackUStart": 20, "rackUHeight": 2, "rackFace": "front" }
    }
}

Getting the components of a server

This endpoint returns the components installed in one server.

GET /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/inventory/hosts/:name/hardwarecomponents

URL path parameters:

  • space_name: workspace name. Required
  • project_name: project name. Required
  • name: server name, exact match. Required

URL query parameters:

  • kind: component kind — cpu, memory, disk, controller, nic, gpu, psu, pci. Optional
  • state: component state — present (default), suspect_missing, removed. Optional
  • page: page number, an integer from 1. Defaults to 1. Optional
  • perPage: page size, an integer from 1 to 100. Defaults to 50. Optional

There is no historical parameter here — the state of a component is selected with state.

Authentication required… The token must have the “Hardware inventory” read permission

Example request:

$ curl -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/inventory/hosts/web-01.example.com/hardwarecomponents?kind=disk'

Example response:

{
    "apiVersion": "v1",
    "kind": "List",
    "metadata": { "page": 1, "perPage": 50, "totalItems": 2, "totalPages": 1 },
    "items":
    [
        {
            "apiVersion": "observability.deckhouse.io/v1alpha1",
            "kind": "ObservabilityHardwareComponent",
            "metadata":
            {
                "name": "wwn:0x5002538e00000001",
                "creationTimestamp": "2026-03-01T10:00:00Z"
            },
            "spec":
            {
                "componentType": "disk",
                "componentKey": "wwn:0x5002538e00000001",
                "manufacturer": null,
                "model": "SAMSUNG MZQLB1T9HAJR-00007",
                "serialNumber": "S439NA0R202605",
                "wwn": "0x5002538e00000001",
                "macAddress": null,
                "capacityBytes": 1920383410176,
                "transport": "nvme",
                "rotational": false,
                "lifecycleState": "present",
                "hostName": "web-01.example.com",
                "slotType": "storage_location",
                "slotKey": "nvme0n1",
                "lastSeenAt": "2026-07-29T11:00:00Z"
            }
        }
    ]
}

Getting the slots of a server

This endpoint returns the slots of one server, both occupied and empty.

GET /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/inventory/hosts/:name/hardwareslots

URL path parameters:

  • space_name: workspace name. Required
  • project_name: project name. Required
  • name: server name, exact match. Required

URL query parameters:

  • type: slot kind — cpu_socket, memory_slot, storage_location, system_slot, psu_slot. Optional
  • page: page number, an integer from 1. Defaults to 1. Optional
  • perPage: page size, an integer from 1 to 100. Defaults to 50. Optional

Authentication required… The token must have the “Hardware inventory” read permission

Example request:

$ curl -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/inventory/hosts/web-01.example.com/hardwareslots?type=memory_slot'

Example response:

{
    "apiVersion": "v1",
    "kind": "List",
    "metadata": { "page": 1, "perPage": 50, "totalItems": 16, "totalPages": 1 },
    "items":
    [
        {
            "apiVersion": "observability.deckhouse.io/v1alpha1",
            "kind": "ObservabilityHardwareSlot",
            "metadata": { "name": "memory_slot:P0 CHANNEL A/DIMM 0" },
            "spec":
            {
                "slotType": "memory_slot",
                "slotKey": "P0 CHANNEL A/DIMM 0",
                "occupied": true,
                "componentKey": "mem:M391A4G43AB1-CWE:38F2A1B9",
                "lastSeenAt": "2026-07-29T11:00:00Z"
            }
        }
    ]
}

Getting the change history of a server

This endpoint returns the history of component installations and removals for one server, newest first.

GET /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/inventory/hosts/:name/hardwaretimeline

URL path parameters:

  • space_name: workspace name. Required
  • project_name: project name. Required
  • name: server name, exact match. Required

URL query parameters:

  • limit: number of events, an integer from 1 to 200. Defaults to 50. Optional
  • eventType: event kind — installed or removed. Optional

Moving a component between servers is recorded as two events, removed and installed, with the same timestamp.

This endpoint is not paginated: limit bounds the whole answer, page and perPage are ignored, and metadata reports limit and the number of events actually returned.

Authentication required… The token must have the “Hardware inventory” read permission

Example request:

$ curl -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/inventory/hosts/web-01.example.com/hardwaretimeline?limit=50'

Example response:

{
    "apiVersion": "v1",
    "kind": "List",
    "metadata": { "limit": 50, "returned": 3 },
    "items":
    [
        {
            "apiVersion": "observability.deckhouse.io/v1alpha1",
            "kind": "ObservabilityHardwareTimelineEvent",
            "spec":
            {
                "eventType": "installed",
                "componentKey": "wwn:0x5002538e00000001",
                "componentType": "disk",
                "hostName": "web-01.example.com",
                "slotType": "storage_location",
                "slotKey": "nvme0n1",
                "occurredAt": "2026-07-16T14:35:42Z"
            }
        }
    ]
}

Searching for components

This endpoint searches for components across every server of the project and every kind of hardware.

GET /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/inventory/hardwarecomponents

URL path parameters:

  • space_name: workspace name. Required
  • project_name: project name. Required

URL query parameters:

  • host: substring of the server name, at least 2 characters, case-insensitive. Optional
  • hostSerial: substring of the system serial number from SMBIOS, at least 2 characters. Optional
  • hostUuid: substring of the system UUID from SMBIOS, at least 2 characters. Optional
  • hostIdentity: substring of the system serial number or UUID, at least 2 characters. Optional
  • motherboardSerial: substring of the motherboard serial number, at least 2 characters. Optional
  • chassisSerial: substring of the chassis serial number, at least 2 characters. Optional
  • datacenter: exact datacenter name. Only the current placement is considered. Optional
  • rack: exact rack name. Requires datacenter, because rack names are unique only within a datacenter; on its own it returns 400 invalid_parameter. Optional
  • historical: true also returns the components of servers whose last scan is older than two hours. Defaults to false. Optional
  • partial: true returns only the components of servers whose last scan did not cover the whole configuration. Optional
  • kind: component kind — cpu, memory, disk, controller, nic, gpu, psu, pci. Optional
  • serial: substring of the component serial number, at least 2 characters. Optional
  • manufacturer: substring of the component manufacturer, at least 2 characters. Empty for disks — the brand is part of model. Optional
  • model: substring of the component model, at least 2 characters. Optional
  • key: substring of the component key, at least 2 characters. Optional
  • wwn: substring of the WWN, at least 2 characters. Only together with kind=disk, otherwise 400 wwn_not_applicable. Optional
  • mac: substring of the MAC address, at least 2 characters. Only together with kind=nic, otherwise 400 mac_not_applicable. Optional
  • transport: disk interface — nvme, sas, sata, scsi, virtio, unknown. Only together with kind=disk. Optional
  • rotational: true for hard drives, false for SSD and NVMe. Only together with kind=disk. Components whose value is not set match neither. Optional
  • state: component state — present (default), suspect_missing, removed. Optional
  • page: page number, an integer from 1. Defaults to 1. Optional
  • perPage: page size, an integer from 1 to 100. Defaults to 50. Optional

Server parameters select components by the servers they sit in: ?datacenter=dc-msk-1&kind=disk returns the disks of that datacenter. Without kind the search spans every kind of hardware, which is how “find this serial number anywhere” works. The parameter set is the same as for the list of servers, so one query string can be moved between the two views of the same search.

Authentication required… The token must have the “Hardware inventory” read permission

Example request:

$ curl -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/inventory/hardwarecomponents?serial=S439NA'

Example response:

{
    "apiVersion": "v1",
    "kind": "List",
    "metadata": { "page": 1, "perPage": 50, "totalItems": 1, "totalPages": 1 },
    "items":
    [
        {
            "apiVersion": "observability.deckhouse.io/v1alpha1",
            "kind": "ObservabilityHardwareComponent",
            "metadata":
            {
                "name": "wwn:0x5002538e00000001",
                "creationTimestamp": "2026-03-01T10:00:00Z"
            },
            "spec":
            {
                "componentType": "disk",
                "componentKey": "wwn:0x5002538e00000001",
                "manufacturer": null,
                "model": "SAMSUNG MZQLB1T9HAJR-00007",
                "serialNumber": "S439NA0R202605",
                "wwn": "0x5002538e00000001",
                "macAddress": null,
                "capacityBytes": 1920383410176,
                "transport": "nvme",
                "rotational": false,
                "lifecycleState": "present",
                "hostName": "web-01.example.com",
                "slotType": "storage_location",
                "slotKey": "nvme0n1",
                "lastSeenAt": "2026-07-29T11:00:00Z"
            }
        }
    ]
}

Searching for components of one kind

This endpoint searches for components of one kind across every server of the project.

GET /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/inventory/hardwarecomponents/:kind

URL path parameters:

  • space_name: workspace name. Required
  • project_name: project name. Required
  • kind: component kind — cpu, memory, disk, controller, nic, gpu, psu, pci. An unknown kind returns 404. Required

URL query parameters are the same as for the search across every kind. The kind in the path wins over the kind query parameter, so /hardwarecomponents/cpu?kind=disk searches for processors.

Authentication required… The token must have the “Hardware inventory” read permission

Example request:

$ curl -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/inventory/hardwarecomponents/disk?model=SAMSUNG&rotational=false'

Example response:

{
    "apiVersion": "v1",
    "kind": "List",
    "metadata": { "page": 1, "perPage": 50, "totalItems": 2, "totalPages": 1 },
    "items":
    [
        {
            "apiVersion": "observability.deckhouse.io/v1alpha1",
            "kind": "ObservabilityHardwareComponent",
            "metadata":
            {
                "name": "wwn:0x5002538e00000001",
                "creationTimestamp": "2026-03-01T10:00:00Z"
            },
            "spec":
            {
                "componentType": "disk",
                "componentKey": "wwn:0x5002538e00000001",
                "manufacturer": null,
                "model": "SAMSUNG MZQLB1T9HAJR-00007",
                "serialNumber": "S439NA0R202605",
                "wwn": "0x5002538e00000001",
                "macAddress": null,
                "capacityBytes": 1920383410176,
                "transport": "nvme",
                "rotational": false,
                "lifecycleState": "present",
                "hostName": "web-01.example.com",
                "slotType": "storage_location",
                "slotKey": "nvme0n1",
                "lastSeenAt": "2026-07-29T11:00:00Z"
            }
        }
    ]
}

Getting a component by key

This endpoint returns one component by its key, together with the full history of its installations.

GET /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/inventory/hardwarecomponents/keys/:key

URL path parameters:

  • space_name: workspace name. Required
  • project_name: project name. Required
  • key: component key, exact match, URL-encoded. Required

Authentication required… The token must have the “Hardware inventory” read permission

Example request:

$ curl -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/inventory/hardwarecomponents/keys/wwn%3A0x5002538e00000001'

Example response:

{
    "apiVersion": "observability.deckhouse.io/v1alpha1",
    "kind": "ObservabilityHardwareComponent",
    "metadata":
    {
        "name": "wwn:0x5002538e00000001",
        "creationTimestamp": "2026-03-01T10:00:00Z"
    },
    "spec":
    {
        "componentType": "disk",
        "componentKey": "wwn:0x5002538e00000001",
        "manufacturer": null,
        "model": "SAMSUNG MZQLB1T9HAJR-00007",
        "serialNumber": "S439NA0R202605",
        "wwn": "0x5002538e00000001",
        "macAddress": null,
        "capacityBytes": 1920383410176,
        "transport": "nvme",
        "rotational": false,
        "lifecycleState": "present",
        "hostName": "web-01.example.com",
        "slotType": "storage_location",
        "slotKey": "nvme0n1",
        "lastSeenAt": "2026-07-29T11:00:00Z",
        "installations":
        [
            {
                "hostName": "web-01.example.com",
                "slotType": "storage_location",
                "slotKey": "nvme0n1",
                "installedAt": "2026-07-16T14:35:42Z",
                "removedAt": null
            }
        ]
    }
}

Exporting the inventory of servers to CSV

This endpoint returns the whole inventory of the project as a CSV file, one row per component, sorted by server name, component kind and component key.

GET /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/inventory/hosts/export

URL path parameters:

  • space_name: workspace name. Required
  • project_name: project name. Required

URL query parameters:

  • hostNames[]: server names, exact match, no more than 500. Repeated with the brackets: hostNames[]=web-01&hostNames[]=web-02. The bracketless hostNames= takes a single name — repeating it keeps only the last value. Without the parameter the export covers the whole project. A prefix or a substring is not accepted here. Optional
  • state: component state — present (default), suspect_missing, removed. Optional

There is no historical parameter and no freshness cut: unlike the list of servers, which by default hides a server whose last scan is older than two hours, the export covers every synchronized server of the project.

An export of more than 100 000 rows is refused with 413 export_too_large before the first byte is sent. The response has the text/csv; charset=utf-8 type with a UTF-8 BOM and is sent as an attachment named <project>-hosts-<YYYYMMDD>.csv.

Authentication required… The token must have the “Hardware inventory” read permission

Example request:

$ curl -H "X-Auth-Token: <API-token>" -OJ \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/inventory/hosts/export?hostNames[]=web-01.example.com&hostNames[]=web-02.example.com'

Example response:

hostName,componentKey,componentType,manufacturer,model,serialNumber,wwn,macAddress,capacityBytes,transport,lifecycleState,slotType,slotKey,lastSeenAt
web-01.example.com,wwn:0x5002538e00000001,disk,,SAMSUNG MZQLB1T9HAJR-00007,S439NA0R202605,0x5002538e00000001,,1920383410176,nvme,present,storage_location,nvme0n1,2026-07-29T11:00:00Z

Exporting components of one kind to CSV

This endpoint returns the components of one kind as a CSV file, sorted by server name and component key.

GET /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/inventory/hardwarecomponents/:kind/export

URL path parameters:

  • space_name: workspace name. Required
  • project_name: project name. Required
  • kind: component kind — cpu, memory, disk, controller, nic, gpu, psu, pci. Required

URL query parameters:

  • hostNames[]: server names, exact match, no more than 500, repeated with the brackets the same way as in the export of the inventory of servers. Optional
  • state: component state — present (default), suspect_missing, removed. Optional
  • the hardware parameters of the component search — serial, manufacturer, model, key, wwn, mac, transport, rotational. Optional

The server parameters of the search — host, datacenter, rack and the rest — are ignored here: the set of servers is given by hostNames. historical is one of them, so the export has no freshness cut either and returns the components of the servers that the list of components hides by default. The columns, the 100 000 row limit and the response headers are the same as for the inventory of servers; the file is named <project>-<kind>-<YYYYMMDD>.csv.

Authentication required… The token must have the “Hardware inventory” read permission

Example request:

$ curl -H "X-Auth-Token: <API-token>" -OJ \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/inventory/hardwarecomponents/disk/export?rotational=false'

Example response:

hostName,componentKey,componentType,manufacturer,model,serialNumber,wwn,macAddress,capacityBytes,transport,lifecycleState,slotType,slotKey,lastSeenAt
web-01.example.com,wwn:0x5002538e00000001,disk,,SAMSUNG MZQLB1T9HAJR-00007,S439NA0R202605,0x5002538e00000001,,1920383410176,nvme,present,storage_location,nvme0n1,2026-07-29T11:00:00Z

Getting the list of datacenters

This endpoint returns the list of datacenters of the project.

GET /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/inventory/datacenters

URL path parameters:

  • space_name: workspace name. Required
  • project_name: project name. Required

URL query parameters:

  • page: page number, an integer from 1. Defaults to 1. Optional
  • perPage: page size, an integer from 1 to 100. Defaults to 50. Optional

Authentication required… The token must have the “Hardware inventory” read permission

Example request:

$ curl -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/inventory/datacenters'

Example response:

{
    "apiVersion": "v1",
    "kind": "List",
    "metadata": { "page": 1, "perPage": 50, "totalItems": 2, "totalPages": 1 },
    "items":
    [
        {
            "apiVersion": "observability.deckhouse.io/v1alpha1",
            "kind": "ObservabilityDatacenter",
            "metadata": { "name": "dc-msk-1" },
            "spec":
            {
                "address": "Moscow, Butlerova 7",
                "description": "Main site",
                "racksCount": 12
            }
        }
    ]
}

Getting a datacenter

This endpoint returns one datacenter by name, together with the names of its racks.

GET /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/inventory/datacenters/:name

URL path parameters:

  • space_name: workspace name. Required
  • project_name: project name. Required
  • name: datacenter name, exact match. Required

Authentication required… The token must have the “Hardware inventory” read permission

Example request:

$ curl -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/inventory/datacenters/dc-msk-1'

Example response:

{
    "apiVersion": "observability.deckhouse.io/v1alpha1",
    "kind": "ObservabilityDatacenter",
    "metadata": { "name": "dc-msk-1" },
    "spec":
    {
        "address": "Moscow, Butlerova 7",
        "description": "Main site",
        "racksCount": 12,
        "racks": ["R11", "R12", "R13"]
    }
}

Getting the list of racks

This endpoint returns the racks of one datacenter.

GET /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/inventory/datacenters/:name/racks

URL path parameters:

  • space_name: workspace name. Required
  • project_name: project name. Required
  • name: datacenter name, exact match. Required

URL query parameters:

  • page: page number, an integer from 1. Defaults to 1. Optional
  • perPage: page size, an integer from 1 to 100. Defaults to 50. Optional

Authentication required… The token must have the “Hardware inventory” read permission

Example request:

$ curl -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/inventory/datacenters/dc-msk-1/racks'

Example response:

{
    "apiVersion": "v1",
    "kind": "List",
    "metadata": { "page": 1, "perPage": 50, "totalItems": 12, "totalPages": 1 },
    "items":
    [
        {
            "apiVersion": "observability.deckhouse.io/v1alpha1",
            "kind": "ObservabilityEquipmentRack",
            "metadata": { "name": "R12" },
            "spec":
            {
                "datacenter": "dc-msk-1",
                "uHeight": 42,
                "occupiedUnits": 18
            }
        }
    ]
}

Getting a rack

This endpoint returns one rack together with what is placed in it.

GET /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/inventory/datacenters/:name/racks/:rack_name

URL path parameters:

  • space_name: workspace name. Required
  • project_name: project name. Required
  • name: datacenter name, exact match. Required
  • rack_name: rack name, exact match. Required

Authentication required… The token must have the “Hardware inventory” read permission

Example request:

$ curl -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/inventory/datacenters/dc-msk-1/racks/R12'

Example response:

{
    "apiVersion": "observability.deckhouse.io/v1alpha1",
    "kind": "ObservabilityEquipmentRack",
    "metadata": { "name": "R12" },
    "spec":
    {
        "datacenter": "dc-msk-1",
        "uHeight": 42,
        "occupiedUnits": 18,
        "placements":
        [
            {
                "hostName": "web-01.example.com",
                "rackUStart": 20,
                "rackUHeight": 2,
                "rackFace": "front"
            }
        ]
    }
}

Errors when requesting inventory

Errors are returned in the Kubernetes Status format:

{
    "apiVersion": "observability.deckhouse.io/v1alpha1",
    "kind": "Status",
    "status": "Failure",
    "code": 400,
    "reason": "query_too_short",
    "message": "parameter serial must be at least 2 characters"
}
  • 400 query_too_short: a substring parameter is shorter than 2 characters
  • 400 invalid_parameter: perPage is greater than 100, rack is given without datacenter, or the value of an enumeration is not one of the allowed ones
  • 400 page_too_deep: page multiplied by perPage is greater than 100 000
  • 400 wwn_not_applicable, mac_not_applicable, rotational_not_applicable, transport_not_applicable: a parameter is used with a component kind that does not have that field
  • 401: the token is missing, invalid, or has no read permission for the inventory. This response comes from the authentication gateway and is not in the Status format
  • 404: the server, key, kind or datacenter does not exist. An unknown address and any method other than GET also return 404, not 405
  • 413 export_too_large: the export would be larger than 100 000 rows. It is checked before the first byte is sent

A parameter that is valid but matches nothing is not an error: the response is an empty list. In particular, a filter on a field that a given kind of hardware does not have returns nothing rather than failing — this is why a disk has to be searched by model and not by manufacturer.

RSM (experimental)

RSM (resource-service model) lets you describe your infrastructure and services as configuration items — products and business functions, services, datastores, platforms, machines, network and power equipment, locations, certificates, and more — connected by typed relations. Each relation carries an answer: what happens to the item that depends on it when the item at its other end does not work. The API stores and serves the model itself — items, their types, the relations between them and the rules of the groups those relations form. A state engine computes each item’s state from that model and from the item’s own signals, and this API also serves that computed state — see “State, manual signals and state history” below.

An item’s own signals come from its manual signal and from its indicators: alerts of the project’s alert storage and PromQL conditions over the project’s metrics. Each type of the platform brings built-in indicators for its items, and you add indicators of your own to any item. The API does not accept telemetry itself: the state engine reads alerts and series from the platform’s alert and metric storage — see “Signals from telemetry” below. The platform also adds items and relations to the model on its own, from its inventory, Kubernetes metrics and the service graph of traces — see “Discovered items” below.

This is a platform-wide setting, disabled by default; ask your administrator to turn it on.

All endpoints require a project-scoped token. GET requests need the permission_api_rsm_read permission, every other method needs permission_api_rsm_write — the two are independent, so a read-only token cannot write and a write-only token cannot read.

Item types (RsmItemType)

GET /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/rsmitemtypes

Returns every item type available to the project: the built-in ones shipped with the platform, plus the project’s own. Use it to discover which spec.type values rsmitems accepts below, and the properties each one expects.

  • metadata.name: type key
  • metadata.creationTimestamp: when a project type was created. Not present on a built-in type
  • spec.archetype: the type’s archetype — the closed category the platform’s model is built from (business_function, service, datastore, platform, compute, device, facility, …). A project type either takes it from its base type or names one of its own
  • spec.layer: the type’s layer (business, service, data, platform, compute, facility, …). A project type without a base type is in the layer of the built-in types of its archetype
  • spec.propertiesSchema: a JSON Schema that a configuration item’s spec.properties must validate against. Besides the type’s own properties it declares the three every item carries: product (a list of the keys of the products the item belongs to; items of the product archetype have none), criticality (1 to 4) and team
  • spec.builtin: true for a type shipped with the platform
  • spec.baseTypeKey: the built-in type a project’s own type extends. Present only on a project type that has one
  • spec.sampleTypeKey: the type a project type was copied from. A note only: the type inherits nothing from it, and the key is not checked, so it may name a type that no longer exists. Present only when set
  • spec.relationRules: the rules the relations of the type’s items follow — see “Relation rules” below. For a project type with a base type, the rules of the base narrowed by the type’s own. {} when the type has none
  • spec.name: display name. Present only when set

A project type whose base type or archetype the platform does not have — one a platform update removed — is still listed and shown, but only as a record: spec.archetype, spec.layer and spec.propertiesSchema are null, spec.relationRules and spec.name are left out, and spec.baseTypeKey still names the removed base type. No item can be created with such a type, and no item of it can be changed (422 on type_key), until a PUT gives the type a base type or an archetype the platform has, by the rules below.

Authentication required… The token must have the permission_api_rsm_read permission

GET .../rsmitemtypes/:key, POST .../rsmitemtypes, PUT .../rsmitemtypes/:key and DELETE .../rsmitemtypes/:key follow the same pattern as other resources below, but addressed by key rather than by id — a built-in type has no id at all. POST and PUT always create or change one of the project’s own types, and a project type stands either on a built-in type or on an archetype of its own:

  • with spec.baseTypeKey, it takes the base type’s archetype and layer, its relation rules, its built-in indicators and dashboards (see “Signals from telemetry” and “Dashboards of an item” below), and the base type’s schema while it has no spec.propertiesSchema of its own. The base must be a built-in type: another project type cannot be one. spec.archetype may be given as well, but must then be the base type’s archetype
  • without spec.baseTypeKey, spec.archetype is required and names one of the platform’s archetypes. The type’s items are then described by its own spec.propertiesSchema only, and have no built-in indicators or dashboards

spec.propertiesSchema, if given, replaces the base type’s schema entirely rather than extending it. A project type’s key consists of lowercase Latin letters, digits and _, starts with a letter, may not collide with a built-in one or be new, and never changes once the type is created: metadata.name in a PUT body is ignored.

PUT changes only the fields the request body carries; spec.propertiesSchema and spec.relationRules are replaced as a whole, not merged, and null clears spec.sampleTypeKey or spec.relationRules. The base type and the archetype change as follows:

  • a different spec.baseTypeKey moves the type to that base type’s archetype, unless the request also names an archetype, which must then be the base type’s
  • "baseTypeKey": null detaches the type from its base type, and the type keeps its archetype. If the type has no spec.propertiesSchema of its own and the base type declares properties, the same request must bring a spec.propertiesSchema, or it is refused with 422 on properties_schema: the type’s items would be left with no properties declared at all
  • the archetype cannot change while the project has items of the type: such a request is refused with 422 on archetype

DELETE of a type the project still has items of is refused with 409 type_in_use, and the type is kept. The API does not move the items to another type: give each of them another type of the same archetype with PUT .../rsmitems/:id first, then delete the type. Other project types whose spec.relationRules name the deleted type keep its key in their types lists, where it matches no item. A type that is deleted takes its type settings with it (see “Type settings” below).

The items are counted and the type deleted as one step. An item created with the type, or given it, at the same moment — through rsmitems or an import — is either counted, and the DELETE answers 409 type_in_use, or comes after the delete and is refused on type_key, as for any type the project does not have: 422 from rsmitems, an entry in errors from an import. A DELETE of a type that another request has just deleted answers 404.

Calling PUT or DELETE on a built-in type’s key returns 403 builtin_type_read_only — the type exists, it is simply not the project’s to change.

Authentication required… GET needs the permission_api_rsm_read permission, the rest need permission_api_rsm_write

Example request:

$ curl -X POST -H "Content-Type: application/json" -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/rsmitemtypes' -d \
'
{
    "metadata": { "name": "mkt_shop" },
    "spec": {
        "baseTypeKey": "service",
        "name": "Shop",
        "relationRules": {
            "depends_on": {
                "runs_on": { "need": "one", "types": ["vm"] },
                "exposed_via": { "allowed": false }
            }
        }
    }
}
'

Relation rules

spec.relationRules narrows, for the items of a type, the relations their archetype allows. Built-in types carry rules of their own; a project type has the rules of its base type, which its own rules may only narrow further. It is an object keyed by the two sides of an item:

  • depends_on: what the item cannot work without — what it runs on, calls, uses the data of
  • dependents: what suffers when the item stops

A side is not an end of the edge: which one it is follows from the way state flows along the relation type. For most relation types the source depends on the target — mkt-order-service uses_data pg-mkt-orders stands on the depends_on side of the service and on the dependents side of the database; for some, such as instance_of, it is the other way round.

Each side maps a relation type the archetype has on that side to an entry of up to four keys:

  • allowed: false — items of the type have no such relation; true or absent — they may have it
  • types: the item types an item at the other end may have; absent or empty — any. A type named here matches the project types based on it as well. The keys are not checked for existence, so a rule may name a project type created later, or further down the same import file
  • need: how many such relations an item must have — min1 (at least one), one (exactly one) or max1 (at most one). Only the item and type forms of the platform’s UI check it: neither this API nor import does, since both write one relation at a time
  • editable: true or false, on the dependents side only: whether the item form of the platform’s UI shows this relation on the item as well, although the relation is written at its other end

A relation type the rules leave out is not restricted. In the example above, items of mkt_shop run on exactly one virtual machine as far as the item form is concerned, and are never exposed through a gateway.

POST and PUT refuse with 422 on relation_rules a side other than these two, a relation type the platform does not have or the type’s archetype does not have on that side, an entry that is not an object, a key other than these four, a value of the wrong kind, and an entry that widens the rules of the base type — allows a relation the base rules out, or names a type the base’s types do not. A PUT that keeps the archetype checks only the entries it changes. The response leaves out entries the platform does not recognize — for example, of a relation type a platform update has removed. An old key of a relation type is read as the relation type it stands for.

The rules are checked whenever a relation is written, through rsmrelations or an import: the relation must fit the rules of the item types at both of its ends (see “Relations” below). Changing the rules, or the type of an item, does not re-check relations that already exist.

Configuration items (RsmItem)

  • metadata.name: the item’s key, unique within the project. Chosen by the client on creation and never changed afterwards
  • metadata.uid: the item’s id, assigned by the platform on creation. This is what :id in the routes below addresses the item by — not metadata.name
  • metadata.creationTimestamp: item creation date/time
  • spec.type: item type key, one of the values rsmitemtypes lists above
  • spec.archetype: the type’s archetype. Derived from spec.type; read-only
  • spec.name: display name. Present only when set
  • spec.labels: the item’s labels — the ones the rules of its type derive from its key, its properties and its relations, and the ones written for it. Telemetry finds the item by them, see “Labels of an item” below
  • spec.properties: item properties, validated against the JSON schema of spec.type
  • spec.source: manual for an item created through this API, import for one written by .../rsmmodel/import, discovery for one the platform created on its own (see “Discovered items” below). A change through this API keeps the source
  • spec.lifecycle: active, or stale once discovery has stopped seeing the item (see “Discovered items” below)
  • spec.lastSeenAt: when discovery last saw the item. Present only when set
  • spec.discovery: { source, lastSeenAt, lifecycle } — which of the discovery sources last saw the item (inventory, kube, service_graph, or null if none has), when, and the same lifecycle as above. Present on every item, whatever its spec.source: an item created by hand or imported that discovery finds keeps its source
  • spec.dashboards: the dashboards the item is shown with, see “Dashboards of an item” below. Present only in the response about one item — of GET, POST and PUT/PATCH — and not in the list
  • status: the item’s computed state, see “State, manual signals and state history” below

GET /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/rsmitems returns every item of the project, ordered by key; the list is not paginated. ?key=, ?archetype=, ?discovery_source= (inventory, kube, service_graph) and ?lifecycle= (active, stale) narrow it to items with exactly that value, and can be combined.

GET .../rsmitems/:id returns one item, addressed by metadata.uid — not by metadata.name: the key of an item can contain a / (a workload discovered in Kubernetes is keyed <cluster>/<namespace>/<name>), which does not fit in a single route segment.

Authentication required… The token must have the permission_api_rsm_read permission

POST .../rsmitems creates an item. Its spec.properties must name the products it belongs to in product (422 on properties otherwise), except on an item of the product archetype. spec.labels takes only the labels the rules of the type do not derive: a request that sets a derived label is refused with 422 on labels, naming it.

PUT/PATCH .../rsmitems/:id updates an item — a field left out of the request body keeps its previous value; metadata.name cannot be changed once set. spec.type may only change to another type of the same archetype, so spec.archetype does not change: a type of another archetype is refused with 422 on type_key, and the item keeps its type — create a new item instead. One exception: an item discovery created, which no relation written by a person or an import touches, may take a type of another archetype, provided all of its relations are allowed for the new archetype. The item’s relations are not re-checked against the relation rules of its new type.

DELETE .../rsmitems/:id removes an item and, with it, every relation that has it as a source or a target, the group rules at it, its manual signal and state history, its own indicators — with their recording rules — the marks that switch built-in indicators off for it, and its dashboard bindings.

Authentication required… The token must have the permission_api_rsm_write permission

Example request:

$ curl -X POST -H "Content-Type: application/json" -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/rsmitems' -d \
'
{
    "metadata": { "name": "pg-mkt-orders" },
    "spec": {
        "type": "dbms",
        "name": "PostgreSQL orders",
        "labels": { "env": "prod" },
        "properties": { "engine": "postgresql", "topology": "ha", "product": ["mkt"], "criticality": "2" }
    }
}
'

Example response:

{
    "apiVersion": "observability.deckhouse.io/v1alpha1",
    "kind": "RsmItem",
    "metadata": {
        "name": "pg-mkt-orders",
        "uid": "3fae9f2f-6f2e-4c1c-8b7e-1a5b2c9d4e6f",
        "creationTimestamp": "2026-09-17T10:00:00Z"
    },
    "spec": {
        "type": "dbms",
        "archetype": "datastore",
        "labels": { "env": "prod", "job": "postgresql" },
        "properties": { "engine": "postgresql", "topology": "ha", "product": ["mkt"], "criticality": "2" },
        "source": "manual",
        "lifecycle": "active",
        "name": "PostgreSQL orders",
        "dashboards": [],
        "discovery": { "source": null, "lastSeenAt": null, "lifecycle": "active" }
    },
    "status": null
}

The job label is derived from the engine property by the rules of the dbms type; once the database is related to the machine it runs on (runs_on), the item also carries that machine’s instance.

Relations (RsmRelation)

A relation is a typed, directed edge between two items of the project, read as “source type target”: mkt-order-service uses_data pg-mkt-orders. Which pairs of archetypes a relation type may connect, which way state flows along it, and which answers it may give, is fixed by the relation type itself — the set of relation types is part of the platform, not something this API lists on its own. The item state reaches along the edge is its receiver: the item that depends on the other end.

  • metadata.name, metadata.uid: a server-generated id — a relation has no natural key of its own, so both fields carry the same value
  • metadata.creationTimestamp: when the relation was created
  • spec.sourceKey, spec.targetKey: the keys of the two items the relation connects
  • spec.type: relation type key, for example uses_data, calls, runs_on, consists_of, fed_by
  • spec.consequence: the answer stored on the relation — what its receiver does when the other end does not work: stops, partial, degraded, share, loses_part, optional, delayed, data_wrong, no_control, no_remote_console, no_reserve or nothing, out of the answers the relation type gives for this pair. null — the default answer of the pair, and always on a relation in a group (the group answers, see “Groups of relations” below) and on a relation whose answer the item at its target gives itself (a service or an artifact used through uses_service or uses_artifact, by its consumers_without property)
  • spec.effectiveConsequence: the answer the relation actually gives — its group’s while it is in a group, else its own, else the default of the pair. Read-only. null for a relation whose type or pair the platform does not have
  • spec.properties: arbitrary properties of the edge
  • spec.source: manual, import or discovery (see “Discovered items” below)
  • spec.groupKey: the key of the group of relations the relation is in at its receiver. Present only when set
  • spec.weight: share, an integer 0–100: what part of its receiver’s work the relation carries in a group by shares (the instances of a service, instance_of). Present only when set
  • spec.placement: on a runs_on relation to an item of the platform archetype, the nodes of the platform the source item actually runs on, [{ node, share }] — node is the key of a machine of the platform, and share its share in percent, null when not known. Written by discovery and by a model file only, and read-only here. Present only when set

GET .../rsmrelations, GET .../rsmrelations/:id, POST .../rsmrelations, PUT/PATCH .../rsmrelations/:id and DELETE .../rsmrelations/:id follow the same pattern as configuration items above — addressed by metadata.uid for the same reason: spec.sourceKey/spec.targetKey can themselves contain a /. The list is ordered by creation time, and neither paginated nor filtered.

POST creates a relation with spec.source: manual; spec.sourceKey, spec.targetKey and spec.type are required. PUT/PATCH changes the fields of spec the request carries and keeps the rest; a spec.placement in a POST or PUT/PATCH body is refused with 422 not_writable on placement. A spec.sourceKey or spec.targetKey that names no item of the project answers 404. spec.type and spec.consequence also take an old key of a relation type or an answer, and store the one it stands for: an old relation type may bring an answer of its own, which a spec.consequence in the same request overrides.

A relation of a kind whose relations replace one another at their receiver (fed_by, connected_via, consists_of, …) or share its work (instance_of, serves) joins a group on its own when it is written without spec.groupKey: the group its kind already has at the receiver for items of the same archetype, or a group made with the one other such relation, which takes the default rule of the kind. A group by shares that lacks shares splits them equally. "groupKey": "" in a PUT/PATCH takes the relation out of its group, and a group left with one relation falls apart: that relation keeps the answer the group gave. DELETE settles the group the relation leaves the same way.

A field a person changes through PUT/PATCH on a relation discovery wrote — spec.consequence, spec.groupKey or spec.weight — is kept by later passes of discovery.

Authentication required… GET needs the permission_api_rsm_read permission, the rest need permission_api_rsm_write

Example request:

$ curl -X POST -H "Content-Type: application/json" -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/rsmrelations' -d \
'
{
    "spec": {
        "sourceKey": "mkt-order-service",
        "targetKey": "pg-mkt-orders",
        "type": "uses_data",
        "consequence": "partial"
    }
}
'

Example response:

{
    "apiVersion": "observability.deckhouse.io/v1alpha1",
    "kind": "RsmRelation",
    "metadata": {
        "name": "7c1d2f3a-4b5c-4e6f-8a9b-0c1d2e3f4a5b",
        "uid": "7c1d2f3a-4b5c-4e6f-8a9b-0c1d2e3f4a5b",
        "creationTimestamp": "2026-09-17T10:05:00Z"
    },
    "spec": {
        "sourceKey": "mkt-order-service",
        "targetKey": "pg-mkt-orders",
        "type": "uses_data",
        "consequence": "partial",
        "effectiveConsequence": "partial",
        "properties": {},
        "source": "manual"
    }
}

A relation is refused with 422 — see Errors below — when its relation type is unknown to the platform, does not join the archetypes of its two items, or the same two items already have a relation of that type; when it joins an item to itself, repeats from the other end a calls or exposed_via relation between the same two services, or closes a cycle where the relation type forbids one (the message names the cycle); when its answer is not one its pair gives; or when it skips a level of placement:

  • an item that runs on a platform does not also run on one of the platform’s nodes — the node goes into the placement of the relation to the platform
  • a service runs on its machine itself or through its instances, a datastore itself or through its nodes, a platform on another platform or on machines of its own — never both

A relation must also fit the relation rules of the types at both of its ends (see “Relation rules” above). It is refused with 422 on relation_type when the rules of the type at one end say its items have no such relation (allowed: false), or name other types for the item at the other end (types). An existing relation the rules have ruled out since it was written stays in the model, but a PUT to it is refused the same way.

Groups of relations (RsmRelationSet)

Relations of one kind at one receiver that carry the same spec.groupKey are a group: the receiver loses its work only when the group’s rule says so — for example, a server fed by two PDUs stops only when both are down. A group with no record of its own follows the default rule of its kind. A relation set is the explicit rule of one group:

  • metadata.name, metadata.uid: a server-generated id, the same value in both
  • metadata.creationTimestamp: when the record was created
  • spec.itemKey: the key of the receiver — the item the relations of the group lead state to
  • spec.type: the relation type of the group’s relations
  • spec.groupKey: the spec.groupKey the group’s relations carry
  • spec.rule: one (one member is enough), need (spec.required members are needed), majority, all, or shares (the receiver loses the shares, spec.weight, of the members that do not work; only for the kinds that share their receiver’s work)
  • spec.required: how many members a rule need requires. Present only when set
  • spec.consequence: the group’s answer when its rule is broken, out of the answers its kind gives for that rule. Left out — the default one; never on a rule shares

GET /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/rsmrelationsets lists the project’s relation sets, oldest first; GET .../rsmrelationsets/:id returns one.

Authentication required… The token must have the permission_api_rsm_read permission

POST .../rsmrelationsets creates the rule of a group, and PUT/PATCH .../rsmrelationsets/:id changes the fields of spec the request carries and keeps the rest. The record is checked against the relations the group has when it is written: at least two, all of them with items of one archetype at the other end, of a kind that forms groups; a spec.required the group can take, an answer the rule gives, and, for shares, shares that add up to 100. A relation that leaves the group later does not change the record. DELETE .../rsmrelationsets/:id removes the record: the group follows the default rule of its kind again, and its relations keep their spec.groupKey. A spec.itemKey that names no item of the project answers 404.

Authentication required… The token must have the permission_api_rsm_write permission

Example request:

$ curl -X POST -H "Content-Type: application/json" -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/rsmrelationsets' -d \
'
{
    "spec": {
        "itemKey": "msk1-db-01",
        "type": "fed_by",
        "groupKey": "g1",
        "rule": "one"
    }
}
'

Example response:

{
    "apiVersion": "observability.deckhouse.io/v1alpha1",
    "kind": "RsmRelationSet",
    "metadata": {
        "name": "2e4f6a8c-0b1d-4f3e-9a5c-7e9b1d3f5a7c",
        "uid": "2e4f6a8c-0b1d-4f3e-9a5c-7e9b1d3f5a7c",
        "creationTimestamp": "2026-09-17T10:10:00Z"
    },
    "spec": {
        "itemKey": "msk1-db-01",
        "type": "fed_by",
        "groupKey": "g1",
        "rule": "one"
    }
}

PATCH .../rsmrelationsets/shares changes the shares of the relations of one group by shares in a single request. spec.itemKey, spec.type and spec.groupKey name the group the way its relations carry it, so a group without a record of its own is changed the same way. spec.shares lists the members to change as { "item": ..., "share": ... }: item is the key of the item at the other end of the member’s relation (the instance of an instance_of), share is its new spec.weight. A member left out keeps its share. All the shares are applied first, and the sum of the whole group is checked after: the request is taken whole, or refused whole with 422 naming the sum, and then no share changes. A change of one share through PUT/PATCH .../rsmrelations/:id is refused the same way when the shares of its group would no longer add up to 100, so shares are moved between members with this request. The response is a List of the group’s relations as they now stand, in the format of GET .../rsmrelations.

Authentication required… The token must have the permission_api_rsm_write permission

Example request:

$ curl -X PATCH -H "Content-Type: application/json" -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/rsmrelationsets/shares' -d \
'
{
    "spec": {
        "itemKey": "mkt-order-service",
        "type": "instance_of",
        "groupKey": "g1",
        "shares": [
            { "item": "mkt-order-service@k8s-1", "share": 70 },
            { "item": "mkt-order-service@k8s-2", "share": 30 }
        ]
    }
}
'

State, manual signals and state history

Once the platform’s state engine has run at least one cycle for a project, every configuration item carries a computed status alongside its spec: its state vector, its own state versus what it inherited from related items, what its own state is made of, a verdict (business functions only) and the root causes behind an inherited problem. Until then, status is null. The engine computes a project once a minute.

  • status.vector, status.own, status.inherited: one entry per state dimension whose value is not that dimension’s own baseline. A dimension left out is at its baseline. A dimension is a plain string, or an object { value, ... } when it carries more: segment its share and keys, delay its seconds, maintenance its until
  • The eight dimensions and their scale, in order of severity, with their baseline first: availability (ok/degraded/down), quality (ok/reduced), delay (ok/delayed), manageability (managed/unmanaged), segment (ok/affected), integrity (ok/compromised), maintenance (none/in_window/overdue), redundancy (ok/lost — the item would not survive one more failure)
  • status.verdict: only present on a business_function item — one of down, partial, segment, optional, delayed, unmanaged, ok
  • status.rootCauses: the items whose own state explains this item’s inherited state, each with the affected dimension, its value, and the path of relations from the root cause to this item. The keys inside an entry are snake_case — item_id, dimension, value and path, each step of it item_id, relation_id, relation_type — unlike the camelCase of the envelope around them
  • status.computedAt: when the state engine last computed this item
  • status.sources: what status.own is made of, one key per source:
    • manual: the vector of the item’s manual signal, null when it has none
    • alerts: the active alert events that reached the item, each with id, name, severity and startsAt. severity is shown only and changes nothing
    • indicators: the latest reading of each indicator of an expression that applies to the item — name, value and at, the time of the reading. value is 0 while the indicator does not fire, and the step of its answer on the scale of its dimension while it does: 1 for the first step above the baseline, 2 for the second (see “Indicators” below)
  • status.data: { stale, conflict }:
    • stale: true when the item’s own state may be out of date — the alert storage or the metric storage did not answer (the engine then keeps what it last read from that storage for up to 10 minutes rather than clearing it), the project has no tenant in them, an alert event that would reach the item reports that its rule has no data, or discovery has stopped seeing the item (spec.lifecycle: stale)
    • conflict: false

GET .../rsmitems accepts ?verdict= and ?dimension=&value= (used together — either alone narrows nothing) to filter the list by computed state, alongside the filters above.

Authentication required… The token must have the permission_api_rsm_read permission

Manual signal

PUT .../rsmitems/:id/manualstate sets, and DELETE .../rsmitems/:id/manualstate clears, the manual signal of one item — one of the sources of its own state, next to its indicators (see “Signals from telemetry” below). A signal is folded into the item’s state by worst per dimension: it can only make an item look worse than the rest of the sources say, never better — setting a dimension to its own baseline value (availability: ok, maintenance: none, …) is rejected.

The three fields of a signal are read from the top level of the request body, with no spec envelope around them — unlike the response, which returns the same three inside spec. Nothing outside these three keys is read, so a body wrapped in spec sets an empty signal and answers 200.

  • vector: the dimensions the signal sets, with the scales above. segment and delay are objects with value — { "value": "affected", "share": 40 }, { "value": "delayed", "seconds": 300 }; every other dimension, maintenance included, is a plain string: the deadline of a signal goes into its own until field below
  • reason: free text. Optional
  • until: when the signal stops applying. Required when the vector sets maintenance, optional otherwise. A signal without maintenance in its vector stops being read once until has passed; a signal with maintenance keeps every other dimension in effect past until — only maintenance itself moves to overdue
  • segment in the vector requires an integer share between 0 and 100

There is one signal per item: PUT both creates and fully replaces it — a field left out of the request is cleared, not kept, unlike a configuration item’s own PUT/PATCH. DELETE is idempotent: clearing an item that never had a signal still answers 204.

The response carries kind: RsmManualState, metadata.itemId and metadata.creationTimestamp, and the signal in spec.

Authentication required… The token must have the permission_api_rsm_write permission

Example request:

$ curl -X PUT -H "Content-Type: application/json" -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/rsmitems/3fae9f2f-6f2e-4c1c-8b7e-1a5b2c9d4e6f/manualstate' -d \
'
{
    "vector": { "availability": "degraded" },
    "reason": "disk replacement in progress"
}
'

State history

GET .../rsmstateevents?item=&since= returns the project’s state transitions, oldest first — one entry per state dimension of one item that moved between two engine cycles. Read-only: nothing writes to it directly.

  • metadata.uid: the transition’s id
  • spec.itemId, spec.dimension: which item and dimension moved
  • spec.fromValue, spec.toValue: the dimension’s value before and after. Both keys are always present: fromValue is null the first time a dimension is observed
  • spec.verdictFrom, spec.verdictTo: the item’s verdict before and after. Both keys are always present, and both are null unless the item is a business function
  • spec.rootCauses: the root causes behind the transition
  • spec.occurredAt: when the transition was recorded

?item= narrows the list to one item’s id (metadata.uid, not its key); ?since= to transitions strictly after the given instant.

Authentication required… The token must have the permission_api_rsm_read permission

Signals from telemetry

An item’s indicators give it its own state the way a manual signal does: per dimension, the worst of the sources counts, and none of them can make an item look better than another one says. An indicator has a source — an alert or a PromQL condition — and, while it fires, puts the item at its answer: a step of the scale of its dimension above the baseline, such as availability: degraded or redundancy: lost. maintenance is never set by an indicator.

The indicators of an item are:

  • the built-in indicators of its type, which come with the platform and act at every item of the type the labels they need are derived for. For example, a server is put at availability: down by the platform’s okagent-heartbeat alert about its instance, at availability: degraded by disk-usage, at redundancy: lost by raid-md-degraded, and at availability: degraded by the expression disk_free while one of its partitions has 10% of its space free or less; a dbms with engine: postgresql is put at redundancy: lost by pg-replication-status about the machine it runs on. A project type with a base type has the built-in indicators of its base; one without has none. A built-in indicator is switched off for one item with rsmdisabledindicators, and for every item of a type with rsmtypesettings
  • its own indicators, rsmindicators

Labels of an item

Telemetry finds an item by its labels. The rules of a type derive the values of the labels its telemetry uses from the item’s key, its properties and its relations: a server keyed msk1-db-01 carries instance: msk1-db-01, a dbms carries job from its engine property and instance from the machine it runs_on, a workload carries dop_ha_cluster, namespace and its kind (deployment: orders) from its key. A label the rules derive is not written by hand: rsmitems refuses it, an import drops it with a warning, and an export does not write it. Every other label is taken as written. spec.labels of an item shows both.

A built-in indicator or dashboard acts at an item while every label it needs is derived for the item.

Indicators (RsmIndicator)

An own indicator belongs to one item.

  • metadata.name, metadata.uid: a server-generated id, the same value in both
  • metadata.creationTimestamp: when the indicator was created
  • spec.item: the key of the item the indicator is on. Required
  • spec.source: alert or expression; expression when left out on creation
  • spec.name: the indicator’s name, unique among the indicators of its item and not the name of a built-in indicator of the item’s type. For an indicator of an expression: lowercase Latin letters, digits and _, starting with a letter. For an indicator from an alert it is the name of the alert, and the name in the request is ignored
  • spec.alert: the name of the alert, as the alerting rule names it. Only for source: alert
  • spec.matchers: the labels the alert has to carry to be about this item, written as in a PromQL selector: instance="msk1-db-01", mount_point!~"/boot.*", the braces optional, with =, !=, =~ and !~. Only for source: alert
  • spec.expr: a PromQL condition, as the expression of an alerting rule: the indicator fires while it returns series. It needs a comparison outside its strings and selectors, such as ... > 20. Only for source: expression
  • spec.dimension: the dimension the indicator sets, any but maintenance
  • spec.answer: the step of the dimension’s scale above its baseline the indicator puts the item at while it fires — degraded or down for availability, lost for redundancy, and so on
  • spec.enabled: true or false, true when left out on creation. A disabled indicator does nothing
  • status.rule: { name, state } for an enabled indicator of an expression — the name of its recording rule, and ok while the rule is there or missing when it has been removed. null for an indicator from an alert and for a disabled one, which have no rule

An indicator from an alert takes the active events of the project’s alert storage with its alert name whose labels satisfy all its matchers. A matcher with = on a label of the item has to name the item’s own value: another value describes another item and is refused with 422 on matchers. Matchers compare labels the way the platform’s alert storage does: = and != exactly, =~ and !~ by a regular expression that may match anywhere in the value and ignores case — anchor it with ^ and $ to match the whole value. = and =~ need a non-empty value and the event to carry the label; != and !~ read a label the event does not carry as an empty string. A regular expression with a construct the state engine does not support — a lookahead or a lookbehind, a backreference, an atomic group, a comment — is refused with 422 on matchers. The engine finds an event’s items by the labels its indicators name with =: an indicator from an alert without such a matcher reaches no item.

An event’s severity does not change what it does. When the indicators of several items take the same event — a server and the dbms that runs on it, both by instance — the item whose indicator names more labels takes it; with a tie, every one of them does. An event whose rule has lost its data is not counted as active: it only marks the items it would reach with status.data.stale. The state engine reads one page of at most 10 000 active events of a project; events beyond it are not read.

An indicator of an expression is written as a recording rule of the project named rsm- followed by 12 hexadecimal digits: count(<expr>) * 0 + <step>, which writes the series rsm:indicator:state with the step of the answer — 1 for the first step above the baseline, 2 for the second — while the condition returns series, and nothing otherwise. A series older than 3 minutes reads as not firing. The rule belongs to the indicator: recordingrules does not list it, answers 404 to a GET, PUT or DELETE of it and 409 to a POST under its name (see “Recording Rules” above). The expression is checked when the rule is written: one the platform’s rule validator refuses is answered with 422 on expr and the validator’s message, and nothing is written. Disabling an indicator removes its rule, and deleting the indicator or its item removes the rule with it. A rule removed any other way leaves the indicator missing until the platform writes the rule again, within 15 minutes.

GET /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/rsmindicators lists the project’s own indicators, oldest first; GET .../rsmindicators/:id returns one.

Authentication required… The token must have the permission_api_rsm_read permission

POST .../rsmindicators creates an indicator. PUT/PATCH .../rsmindicators/:id changes the fields of spec the request carries and keeps the rest; a spec.item in it moves the indicator to that item. DELETE .../rsmindicators/:id removes an indicator with its rule. An item the project does not have answers 404, and an enabled other than true or false answers 400.

Authentication required… The token must have the permission_api_rsm_write permission

An indicator of the database pg-mkt-orders from an alert of the project:

$ curl -X POST -H "Content-Type: application/json" -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/rsmindicators' -d \
'
{
    "spec": {
        "item": "pg-mkt-orders",
        "source": "alert",
        "alert": "mkt-orders-lag",
        "matchers": "instance=\"msk1-db-01\", job=\"postgresql\"",
        "dimension": "delay",
        "answer": "delayed"
    }
}
'

An indicator of the same database from an expression:

$ curl -X POST -H "Content-Type: application/json" -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/rsmindicators' -d \
'
{
    "spec": {
        "item": "pg-mkt-orders",
        "name": "waiting_connections",
        "expr": "sum(postgresql__connections__count{state=\"waiting\", instance=\"msk1-db-01\"}) > 20",
        "dimension": "availability",
        "answer": "degraded"
    }
}
'

Example response:

{
    "apiVersion": "observability.deckhouse.io/v1alpha1",
    "kind": "RsmIndicator",
    "metadata": {
        "name": "5a8e2c17-3b4d-4f6a-9e0b-7c1d2f3a4b5c",
        "uid": "5a8e2c17-3b4d-4f6a-9e0b-7c1d2f3a4b5c",
        "creationTimestamp": "2026-09-29T10:00:00Z"
    },
    "spec": {
        "item": "pg-mkt-orders",
        "source": "expression",
        "name": "waiting_connections",
        "dimension": "availability",
        "answer": "degraded",
        "enabled": true,
        "expr": "sum(postgresql__connections__count{state=\"waiting\", instance=\"msk1-db-01\"}) > 20"
    },
    "status": {
        "rule": { "name": "rsm-4f1a9c0e7b2d", "state": "ok" }
    }
}

Disabled built-in indicators (RsmDisabledIndicator)

A built-in indicator of an item’s type acts at the item unless a mark switches it off for that item:

  • metadata.name, metadata.uid: a server-generated id, the same value in both
  • metadata.creationTimestamp: when the mark was created
  • spec.item: the key of the item
  • spec.name: the name of a built-in indicator of the item’s type — of an alert, such as disk-usage, or of an expression, such as disk_free

GET /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/rsmdisabledindicators lists the project’s marks, oldest first; GET .../rsmdisabledindicators/:id returns one.

Authentication required… The token must have the permission_api_rsm_read permission

POST .../rsmdisabledindicators creates a mark, and DELETE .../rsmdisabledindicators/:id removes it — the indicator acts at the item again. A mark has nothing to change, so there is no PUT. A name that is no built-in indicator of the item’s type is refused with 422 on name, and an item the project does not have answers 404.

Authentication required… The token must have the permission_api_rsm_write permission

Example request:

$ curl -X POST -H "Content-Type: application/json" -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/rsmdisabledindicators' -d \
'
{
    "spec": { "item": "msk1-db-01", "name": "disk-usage" }
}
'

Type settings (RsmTypeSetting)

What a project switches off for all its items of one type:

  • metadata.name: the type’s key — a built-in type or one of the project’s own
  • metadata.creationTimestamp: when the type’s settings were first written. Present only after that
  • spec.disabledIndicators: the names of the type’s built-in indicators switched off for every item of the type, [] by default

GET /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/rsmtypesettings lists every type of the project, built-in and the project’s own, with its settings — nothing switched off for a type whose settings were never written.

Authentication required… The token must have the permission_api_rsm_read permission

PUT .../rsmtypesettings/:type_key replaces spec.disabledIndicators with the list the request carries; a request without it keeps the list. A type the project does not have answers 404, a value that is not a list of strings answers 400, and a name that is no built-in indicator of the type is refused with 422 on disabled_indicators. The recording rules of the built-in indicators of an expression follow the setting: a rule is written while its indicator acts at some item of the project, and removed when it acts at none.

Authentication required… The token must have the permission_api_rsm_write permission

Example request:

$ curl -X PUT -H "Content-Type: application/json" -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/rsmtypesettings/server' -d \
'
{
    "spec": { "disabledIndicators": ["cpu-usage", "disk_free"] }
}
'

Example response:

{
    "apiVersion": "observability.deckhouse.io/v1alpha1",
    "kind": "RsmTypeSetting",
    "metadata": { "name": "server", "creationTimestamp": "2026-09-29T10:00:00Z" },
    "spec": { "disabledIndicators": ["cpu-usage", "disk_free"] }
}

Dashboards of an item

spec.dashboards of an item (see “Configuration items” above) lists the Grafana dashboards the item is shown with. Each entry is { key, title, url, source, labels }: url is the path in the platform’s UI that opens the dashboard with its variables filled in, labels the [label, value] pairs of the item it is opened for, and source says where the entry comes from:

  • binding: a dashboard bound to the item — see “Dashboard bindings” below. These come first, oldest binding first, with key: null. A binding whose dashboard has been deleted is left out
  • builtin: a built-in dashboard of the item’s type, key naming it — for example, the main, disk and network dashboards of a server with var-host from its instance label, the SNMP dashboards of a network device with var-target from its target label. A built-in dashboard is listed while every label it needs is derived for the item (see “Labels of an item” above)

Dashboard bindings (RsmDashboardBinding)

  • metadata.name, metadata.uid: a server-generated id, the same value in both
  • metadata.creationTimestamp: when the binding was created
  • spec.item: the key of the item the binding is on. Required
  • spec.dashboard: { scope, name } — scope is project for a dashboard of the project or global for a global one, name is the dashboard’s metadata.name (see “Dashboards” below). A built-in dashboard or a dashboard of another project cannot be bound. null in the response once the dashboard has been deleted: the binding stays, and shows nothing
  • spec.variables: { <variable>: <value> } — a variable of the dashboard (var-<variable> of its link) and its value; {} for a dashboard with nothing to fill in. A variable named like a label of the item takes the item’s value: left empty, it is filled with it, and another value is refused with 422 on variables. Any other variable needs a value

GET /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/rsmdashboardbindings lists the project’s dashboard bindings, oldest first; GET .../rsmdashboardbindings/:id returns one.

Authentication required… The token must have the permission_api_rsm_read permission

POST .../rsmdashboardbindings creates a binding; spec.dashboard is required, and a dashboard the named scope does not have is refused with 422 on grafana_dashboard. PUT/PATCH .../rsmdashboardbindings/:id changes the fields of spec the request carries and keeps the rest. DELETE .../rsmdashboardbindings/:id removes a binding. An item the project does not have answers 404, and a spec.dashboard that is not an object answers 400.

Authentication required… The token must have the permission_api_rsm_write permission

Example request:

$ curl -X POST -H "Content-Type: application/json" -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/rsmdashboardbindings' -d \
'
{
    "spec": {
        "item": "pg-mkt-orders",
        "dashboard": { "scope": "project", "name": "pg-slow-queries" },
        "variables": { "job": "", "database": "orders" }
    }
}
'

Example response:

{
    "apiVersion": "observability.deckhouse.io/v1alpha1",
    "kind": "RsmDashboardBinding",
    "metadata": {
        "name": "9d0e1f2a-3b4c-4d5e-8f6a-7b8c9d0e1f2a",
        "uid": "9d0e1f2a-3b4c-4d5e-8f6a-7b8c9d0e1f2a",
        "creationTimestamp": "2026-09-29T10:00:00Z"
    },
    "spec": {
        "item": "pg-mkt-orders",
        "variables": { "job": "postgresql", "database": "orders" },
        "dashboard": { "scope": "project", "name": "pg-slow-queries" }
    }
}

Discovered items

The platform adds items and relations to the model of a project from its own data every 10 minutes, with spec.source: discovery — this is what the rest of this section calls discovery:

  • from its inventory: hosts (as server, or vm for a virtual machine; a host that is a Kubernetes node also carries its node and dop_ha_cluster), network devices (as switch, router, firewall, load_balancer, vpn_gateway, storage_array, ups, pdu by their category, or network_device), datacenters and racks; and the relations of a virtual machine to the virtualization cluster of its hypervisor (runs_on, with the hypervisor in its placement) or to its hypervisor, of a host to the network devices it is connected to (connected_via, in the group uplink), of a rack to its datacenter and of equipment to the rack or the datacenter it stands in (located_in)
  • from the Kubernetes metrics of the project: clusters (k8s_cluster), their control planes (k8s_control_plane), nodes (server, keyed by the node’s name) and workloads (workload, keyed <cluster>/<namespace>/<name>, with the kind in properties.kind). A cluster consists_of its nodes, a control plane consists_of the masters and the cluster is managed_by its control plane. A workload has one runs_on relation to its cluster, and the nodes its running pods are on go into the placement of that relation, each with its share of the pods in whole percent — at least 1, so the shares of a workload spread over many nodes may add up to more than 100
  • from the service graph of the project’s traces: services (service, keyed <service_namespace>/<service>) and the calls between them

Discovery covers a project once its model has been written to at least once — an item created, a model imported, and so on. A Kubernetes cluster is named by its dop_ha_cluster label; series without it, and a cluster still named CHANGE_TO_YOUR_CLUSTER_NAME — the placeholder in the manifest of the Deckhouse integration, not yet replaced with the cluster’s name — are skipped. Discovery never creates items of the product, business_function, client_channel, artifact and external_system archetypes, nor of a project type without a base type.

An object the model already has is not added again. Discovery finds it by its labels among the items of all the types of its archetype (a server and a vm are both machines), or by its key among all items of the project, whatever their type. So an item you create or import with the labels of its object, or with the key discovery would give it (the host name for a machine, target for a network device), is found rather than duplicated. Of an item it finds, discovery writes nothing but the object’s labels over the item’s own, spec.lastSeenAt and spec.discovery.source, and a name if the item has none, and makes a stale item active again: its type, properties, name and spec.source stay as they are.

A relation written by hand or by an import is never changed or removed by discovery, except for its placement, which each pass writes on a runs_on relation to a platform whoever wrote the relation. A relation discovery wrote keeps what a person set on it through rsmrelations (spec.consequence, spec.groupKey, spec.weight). A pass of Kubernetes or of the service graph reports everything its source sees: a relation of its kinds that discovery wrote from the same source out of an item of the pass, and that the pass no longer reports, is removed by that pass — a workload moved to another cluster stops running on the old one with the pass that sees it.

What discovery stops seeing ages; the platform checks every 15 minutes:

  • an item no pass has seen for longer than the time to live of the discovery that saw it last — 2 hours for the inventory, 1 hour for Kubernetes and the service graph — becomes spec.lifecycle: stale, whatever its spec.source. It stays in the model and in the state computation, marked status.data.stale, and is active again once a pass sees it
  • an item or a relation discovery created that no pass has seen for longer than the module setting rsm.staleDeleteAfter (7 days by default) is deleted — an item only while nothing people wrote stands on it: a relation of another source, a manual signal, an own indicator, a mark that switches off a built-in indicator, or a dashboard binding. Items and relations of source manual and import are never deleted

Importing and exporting the model

A project’s whole model — its items, relations, group rules and custom item types — can be exported to a YAML file and re-imported from one, for example to move a model between projects or keep it under version control. Manual signals, indicators, marks that switch off built-in indicators, type settings and dashboard bindings are not part of the file: move them through rsmitems/:id/manualstate, rsmindicators, rsmdisabledindicators, rsmtypesettings and rsmdashboardbindings above.

GET /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/rsmmodel/export returns the file as application/x-yaml. Unlike the endpoints above, the file holds keys, not ids, and leaves out source, lifecycle, every timestamp, the labels the rules of a type derive, empty fields, and archetype — except on a custom type without a base type, the one place it cannot be derived from — and importing the file back derives all of these on its own.

Authentication required… The token must have the permission_api_rsm_read permission

POST /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/rsmmodel/import applies a model file — the request body is the file itself, in the format .../rsmmodel/export returns, not a JSON envelope. Add ?dry_run=1 to validate the file and get the same report back without writing anything.

Authentication required… The token must have the permission_api_rsm_write permission

Example request:

$ curl -X POST -H "Content-Type: application/x-yaml" -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/rsmmodel/import' \
  --data-binary @model.yaml

Example response:

{
    "applied": 42,
    "errors": [
        { "key": "mkt-order-service -> mkt-payments (calls)", "messages": ["unknown key priority"] }
    ],
    "warnings": [
        "mkt-order-service -> pg-mkt-orders (stores): relation type stores is now uses_data"
    ]
}

The response is 200 OK whenever the import applied at least one entry, even if others in the same file failed — check errors, since a 200 can still list them. It is 422 only when nothing applied at all and the file has at least one error: every entry failed validation, or the document itself is not a valid model file. An entry that fails validation is listed in errors under its key and skipped; the rest of the file is still applied. warnings lists what the file asked for that was read differently, with the entry still applied — an old key of a type or a relation type read as the one it stands for, an answer the pair does not give or a group_key on a relation of a kind that forms no groups dropped, the labels of items the rules of their types derive dropped.

Importing is an upsert: a custom type is matched by its key, an item by its key, a relation by its source, target and type, a group rule by its item, type and group key, and a match already in the project is updated in place rather than duplicated. Every entry is written whole: a field the entry leaves out is cleared, not kept. Entries the file does not list are not touched, and a relation or a group rule may name items the project already has without listing them. Items left without product in their properties get the products whose business functions depend on them.

An import that collides with another change of the same model at the same moment (such as a type deleted in the platform’s UI) may be stopped by the database. Then nothing of the file is applied, and the response is 422 with applied: 0 and one entry in errors whose key is null and whose message says the model was changed by another request. Send the same file again.

The file is a YAML mapping with version: 1 and four lists — custom_types, items, relations and relation_sets — applied in that order, so an item may be of a custom type, a relation is checked against the relation rules the same file writes, and a group rule against the relations the same file writes.

An entry of custom_types carries the fields of rsmitemtypes under their own names:

  • key: type key, as metadata.name. Required
  • base_type: the built-in base type, as spec.baseTypeKey
  • archetype: as spec.archetype. Required without base_type; with it, it must be the base type’s archetype
  • name: display name
  • sample_type: the type it was copied from, as spec.sampleTypeKey
  • properties_schema: JSON Schema of the properties, as spec.propertiesSchema
  • relation_rules: the type’s own relation rules, as spec.relationRules

An entry of items:

  • key: item key, as metadata.name. Required
  • type: as spec.type. An old key of a built-in type is read as the type it stands for
  • name, labels, properties: as spec.name, spec.labels and spec.properties

An entry of relations takes only these keys, and any other key refuses the relation with an entry in errors (unknown key ...):

  • source, target: the keys of the two items. Required
  • type: relation type key, as spec.type. Required
  • consequence: as spec.consequence
  • group_key: as spec.groupKey
  • weight: as spec.weight
  • placement: on a runs_on relation to a platform, [{ node, share }] with the keys of the platform’s machines, as spec.placement. A node the project does not have refuses the relation
  • properties: as spec.properties

An entry of relation_sets carries the fields of rsmrelationsets: item (the receiver’s key), type, group_key, rule, required and consequence.

version: 1
custom_types:
  - key: mkt_queue
    archetype: datastore
    name: Queue
    sample_type: message_broker
    properties_schema:
      type: object
      properties:
        partitions: { type: integer }
    relation_rules:
      dependents:
        uses_data: { types: [mkt_shop] }
  - key: mkt_shop
    base_type: service
items:
  - { key: mkt-orders-queue, type: mkt_queue, properties: { product: [mkt] } }
  - { key: mkt-order-service, type: mkt_shop, properties: { product: [mkt] } }
  - { key: msk1-db-01, type: server }
  - { key: pdu-a, type: pdu }
  - { key: pdu-b, type: pdu }
relations:
  - { source: mkt-order-service, target: mkt-orders-queue, type: uses_data, consequence: delayed }
  - { source: msk1-db-01, target: pdu-a, type: fed_by, group_key: power }
  - { source: msk1-db-01, target: pdu-b, type: fed_by, group_key: power }
relation_sets:
  - { item: msk1-db-01, type: fed_by, group_key: power, rule: one }

A custom type is written whole, like an item: sample_type, properties_schema and relation_rules an entry leaves out are cleared. archetype of a type with a base type is the exception: left out, it is taken from the base type for a new type or a changed base type, and kept otherwise. An entry the checks of rsmitemtypes, rsmitems, rsmrelations or rsmrelationsets above refuse is listed in errors under its key and skipped — among them a custom type whose archetype would change while the project has items of it, an item whose type would change to one of another archetype, and a relation the relation rules of either end rule out. Unlike rsmitems, an import does not require product of an item. The stored type, item, relation or group rule then stays as it was.

Errors

RSM endpoints that reject an otherwise well-formed request use the same envelope — except .../rsmmodel/import, whose 422 is the { applied, errors, warnings } body described above, not this one:

{
    "apiVersion": "observability.deckhouse.io/v1alpha1",
    "kind": "Status",
    "status": "Failure",
    "code": 422,
    "reason": "invalid",
    "message": "Relation is invalid: Placement is written by discovery or a model file and is not set through the API",
    "details": {
        "causes": [
            { "field": "placement", "message": "is written by discovery or a model file and is not set through the API" }
        ]
    }
}
  • 400 invalid_body: spec or metadata of the request body, or spec.dashboard of a dashboard binding, is not an object; spec.enabled of an indicator is not true or false; spec.disabledIndicators of a type setting is not a list of strings; spec.shares of PATCH .../rsmrelationsets/shares is not a list of one { item, share } or more, each with both fields, or names an item twice
  • 401: the token is missing, invalid, or lacks the permission the request needs. This response comes from the authentication gateway and is not in the Status format
  • 403 builtin_type_read_only: the request tried to change or delete a built-in item type
  • 404 rsm_disabled: the resource-service model is disabled in the module configuration (rsm.enabled: false)
  • 404 not_found: no item, relation, relation set, type, indicator, mark or dashboard binding exists at the given id or key. Also when a request names by key an item the project does not have — spec.sourceKey or spec.targetKey of a relation, spec.itemKey of a relation set, spec.item of an indicator, a mark or a dashboard binding — when PUT .../rsmtypesettings/:type_key names a type the project does not have, and when PATCH .../rsmrelationsets/shares names a group the item does not have
  • 409 type_in_use: the item type to delete still has items in the project, including one created with it or given it while the DELETE ran; give them another type first
  • 422 invalid: the record failed validation; details.causes lists the field and the message, one entry per problem. Among the fields:
    • an item: type_key — a type the project does not have, including one deleted while the item was being saved, or a type of another archetype; properties — properties the schema of the type refuses, or no product on creation; labels — a label the rules of the type derive
    • an item type: key, base_type_key (not a built-in type), archetype (unknown, not the base type’s, or changed under the project’s items), properties_schema (an invalid schema, or a base type removed without a schema of the type’s own) and relation_rules
    • a relation: relation_type — an unknown relation type, a pair of archetypes it does not join, a relation the two items already have, one the relation rules of either end rule out, a carrier and parts of one item at once; target_item_id — the item itself, a relation repeated from the other end, a cycle, a skipped level of placement; consequence — an unknown answer, one the pair does not give, one on a relation in a group or on one whose target gives the answer; group_key — a kind that forms no groups, or items of different archetypes in one group; weight — not an integer 0–100; placement — a placement in the request (not_writable); source_item, target_item — spec.sourceKey or spec.targetKey left out; base — the shares of its group by shares would no longer add up to 100
    • a relation set: relation_type, group_key (fewer than two relations, items of different archetypes, a group that already has a record), rule, required, consequence, and base for shares that do not add up to 100 and, in PATCH .../rsmrelationsets/shares, for a group not by shares or an item that is no member of the group
    • a manual signal: vector — an unknown dimension or value, a value of the wrong shape, a dimension at its own baseline value (a signal does not heal), segment without share; until — maintenance without it
    • an indicator: name, alert, matchers, expr (no condition, or one the rule validator refuses), dimension, answer, and item when spec.item is left out
    • a mark: name — no built-in indicator of the item’s type, or a mark the item already has
    • a type setting: disabled_indicators — a name that is no built-in indicator of the type
    • a dashboard binding: grafana_dashboard — a dashboard the named scope does not have; variables — a variable without a value, or one named like a label of the item with another value

Dashboards

Dashboard parameters

  • metadata.name: dashboard name, must be unique (not used by another project dashboard or global dashboard), lowercase Latin letters and - are allowed
  • metadata.generation: dashboard version
  • metadata.resourceVersion: global dashboard version
  • metadata.creationTimestamp: dashboard creation date/time
  • metadata.annotations: list of dashboard annotations in name-value format. Currently the following annotations are supported:
    • metadata.deckhouse.io/category - dashboard category
    • metadata.deckhouse.io/title - display title
  • spec.definition: JSON dashboard definition

Getting the list of project dashboards

This endpoint returns the list of project dashboards (not including global dashboards).

GET /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/observabilitydashboards

URL path parameters:

  • space_name: workspace name. Required
  • project_name: project name. Required

Authentication required… The token must have “API management” and “Dashboards” permissions

Example request:

$ curl -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/observabilitydashboards'

Example response:

{
    "apiVersion": "observability.deckhouse.io/v1alpha1",
    "kind": "ObservabilityDashboardList",
    "items":
    [
        {
            "apiVersion": "observability.deckhouse.io/v1alpha1",
            "kind": "ObservabilityDashboard",
            "metadata":
            {
                "annotations":
                {
                    "metadata.deckhouse.io/category": "Category-3",
                    "metadata.deckhouse.io/title": "dashboard-3"
                },
                "creationTimestamp": "2025-01-24T10:32:23Z",
                "generation": 1,
                "name": "dash-dash-board-3",
                "namespace": "spicy-space-1",
                "resourceVersion": 1
            },
            "spec":
            {
                "definition": "{\"id\":255,\"uid\":\"GrxobkC5leWtZmaE\",\"tags\":[\"test\",\"test1\"],\"title\":\"Dash-dash-board-3\"}"
            }
        }
    ]
}

Getting a dashboard

This endpoint returns a dashboard by name.

GET /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/observabilitydashboards/:name

URL path parameters:

  • space_name: workspace name. Required
  • project_name: project name. Required
  • name: dashboard name. Required

Authentication required… The token must have “API management” and “Dashboards” permissions

Example request:

$ curl -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/observabilitydashboards/:name'

Example response:

{
    "apiVersion": "observability.deckhouse.io/v1alpha1",
    "kind": "ObservabilityDashboard",
    "metadata":
    {
        "annotations":
        {
            "metadata.deckhouse.io/category": "Category-1",
            "metadata.deckhouse.io/title": "Dash-dash-board 1"
        },
        "creationTimestamp": "2025-01-24T10:38:57Z",
        "generation": 1,
        "name": "dash-dash-board-1",
        "namespace": "spicy-space-1",
        "resourceVersion": 1
    },
    "spec":
    {
        "definition": "{\"uid\":\"KttpW5ERbCrk6H8R\",\"tags\":[\"test\",\"test1\"],\"title\":\"Dash-dash-board-1\"}"
    }
}

Creating a dashboard

This endpoint creates a new dashboard.

POST /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/observabilitydashboards

URL path parameters:

  • space_name: workspace name. Required
  • project_name: project name. Required

Authentication required… The token must have “API management” and “Dashboards” permissions

Example request:

$ curl -X POST -H "Content-Type: application/json" -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/observabilitydashboards' -d \
'
{
    "kind": "ObservabilityDashboard",
    "metadata":
    {
        "annotations":
        {
            "metadata.deckhouse.io/category": "category-name",
            "metadata.deckhouse.io/title": "some name"
        },
        "name": "some-name"
    },
    "spec":
    {
        "definition": {...}
    }
}
'

Example response:

{
    "apiVersion": "observability.deckhouse.io/v1alpha1",
    "kind": "ObservabilityDashboard",
    "metadata":
    {
        "annotations":
        {
            "metadata.deckhouse.io/category": "category-name",
            "metadata.deckhouse.io/title": "some name"
        },
        "creationTimestamp": "2025-01-24T10:41:12Z",
        "generation": 1,
        "name": "some-name",
        "namespace": "spicy-space-1",
        "resourceVersion": 1
    },
    "spec":
    {
        "definition": "{\"uid\":\"czvSGOukIQTWEE19\",\"tags\":[\"test\"],\"title\":\"some name\"}"
    }
}

Updating a dashboard

This endpoint updates an existing dashboard.

PUT /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/observabilitydashboards/:name

URL path parameters:

  • space_name: workspace name. Required
  • project_name: project name. Required
  • name: dashboard name

Authentication required… The token must have “API management” and “Dashboards” permissions

Example request:

$ curl -X PUT -H "Content-Type: application/json" -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/observabilitydashboards/:name' -d \
'
{
    "kind": "ObservabilityDashboard",
    "metadata":
    {
        "annotations":
        {
            "metadata.deckhouse.io/category": "new-category"
        }
    },
    "spec":
    {
        "definition": {...}
    }
}
'

Example response:

{
    "apiVersion": "observability.deckhouse.io/v1alpha1",
    "kind": "ObservabilityDashboard",
    "metadata":
    {
        "annotations":
        {
            "metadata.deckhouse.io/category": "new-category",
            "metadata.deckhouse.io/title": "Dash-dash-board-1"
        },
        "creationTimestamp": "2025-01-24T10:45:15Z",
        "generation": 1,
        "name": "dash-dash-board-1",
        "namespace": "spicy-space-1",
        "resourceVersion": 1
    },
    "spec":
    {
        "definition": "{\"uid\":\"yS1Qy46y6x01bFJI\",\"tags\":[\"test\",\"another-test\"],\"title\":\"Dash-dash-board-1\"}"
    }
}

Deleting a dashboard

This endpoint deletes an existing dashboard.

DELETE /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/observabilitydashboards/:name

URL path parameters:

  • space_name: workspace name. Required
  • project_name: project name. Required
  • name: dashboard name

Authentication required… The token must have “API management” and “Dashboards” permissions

Example request:

$ curl -X DELETE -H "Content-Type: application/json" -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/observabilitydashboards/:name'

Errors when creating or updating dashboards

If the request to create or update a dashboard contains invalid data, the response will have a 4xx status with an error message:

{"error":"Validation failed: Name has already been taken"}

Workspaces

Workspace parameters

  • metadata.name: workspace name, must be unique, lowercase Latin letters and - are allowed
  • metadata.generation: workspace version
  • metadata.resourceVersion: global workspace version
  • metadata.creationTimestamp: workspace creation date/time

Getting the list of workspaces

This endpoint returns the list of workspaces. GET /api/v1/observability.deckhouse.io/spaces

Authentication required… The token must have “API management” and “Workspaces” permissions

Example request:

$ curl -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces'

Example response:

{
    "apiVersion": "observability.deckhouse.io/v1alpha1",
    "kind": "ObservabilitySpacesList",
    "metadata": {},
    "items":
    [
        {
            "apiVersion": "observability.deckhouse.io/v1alpha1",
            "kind": "ObservabilitySpace",
            "metadata":
            {
                "creationTimestamp": "2025-03-14T06:07:50Z",
                "generation": 1,
                "name": "example-space",
                "resourceVersion": 1
            },
            "spec":
            {}
        }
    ]
}

Getting a workspace

This endpoint returns a workspace by name.

GET /api/v1/observability.deckhouse.io/spaces/:name

URL path parameters:

  • name: workspace name. Required

Authentication required… The token must have “API management” and “Workspaces” permissions

Example request:

$ curl -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:name'

Example response:

{
  "apiVersion": "observability.deckhouse.io/v1alpha1",
  "kind": "ObservabilitySpace",
  "metadata":
  {
      "creationTimestamp": "2025-03-14T06:07:50Z",
      "generation": 1,
      "name": "example-space",
      "resourceVersion": 1
  },
  "spec":
  {}
}

Creating a workspace

This endpoint creates a new workspace.

POST /api/v1/observability.deckhouse.io/spaces

Authentication required… The token must have “API management” and “Workspaces” permissions

Example request:

$ curl -X POST -H "Content-Type: application/json" -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces' -d \
'
{
    "kind": "ObservabilitySpace",
    "metadata":
    {
        "name": "some-name"
    }
}
'

Example response:

{
  "apiVersion": "observability.deckhouse.io/v1alpha1",
  "kind": "ObservabilitySpace",
  "metadata":
  {
      "creationTimestamp": "2025-03-14T06:07:50Z",
      "generation": 1,
      "name": "some-name",
      "resourceVersion": 1
  },
  "spec":
  {}
}

Deleting a workspace

This endpoint deletes an existing workspace.

DELETE /api/v1/observability.deckhouse.io/spaces/:name

URL path parameters:

  • name: workspace name

Authentication required… The token must have “API management” and “Workspaces” permissions

Example request:

$ curl -X DELETE -H "Content-Type: application/json" -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:name'

Errors when creating workspaces

If the request to create a workspace contains invalid data, the response will have a 4xx status with an error message:

{"error":"Validation failed: Space name has already been taken"}

Projects

Project parameters

  • metadata.name: project name, must be unique within the workspace, lowercase Latin letters and - are allowed
  • metadata.generation: project version
  • metadata.resourceVersion: global project version
  • metadata.creationTimestamp: project creation date/time
  • spec.description: project description
  • spec.auto-monitoring: flag indicating whether auto-monitoring is used in the specified project.

Getting the list of workspace projects

This endpoint returns the list of projects in a workspace.

GET /api/v1/observability.deckhouse.io/spaces/:space_name/projects

URL path parameters:

  • space_name: workspace name. Required

Authentication required… The token must have “API management” and “Projects” permissions

Example request:

$ curl -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/'

Example response:

{
    "apiVersion": "observability.deckhouse.io/v1alpha1",
    "kind": "ObservabilityProjectsList",
    "metadata": {},
    "items":
    [
        {
            "apiVersion": "observability.deckhouse.io/v1alpha1",
            "kind": "ObservabilityProject",
            "metadata":
            {
                "creationTimestamp": "2025-03-14T06:06:41Z",
                "generation": 1,
                "name": "some-project",
                "resourceVersion": 1
            },
            "spec":
            {
                "description": "project description",
                "auto-monitoring": true
            }
        }
    ]
}

Getting a project

This endpoint returns a project by name.

GET /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:name

URL path parameters:

  • space_name: workspace name. Required
  • name: project name. Required

Authentication required… The token must have “API management” and “Projects” permissions

Example request:

$ curl -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:name'

Example response:

{
  "apiVersion": "observability.deckhouse.io/v1alpha1",
  "kind": "ObservabilityProject",
  "metadata":
  {
      "creationTimestamp": "2025-03-14T06:06:41Z",
      "generation": 1,
      "name": "some-project",
      "resourceVersion": 1
  },
  "spec":
  {
      "description": "project description",
      "auto-monitoring": true
  }
}

Creating a project

This endpoint creates a new project.

POST /api/v1/observability.deckhouse.io/spaces/:space_name/projects

URL path parameters:

  • space_name: workspace name. Required

Authentication required… The token must have “API management” and “Projects” permissions

Example request:

$ curl -X POST -H "Content-Type: application/json" -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects' -d \
'
{
    "kind": "ObservabilityProject",
    "metadata":
    {
      "name": "some-name"
    },
    "spec":
    {
      "description": "project description",
      "auto-monitoring": true
    }
}
'

Example response:

{
  "apiVersion": "observability.deckhouse.io/v1alpha1",
  "kind": "ObservabilityProject",
  "metadata":
  {
      "creationTimestamp": "2025-03-14T06:06:41Z",
      "generation": 1,
      "name": "some-project",
      "resourceVersion": 1
  },
  "spec":
  {
      "description": "project description",
      "auto-monitoring": true
  }
}

Updating a project

This endpoint updates an existing project.

PUT /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:name

URL path parameters:

  • space_name: workspace name. Required
  • name: project name. Required

Authentication required… The token must have “API management” and “Projects” permissions

Example request:

$ curl -X PUT -H "Content-Type: application/json" -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:name' -d \
'
{
    "kind": "ObservabilityProject",
    "spec":
    {
        "description": "updated description",
        "auto-monitoring": false
    }
}
'

Example response:

{
  "apiVersion": "observability.deckhouse.io/v1alpha1",
  "kind": "ObservabilityProject",
  "metadata":
  {
      "creationTimestamp": "2025-03-14T06:06:41Z",
      "generation": 1,
      "name": "some-project",
      "resourceVersion": 1
  },
  "spec":
  {
      "description": "updated description",
      "auto-monitoring": false
  }
}

Deleting a project

This endpoint deletes an existing project.

DELETE /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:name

URL path parameters:

  • space_name: workspace name. Required
  • name: project name. Required

Authentication required… The token must have “API management” and “Projects” permissions

Example request:

$ curl -X DELETE -H "Content-Type: application/json" -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:name'

Errors when creating or updating a project

If the request to create or update a project contains invalid data, the response will have a 4xx status with an error message:

{"error":"Validation failed: Project name has already been taken"}

Notification Channels

Notification channel parameters

  • metadata.name: notification channel name, must be unique within the project, lowercase Latin letters and - are allowed
  • metadata.generation: notification channel version
  • metadata.resourceVersion: global notification channel version
  • metadata.creationTimestamp: notification channel creation date/time
  • spec.type: notification channel type, allowed values: Email, Telegram, Webhook, Slack

Email notification channel parameters

  • spec.email.from: email address from which messages will be sent
  • spec.email.smtp.address: mail server address
  • spec.email.smtp.auth.username: username for mail server authentication
  • spec.email.smtp.auth.password: password for mail server authentication
  • spec.email.stmp.requireTLS: flag indicating whether TLS is required when sending messages. Allowed values: true / false
  • spec.email.template: message template. Returned in responses, not modifiable via API

Telegram notification channel parameters

  • spec.telegram.apiUrl: Telegram API URL, by default the standard https://api.telegram.org is used
  • spec.telegram.apiToken: authorization token for the Telegram channel
  • spec.telegram.template: message template. Returned in responses, not modifiable via API

Slack notification channel parameters

  • spec.slack.apiURL: Slack URL for sending notifications
  • spec.slack.template: message template. Returned in responses, not modifiable via API

Webhook notification channel parameters

  • spec.webhook.url: URL for sending messages

Getting the list of project channels

This endpoint returns the list of project notification channels and public notification channels. For public channels, only the name and type are returned, without channel parameters.

GET /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/observabilitynotificationchannels

URL path parameters:

  • space_name: workspace name. Required
  • project_name: project name

Authentication required… The token must have “API management” and “Notification channels” permissions

Example request:

$ curl -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/observabilitynotificationchannels'

Example response:

{
  "apiVersion": "observability.deckhouse.io/v1alpha1",
  "kind": "ObservabilityNotificationChannelsList",
  "metadata": {},
  "items": [
    {
      "apiVersion": "observability.deckhouse.io/v1alpha1",
      "kind": "ObservabilityNotificationChannel",
      "metadata": {
        "name": "example-channel",
        "creationTimestamp": "2025-03-19T06:12:20Z",
        "generation": 1,
        "resourceVersion": "1"
      },
      "spec": {
        "type": "Email",
        "email": {
          "from": "no-reply@email.com",
          "smtp": {
            "address": "smtp.example.server.com:555",
            "auth": {
              "username": "username",
              "password": "password"
            },
            "requireTLS": true
          },
          "template": "..."
        }
      }
    },
  ]
}

Getting a notification channel

This endpoint returns a project notification channel by name.

GET /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/observabilitynotificationchannels/:name

URL path parameters:

  • space_name: workspace name. Required
  • project_name: project name
  • name: channel name. Required

Authentication required… The token must have “API management” and “Notification channels” permissions

Example request:

$ curl -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/observabilitynotificationchannels/:name'

Example response:

{
  "apiVersion": "observability.deckhouse.io/v1alpha1",
  "kind": "ObservabilityNotificationChannel",
  "metadata": {
    "name": "example-channel",
    "creationTimestamp": "2025-03-19T06:12:20Z",
    "generation": 1,
    "resourceVersion": "1"
  },
  "spec": {
    "type": "Email",
    "email": {
      "from": "no-reply@email.com",
      "smtp": {
        "address": "smtp.example.server.com:555",
        "auth": {
          "username": "username",
          "password": "password"
        },
        "requireTLS": true
      },
      "template": "..."
    }
  }
}

Creating a notification channel

This endpoint creates a new project notification channel.

POST /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/observabilitynotificationchannels

URL path parameters:

  • space_name: workspace name. Required
  • project_name: project name

Authentication required… The token must have “API management” and “Notification channels” permissions

Example request:

$ curl -X POST -H "Content-Type: application/json" -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/observabilitynotificationchannels' -d \
'
{
  "kind": "ObservabilityNotificationChannel",
  "metadata":
  {
      "name": "new-channel"
  },
  "spec":
  {
      "type": "Email",
      "email":
      {
          "from": "from@email.com",
          "smtp":
          {
              "address": "smtp.example.com:444",
              "auth":
              {
                  "username": "username",
                  "password": "password"
              },
              "requireTLS": true
          }
      }
  }
}
'

Example response:

{
  "apiVersion": "observability.deckhouse.io/v1alpha1",
  "kind": "ObservabilityNotificationChannel",
  "metadata":
  {
      "name": "new-channel",
      "creationTimestamp": "2025-03-28T05:04:45Z",
      "generation": 1,
      "resourceVersion": "1"
  },
  "spec":
  {
      "type": "Email",
      "email":
      {
          "from": "from@email.com",
          "smtp":
          {
              "address": "smtp.example.com:444",
              "auth":
              {
                  "username": "username",
                  "password": "password"
              },
              "requireTLS": true
          },
          "template": null
      }
  }
}

Updating a notification channel

This endpoint updates a project notification channel.

PUT /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/observabilitynotificationchannels/:name

URL path parameters:

  • space_name: workspace name. Required
  • project_name: project name
  • name: channel name. Required

Authentication required… The token must have “API management” and “Notification channels” permissions

Example request:

$ curl -X PUT -H "Content-Type: application/json" -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/observabilitynotificationchannels/:name' -d \
'
{
  "kind": "ObservabilityNotificationChannel",
  "metadata":
  {
      "name": "some-channel-1"
  },
  "spec":
  {
      "type": "Email",
      "email":
      {
          "from": "from2@email.com",
          "smtp":
          {
              "address": "smtp.example.com:444",
              "auth":
              {
                  "username": "username",
                  "password": "password"
              },
              "requireTLS": true
          }
      }
  }
}
'

Example response:

{
  "apiVersion": "observability.deckhouse.io/v1alpha1",
  "kind": "ObservabilityNotificationChannel",
  "metadata":
  {
      "name": "some-channel-1",
      "creationTimestamp": "2025-03-28T05:08:42Z",
      "generation": 1,
      "resourceVersion": "1"
  },
  "spec":
  {
      "type": "Email",
      "email":
      {
          "from": "from2@email.com",
          "smtp":
          {
              "address": "smtp.example.com:444",
              "auth":
              {
                  "username": "username",
                  "password": "password"
              },
              "requireTLS": true
          },
          "template": null
      }
  }
}

Deleting a notification channel

This endpoint deletes an existing project notification channel.

DELETE /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/observabilitynotificationchannels/:name

URL path parameters:

  • space_name: workspace name. Required
  • project_name: project name
  • name: channel name. Required

Authentication required… The token must have “API management” and “Notification channels” permissions

Example request:

$ curl -X DELETE -H "Content-Type: application/json" -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/observabilitynotificationchannels/:name'

Errors when creating or updating a notification channel

If the request to create or update a channel contains invalid data, the response will have a 4xx status with an error message:

{"error":"Validation failed: Name has already been taken"}

Notification Rules

Notification rule parameters

  • metadata.name: notification rule name, must be unique within the project, lowercase Latin letters and - are allowed
  • metadata.generation: notification rule version
  • metadata.resourceVersion: global notification rule version
  • metadata.creationTimestamp: notification rule creation date/time
  • spec.alert.selector.matchExpressions.items: array of notification selectors, described below
  • spec.notification.channel.name: notification channel name
  • spec.notification.parameters: notification parameters, depend on the channel type, described below
  • spec.notification.repeatInterval: repeat notification interval, string value in the form ’30s’, ‘5m’, ‘1h’ (seconds, minutes, and hours are allowed)

Notification selector

  • key: label name
  • operator: string operator designation, allowed values: Equal, NotEqual, Regex, NotRegex
  • value: string label value for comparison by the operator

Email notification channel parameters

  • spec.notification.parameters.emails: array of email addresses to which the notification is sent

Telegram notification channel parameters

  • spec.notification.parameters.chatIds: array of chat identifiers to which notifications are sent

Slack notification channel parameters

  • spec.notification.parameters.channels: array of Slack channel names to which the notification is sent

Webhook notification channel parameters

Notification rules for webhook channels do not use parameters.

Getting the list of channel notification rules

This endpoint returns the list of notification rules for a workspace notification channel.

GET /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/observabilitynotificationpolicies

URL path parameters:

  • space_name: workspace name. Required
  • project_name: project name

Authentication required… The token must have “API management” and “Notification rules” permissions

Example request:

$ curl -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/observabilitynotificationpolicies'

Example response:

{
  "apiVersion": "observability.deckhouse.io/v1alpha1",
  "kind": "ObservabilityNotificationPoliciesList",
  "metadata": {},
  "items":
  [
    {
      "apiVersion": "observability.deckhouse.io/v1alpha1",
      "kind": "ObservabilityNotificationPolicy",
      "metadata": {
        "name": "test-rule",
        "creationTimestamp": "2025-03-28T06:42:47Z",
        "generation": 1,
        "resourceVersion": "1"
      },
      "spec": {
        "alert": {
          "selector": {
            "matchExpressions": {
              "items":
              [
                {
                  "key": "severity",
                  "operator": "Equal",
                  "value": "critical"
                }
              ]
            }
          }
        },
        "notification":
        {
          "channel":
          {
            "kind": "ObservabilityNotificationChannel",
            "name": "some-channel-1",
            "parameters": { "emails": ["test@email.com"] }
          },
          "repeatInterval": "30s"
        }
      }
    }
  ]
}

Getting a notification rule

This endpoint returns a project notification rule by name.

GET /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/observabilitynotificationpolicies/:name

URL path parameters:

  • space_name: workspace name. Required
  • project_name: project name
  • name: rule name. Required

Authentication required… The token must have “API management” and “Notification rules” permissions

Example request:

$ curl -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/observabilitynotificationpolicies/:name'

Example response:

{
  "apiVersion": "observability.deckhouse.io/v1alpha1",
  "kind": "ObservabilityNotificationPolicy",
  "metadata": {
    "name": "test-rule",
    "creationTimestamp": "2025-03-28T07:00:54Z",
    "generation": 1,
    "resourceVersion": "1"
  },
  "spec": {
    "alert": {
      "selector": {
        "matchExpressions": {
          "items": [
            {
              "key": "severity",
              "operator": "Equal",
              "value": "critical"
            }
          ]
        }
      }
    },
    "notification": {
      "channel": {
        "kind": "ObservabilityNotificationChannel",
        "name": "some-giper-channel-1",
        "parameters": {
          "emails": ["test@email.com"]
        }
      },
      "repeatInterval": "30s"
    }
  }
}

Creating a notification rule

This endpoint creates a new project notification rule.

POST /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/observabilitynotificationpolicies

URL path parameters:

  • space_name: workspace name. Required
  • project_name: project name

Authentication required… The token must have “API management” and “Notification rules” permissions

Example request:

$ curl -X POST -H "Content-Type: application/json" -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/observabilitynotificationchannels/:notification_channel_name/observabilitynotificationpolicies' -d \
'
{
  "kind": "ObservabilityNotificationPolicy",
  "metadata": {
    "name": "test-rule"
  },
  "spec": {
    "alert": {
      "selector": {
        "matchExpressions": {
          "items": [
            {
              "key": "severity",
              "operator": "Equal",
              "value": "critical"
            }
          ]
        }
      }
    },
    "notification": {
      "channel": {
        "kind": "ObservabilityNotificationChannel",
        "name": "some-giper-channel-1",
        "parameters": {
          "emails": [
            "first@email.com",
            "second@email.com"
          ]
        }
      },
      "repeatInterval": "45s"
    }
  }
}
'

Example response:

{
  "apiVersion": "observability.deckhouse.io/v1alpha1",
  "kind": "ObservabilityNotificationPolicy",
  "metadata": {
    "name": "test-rule",
    "creationTimestamp": "2025-03-28T07:12:41Z",
    "generation": 1,
    "resourceVersion": "1"
  },
  "spec": {
    "alert": {
      "selector": {
        "matchExpressions": {
          "items": [
            {
              "key": "severity",
              "operator": "Equal",
              "value": "critical"
            }
          ]
        }
      }
    },
    "notification": {
      "channel": {
        "kind": "ObservabilityNotificationChannel",
        "name": "some-giper-channel-1",
        "parameters": {
          "emails": [
            "first@email.com",
            "second@email.com"
          ]
        }
      },
      "repeatInterval": "45s"
    }
  }
}

Updating a notification rule

This endpoint updates a project notification rule.

PUT /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/observabilitynotificationpolicies/:name

URL path parameters:

  • space_name: workspace name. Required
  • project_name: project name
  • name: rule name. Required

Authentication required… The token must have “API management” and “Notification rules” permissions

Example request:

$ curl -X PUT -H "Content-Type: application/json" -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/observabilitynotificationpolicies/:name' -d \
'
{
  "kind": "ObservabilityNotificationChannel",
  "metadata": {
    "name": "test-rule"
  },
  "spec": {
    "alert": {
      "selector": {
        "matchExpressions": {
          "items": [
            {
              "key": "severity",
              "operator": "Equal",
              "value": "warning"
            }
          ]
        }
      }
    },
    "notification": {
      "channel": {
        "kind": "ObservabilityNotificationChannel",
        "name": "some-channel-1",
        "parameters": {
          "emails": [
            "first@email.com",
            "second@email.com"
          ]
        }
      },
      "repeatInterval": "46s"
    }
  }
}
'

Example response:

{
  "apiVersion": "observability.deckhouse.io/v1alpha1",
  "kind": "ObservabilityNotificationPolicy",
  "metadata": {
    "name": "test-rule",
    "creationTimestamp": "2025-03-28T07:16:02Z",
    "generation": 1,
    "resourceVersion": "1"
  },
  "spec": {
    "alert": {
      "selector": {
        "matchExpressions": {
          "items": [
            {
              "key": "severity",
              "operator": "Equal",
              "value": "warning"
            }
          ]
        }
      }
    },
    "notification": {
      "channel": {
        "kind": "ObservabilityNotificationChannel",
        "name": "some-giper-channel-1",
        "parameters": {
          "emails": [
            "first@email.com",
            "second@email.com"
          ]
        }
      },
      "repeatInterval": "46s"
    }
  }
}

Deleting a notification rule

This endpoint deletes an existing project notification rule.

DELETE /api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/observabilitynotificationpolicies/:name

URL path parameters:

  • space_name: workspace name. Required
  • project_name: project name
  • name: rule name. Required

Authentication required… The token must have “API management” and “Notification rules” permissions

Example request:

$ curl -X DELETE -H "Content-Type: application/json" -H "X-Auth-Token: <API-token>" \
  'https://api.dop.example.com/api/v1/observability.deckhouse.io/spaces/:space_name/projects/:project_name/observabilitynotificationpolicies/:name'

Errors when creating or updating a notification rule

If the request to create or update a rule contains invalid data, the response will have a 4xx status with an error message:

{"error":"Validation failed: Name has already been taken"}

Users

The Users API is served on the main domain (https://dop.example.com), not on the API domain.

User parameters

  • metadata.external_id: external user identifier (e.g., OIDC ID)
  • metadata.generation: user version
  • metadata.resourceVersion: global user version
  • metadata.creationTimestamp: user creation date/time
  • spec.email: user email
  • spec.firstName: user first name
  • spec.lastName: user last name
  • spec.displayName: full name

Getting the list of users

This endpoint returns the list of users. GET /api/v1/observability.deckhouse.io/users

Authentication required… The token must have “User management” permissions, and the token must be bound to the entire system (global scope)

Example request:

$ curl -H "X-Auth-Token: <API-token>" \
  'https://dop.example.com/api/v1/observability.deckhouse.io/users'

Example response:

{
    "apiVersion": "observability.deckhouse.io/v1alpha1",
    "kind": "ObservabilityUsersList",
    "metadata":
    {},
    "items":
    [
        {
            "apiVersion": "observability.deckhouse.io/v1alpha1",
            "kind": "ObservabilityUser",
            "metadata":
            {
                "creationTimestamp": "2025-05-13T07:14:10Z",
                "generation": 1,
                "externalId": "1",
                "resourceVersion": "1"
            },
            "spec":
            {
                "email": "mail1+memaybe@example.com",
                "firstName": "Jason",
                "lastName": "Bourne-1th",
                "displayName": null
            }
        }
    ]
}

Getting a user

This endpoint returns a user by external identifier.

GET /api/v1/observability.deckhouse.io/users/:external_id

URL path parameters:

  • external_id: external user identifier. Required

Authentication required… The token must have “User management” permissions, and the token must be bound to the entire system (global scope)

Example request:

$ curl -H "X-Auth-Token: <API-token>" \
  'https://dop.example.com/api/v1/observability.deckhouse.io/users/1'

Example response:

{
  "apiVersion": "observability.deckhouse.io/v1alpha1",
  "kind": "ObservabilityUser",
  "metadata":
  {
      "creationTimestamp": "2025-05-13T07:14:10Z",
      "generation": 1,
      "externalId": "1",
      "resourceVersion": "1"
  },
  "spec":
  {
      "email": "mail1+memaybe@example.com",
      "firstName": "Jason",
      "lastName": "Bourne-1th",
      "displayName": null
  }
}

Creating a user

This endpoint creates a new user. To send requests to create a user, OIDC role provisioning must be disabled.

POST /api/v1/observability.deckhouse.io/users

Authentication required… The token must have “User management” permissions, and the token must be bound to the entire system (global scope)

Example request:

$ curl -X POST -H "Content-Type: application/json" -H "X-Auth-Token: <API-token>" \
  'https://dop.example.com/api/v1/observability.deckhouse.io/users' -d \
'
{
    "kind": "ObservabilityUser",
    "metadata":
    {
        "externalId": "1"
    },
    "spec":
    {
        "email": "some@email.com",
        "firstName": "Ivan",
        "lastName": "Ivanov",
        "displayName": "Ivan Ivanov"
    }
}
'  

Example response:

{
    "apiVersion": "observability.deckhouse.io/v1alpha1",
    "kind": "ObservabilityUser",
    "metadata":
    {
        "creationTimestamp": "2025-05-16T12:43:48Z",
        "generation": 1,
        "externalId": "1",
        "resourceVersion": "1"
    },
    "spec":
    {
        "email": "some@email.com",
        "firstName": "Ivan",
        "lastName": "Ivanov",
        "displayName": "Ivan Ivanov"
    }
}

Updating a user

This endpoint updates an existing user. To send requests to update a user, OIDC role provisioning must be disabled.

PUT /api/v1/observability.deckhouse.io/users/:external_id

  • external_id: external user identifier. Required

Authentication required… The token must have “User management” permissions, and the token must be bound to the entire system (global scope)

Example request:

$ curl -X PUT -H "Content-Type: application/json" -H "X-Auth-Token: <API-token>" \
  'https://dop.example.com/api/v1/observability.deckhouse.io/users/1' -d \
'
{
    "kind": "ObservabilityUser",
    "metadata":
    {
        "externalId": "1"
    },
    "spec":
    {
        "email": "updated@email.com",
        "firstName": "Ivan",
        "lastName": "Ivanov",
        "displayName": "Ivan Ivanov"
    }
}
'  

Example response:

{
    "apiVersion": "observability.deckhouse.io/v1alpha1",
    "kind": "ObservabilityUser",
    "metadata":
    {
        "creationTimestamp": "2025-05-16T12:49:06Z",
        "generation": 1,
        "externalId": "1",
        "resourceVersion": "1"
    },
    "spec":
    {
        "email": "updated@email.com",
        "firstName": "Ivan",
        "lastName": "Ivanov",
        "displayName": "Ivan Ivanov"
    }
}

Deleting a user

This endpoint deletes an existing user. To send requests to delete a user, OIDC role provisioning must be disabled.

DELETE /api/v1/observability.deckhouse.io/users/:external_id

  • external_id: external user identifier. Required

Authentication required… The token must have “User management” permissions, and the token must be bound to the entire system (global scope)

Example request:

$ curl -X DELETE -H "Content-Type: application/json" -H "X-Auth-Token: <API-token>" \
  'https://dop.example.com/api/v1/observability.deckhouse.io/users/1'

Errors when creating or updating a user

If the request to create or update a user contains invalid data, the response will have a 4xx status with an error message:

{"error":"Validation failed: Email has already been taken"}

If OIDC role provisioning is enabled, attempts to modify user roles will return the error “OIDC user roles enabled”.

User Roles

The User Roles API is served on the main domain (https://dop.example.com), not on the API domain.

Description of the user role model.

User role parameters

  • metadata.generation: user version
  • metadata.resourceVersion: global user version
  • metadata.creationTimestamp: user creation date/time
  • spec.scope: type of object the user role is bound to (allowed values: GlobalScope, Space, Project)
  • spec.role: user role, allowed values: super_admin, admin, user, viewer, ro_super_admin
  • spec.space: workspace the user role is bound to
  • spec.project: project the user role is bound to

Getting the list of user roles

This endpoint returns the list of user roles. GET /api/v1/observability.deckhouse.io/users/:external_id/memberships

Authentication required… The token must have “User management” permissions, and the token must be bound to the entire system (global scope)

Example request:

$ curl -H "X-Auth-Token: <API-token>" \
  'https://dop.example.com/api/v1/observability.deckhouse.io/users/:external_id/memberships'

Example response:

{
  "apiVersion": "observability.deckhouse.io/v1alpha1",
  "kind": "ObservabilityUserMembershipsList",
  "metadata": {},
  "items":
  [
    {
      "apiVersion": "observability.deckhouse.io/v1alpha1",
      "kind": "ObservabilityUserMembership",
      "metadata":
      {
          "creationTimestamp": "2025-05-13T05:21:39Z",
          "generation": 1,
          "resourceVersion": 1
      },
      "spec":
      {
          "scope": "GlobalScope",
          "role": "admin"
      }
    },
    {
      "apiVersion": "observability.deckhouse.io/v1alpha1",
      "kind": "ObservabilityUserMembership",
      "metadata":
      {
          "creationTimestamp": "2025-05-13T05:21:39Z",
          "generation": 1,
          "resourceVersion": 1
      },
      "spec":
      {
          "scope": "Space",
          "role": "user",
          "space": "spicy-space-1"
      }
    },
    {
      "apiVersion": "observability.deckhouse.io/v1alpha1",
      "kind": "ObservabilityUserMembership",
      "metadata":
      {
          "creationTimestamp": "2025-05-13T05:21:39Z",
          "generation": 1,
          "resourceVersion": 1
      },
      "spec":
      {
          "scope": "Project",
          "role": "viewer",
          "space": "spicy-space-1",
          "project": "umbrella-project-1"
      }
    }
  ]
}

Updating user roles

This endpoint updates user roles. To send requests to update roles, OIDC role provisioning must be disabled.

POST /api/v1/observability.deckhouse.io/users/:external_id/memberships

URL path parameters:

  • external_id: external user identifier. Required

Authentication required… The token must have “User management” permissions, and the token must be bound to the entire system (global scope)

Example request:

$ curl -X POST -H "Content-Type: application/json" -H "X-Auth-Token: <API-token>" \
  'https://dop.example.com/api/v1/observability.deckhouse.io/users/1/memberships' -d \
'
{
  "apiVersion": "observability.deckhouse.io/v1alpha1",
  "kind": "ObservabilityUserMembershipsList",
  "metadata": {},
  "items":
  [
    {
      "spec":
      {
          "scope": "GlobalScope",
          "role": "admin"
      }
    },
    {
      "spec":
      {
          "scope": "Space",
          "role": "user",
          "space": "spicy-space-1"
      }
    },
    {
      "spec":
      {
          "scope": "Project",
          "role": "viewer",
          "space": "spicy-space-1",
          "project": "umbrella-project-1"
      }
    }
  ]
}
'

Example response:

{
  "apiVersion": "observability.deckhouse.io/v1alpha1",
  "kind": "ObservabilityUserMembershipsList",
  "metadata": {},
  "items":
  [
    {
      "spec":
      {
          "scope": "GlobalScope",
          "role": "admin"
      }
    },
    {
      "spec":
      {
          "scope": "Space",
          "role": "user",
          "space": "spicy-space-1"
      }
    },
    {
      "spec":
      {
          "scope": "Project",
          "role": "viewer",
          "space": "spicy-space-1",
          "project": "umbrella-project-1"
      }
    }
  ]
}

Errors when creating or updating user roles

If the request to update user roles contains invalid data, the response will have a 4xx status with an error message:

{"error":"Validation failed: Memberships is invalid"}

If OIDC role provisioning is enabled, attempts to modify user roles will return the error “OIDC user roles enabled”.