Read platform data: metrics, logs, alerts, inventory
Read the data VerOps already holds for your organization: metric names and values, logs, alerts, and software inventory. Each endpoint documented with purpose, parameter tables and validation, request and response examples, and notes on filtering, paging, and sorting.
Overview
These endpoints read the data VerOps already holds for your organization — metric names and values, logs, alerts, and software inventory — delivered as JSON. Every one requires the API scope and wraps its payload in a {"data": ...} envelope. They are all safe to retry.
| Group | Endpoints |
|---|---|
| Metrics | GET /v1/metrics/names, POST /v1/metrics/query |
| Logs | POST /v1/logs/query |
| Alerts | GET /v1/alerts, GET /v1/alerts/{guid} |
| Inventory | GET /v1/inventory/products, GET /v1/inventory/products/{id}, GET /v1/inventory/utilization, GET /v1/inventory/summary |
Metrics
List metric names
GET /v1/metrics/names — the metric names available to your organization. No parameters.
curl https://api.verops.io/v1/metrics/names -H "X-Api-Key: $KEY"
# -> 200
{"data": ["http_server_request_count", "cpu_usage", "memory_used_bytes"]}
Query a metric
POST /v1/metrics/query — read a platform metric as a time-series range or as a single latest value.
| Field | Type | Required | Constraints | Description |
|---|---|---|---|---|
metric |
string | Yes | One of the names from /v1/metrics/names |
The metric to read. |
labels |
object | No | String to string | Filter to series matching these labels. |
start |
number or string | No | Epoch millis or ISO-8601 | Start of the range. Pair with end. |
end |
number or string | No | Epoch millis or ISO-8601 | End of the range. Pair with start. |
step |
string | No | Duration such as 1m, 5m, 1h |
Bucket width for the range. |
If you supply both start and end, you get a time-series over that range. If you omit both, you get the latest instant value.
# Range query
curl -X POST https://api.verops.io/v1/metrics/query \
-H "X-Api-Key: $KEY" -H "Content-Type: application/json" \
-d '{"metric":"http_server_request_count","start":1700000000000,
"end":1700003600000,"step":"1m"}'
# Latest instant value (omit start and end)
curl -X POST https://api.verops.io/v1/metrics/query \
-H "X-Api-Key: $KEY" -H "Content-Type: application/json" \
-d '{"metric":"http_server_request_count"}'
# Range -> 200 (data is an array of [epochMillis, value] pairs)
# {"data": [[1700000000000, 3.0], [1700000060000, 5.0]],
# "meta": {"metric": "http_server_request_count", "type": "range",
# "start": 1700000000000, "end": 1700003600000}}
#
# Instant -> 200 (data is a single number)
# {"data": 42.0, "meta": {"metric": "http_server_request_count", "type": "instant"}}
The response is the standard {"data": ..., "meta": ...} envelope. For a range, data is an array of [epochMillis, value] pairs; for an instant query, data is a single number. Keep ranges reasonable — a very wide window with a small step produces too many buckets and is rejected with 400.
Errors: 400 if metric is missing or the range is too large; standard 401 / 403 / 429.
Logs
POST /v1/logs/query — search your logs, filtered and paginated.
| Field | Type | Required | Constraints | Description |
|---|---|---|---|---|
query |
string | No | — | Free-text search over log messages. |
services |
array of string | No | — | Restrict to these service names. |
levels |
array of string | No | For example ERROR, WARN, INFO |
Restrict to these log levels. |
startTime |
number or string | No | Epoch millis or ISO-8601 | Start of the window. Pair with endTime. |
endTime |
number or string | No | Epoch millis or ISO-8601 | End of the window. |
timeRange |
string | No | One of 15m, 1h, 24h |
A relative window, as an alternative to startTime/endTime. |
page |
number | No | Zero-based, default 0 | Which page to return. |
pageSize |
number | No | 1 to 1000 | Results per page. |
curl -X POST https://api.verops.io/v1/logs/query \
-H "X-Api-Key: $KEY" -H "Content-Type: application/json" \
-d '{"query":"timeout","services":["checkout"],"levels":["ERROR"],
"timeRange":"1h","page":0,"pageSize":50}'
Response — 200:
{
"data": {
"logs": [
{"id": "a1b2...", "timestamp": "2023-11-14T22:13:19Z", "level": "ERROR",
"service": "checkout", "message": "upstream timeout calling payments",
"traceId": "a1b2c3d4", "spanId": "e5f6", "host": "checkout-7c9",
"environment": "prod", "tags": {"region": "us-east"}},
{"id": "a1b3...", "timestamp": "2023-11-14T22:12:20Z", "level": "ERROR",
"service": "checkout", "message": "retry budget exhausted"}
],
"total": 128,
"took": 12,
"page": 0,
"size": 50,
"hasMore": true,
"aggregations": {
"services": [{"key": "checkout", "count": 128}],
"levels": [{"key": "ERROR", "count": 128}]
}
}
}
Logs come newest first. total is the full match count and hasMore tells you whether further pages exist; page through by incrementing page (each page holds up to size entries). took is the query time in milliseconds, and aggregations breaks the matches down by service and level. Fields like traceId, spanId, host, and tags appear only when the log line carried them. Use either timeRange or the explicit startTime/endTime pair, not both.
Alerts
List alerts
GET /v1/alerts — your alerts, paginated.
| Query parameter | Type | Required | Constraints | Description |
|---|---|---|---|---|
status |
string | No | active or history, default active |
Active alerts, or historical (resolved) ones. |
page |
number | No | Zero-based, default 0 | Which page to return. |
size |
number | No | Default 20 | Results per page. |
curl "https://api.verops.io/v1/alerts?status=active&page=0&size=20" \
-H "X-Api-Key: $KEY"
Response — 200:
{
"data": [
{"id": 4021, "guid": "b7f0e2a1-...", "name": "High error rate on checkout",
"description": "5xx ratio above 2% for 5m", "source": "METRICS",
"severity": "critical", "status": "active",
"currentValue": 4.7, "thresholdValue": 2.0, "thresholdType": "gt",
"query": "...", "startedAt": "2023-11-14T22:10:00Z"}
],
"meta": {
"status": "active",
"page": 0,
"size": 20,
"totalElements": 3,
"totalPages": 1
}
}
The alerts are in data (newest first); paging lives in meta (page, size, totalElements, totalPages). Page through by incrementing page. severity is one of critical, warning, info; currentValue and thresholdValue show what tripped the rule.
Get one alert
GET /v1/alerts/{guid} — the full detail of a single alert by its id.
| Path parameter | Type | Required | Description |
|---|---|---|---|
guid |
string | Yes | The alert id, as returned in the list response. |
curl https://api.verops.io/v1/alerts/b7f0e2a1-... -H "X-Api-Key: $KEY"
# -> 200 {"data": { ...alert detail... }}
# -> 404 {"error": {"code": "not_found", "message": "alert not found"}}
An unknown or non-existent id returns 404 not_found.
Inventory
The software inventory endpoints report the products your fleet runs and how much they are used. Windows are expressed in whole days.
List products
GET /v1/inventory/products — your software product list. No parameters.
curl https://api.verops.io/v1/inventory/products -H "X-Api-Key: $KEY"
# -> 200
{
"data": [
{"id": 123, "product": "Visual Studio Code", "vendor": "Microsoft",
"category": "Developer tools", "exeCount": 3, "hostCount": 84,
"activeHosts": 71, "policy": "approved"}
],
"meta": {"count": 1}
}
| Field | Meaning |
|---|---|
id |
Product id — use it with the detail endpoint. |
product / vendor / category |
The normalized product name, its vendor, and its category. |
hostCount |
How many hosts have the product installed. |
activeHosts |
How many hosts actually used it. |
policy |
The governance policy: approved, tolerated, prohibited, or needs_review. |
Get one product
GET /v1/inventory/products/{id} — detail for one product.
| Path parameter | Type | Required | Description |
|---|---|---|---|
id |
number | Yes | The product id from the list endpoint. |
curl https://api.verops.io/v1/inventory/products/123 -H "X-Api-Key: $KEY"
# -> 200 {"data": { ...product detail... }, "meta": {...}}
# -> 404 {"error": {"code": "not_found", "message": "product not found"}}
Utilization
GET /v1/inventory/utilization — per-product utilization over a window.
| Query parameter | Type | Required | Constraints | Description |
|---|---|---|---|---|
days |
number | No | 1 to 365, default 30 | Size of the look-back window in days. |
curl "https://api.verops.io/v1/inventory/utilization?days=30" \
-H "X-Api-Key: $KEY"
# -> 200
{
"data": [
{"product": "Visual Studio Code", "hoursUsed": 1240.5,
"utilizationPct": 62.3, "activeHosts": 71, "installedHosts": 84}
],
"meta": {"days": 30}
}
| Field | Meaning |
|---|---|
hoursUsed |
Total active hours across the fleet in the window. |
utilizationPct |
Usage normalized to a standard workday, as a percentage. |
activeHosts / installedHosts |
Hosts that used it versus hosts that merely have it installed. |
Summary
GET /v1/inventory/summary — an estate-wide utilization summary over a window.
| Query parameter | Type | Required | Constraints | Description |
|---|---|---|---|---|
days |
number | No | 1 to 365, default 30 | Size of the look-back window in days. |
curl "https://api.verops.io/v1/inventory/summary?days=30" \
-H "X-Api-Key: $KEY"
# -> 200
{
"data": {
"hoursUsed": 20418.0,
"weightedHours": 15230.5,
"sessions": 4120,
"activeProducts": 63,
"activeHosts": 210,
"totalProducts": 118,
"unusedProducts": 55,
"avgUtilizationPct": 41.7,
"tierBreakdown": {"power": 12, "regular": 40, "light": 30, "inactive": 36},
"trendingUp": 8,
"trendingDown": 5,
"windowDays": 30
},
"meta": {"days": 30}
}
Filtering, paging, and sorting
- Logs filter by
query,services, andlevels; request pages withpagepluspageSize, and the response reportssize,total, andhasMore; logs come newest first. - Alerts filter by
status; page withpageplussize; themetaobject carriestotalElementsandtotalPagesfor the full count. - Inventory windows are set with
days(1 to 365). The product list and detail endpoints take no window. - Time parameters everywhere accept epoch milliseconds or ISO-8601, and results are UTC.
Best practice: Discover names before you query values: callGET /v1/metrics/namesto learn exactly which metrics exist for your organization rather than guessing. For inventory, readGET /v1/inventory/summaryfirst for the headline numbers, then drill intoutilizationand individual products.
Common pitfall: Do not poll these read endpoints in a tight loop — you will burn your per-minute rate budget and start seeing 429. Poll on a sensible interval (seconds to minutes, matching how fast the data actually changes) and page through results instead of re-fetching everything.