> ## Documentation Index
> Fetch the complete documentation index at: https://docs.vexlo.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Tags, coverage, health

> The tag keys a team has declared, per-service coverage and loss counters, and the server's own health.

Three read routes answer questions about a team as a whole rather than about one trace: which tag
keys exist, which services report and how much they have lost, and whether the Vexlo server itself
is healthy. Every response body on this page was captured from a server seeded with the spec's
conformance trace, on team `fixture` with environment `prod`. `$READ_TOKEN` holds a read token
whose team-set includes `fixture`.

## GET /v1/tags

Lists the tag keys seen on the team's traces, `key` ascending, with the services that declared
each key and how many distinct values it has carried.

| Parameter | Meaning |
| - | - |
| `team`, `environment` | The shared filters ([conventions](https://docs.vexlo.ai/api/conventions.md#team-and-environment-filters)). |
| `service` | One service name. |
| `limit`, `cursor` | Pagination, default 50, maximum 500. |

```bash theme={null}
curl -s -H "Authorization: Bearer $READ_TOKEN" \
  "http://127.0.0.1:18200/v1/tags?team=fixture" | jq .
```

```json theme={null}
{
  "items": [
    {
      "key": "order_id",
      "services": [
        "delivery-service"
      ],
      "distinct_value_count": 1
    }
  ],
  "limit": 50,
  "next_cursor": null
}
```

The conformance trace declares one tag, `order_id`, with one value. Call this route before
filtering traces by `tag_key` or asking for related traces: it tells you how a team spells its
keys.

## GET /v1/coverage

Reports service coverage: one row per service (or per service and environment when filtered)
with the last 24 hours of traces and loss, and the number of distinct marked functions the
function index has seen for it. The route is never paginated.

| Parameter | Meaning |
| - | - |
| `team`, `environment`, `environment_unset` | The shared filters. |
| `service` | One service name. |

```bash theme={null}
curl -s -H "Authorization: Bearer $READ_TOKEN" \
  "http://127.0.0.1:18200/v1/coverage?team=fixture" | jq .
```

```json theme={null}
{
  "services": [
    {
      "service": "delivery-service",
      "traces_24h": 1,
      "marked_functions_seen": 17,
      "records_lost_24h": 0,
      "records_shed_24h": 0,
      "last_seen_at": "2026-10-20T01:50:27.911Z"
    }
  ]
}
```

| Field | Meaning |
| - | - |
| `service` | The service name from `init()`. |
| `environment` | Present only when the request filtered by `environment`. |
| `traces_24h` | Traces first seen in the last 24 hours. |
| `marked_functions_seen` | Distinct functions the function index has observed for this service. It names what is marked, never what is not: nothing on the server knows which functions a team chose not to mark. |
| `records_lost_24h` | Records the relay daemon's heartbeats for this service reported as dropped in the last 24 hours. |
| `records_shed_24h` | Records ingest rejected with `trace_shed` in the last 24 hours. |
| `last_seen_at` | The last instant a record for one of the service's traces arrived. |

The same request narrowed to `environment=prod` adds the `environment` field to the row:

```bash theme={null}
curl -s -H "Authorization: Bearer $READ_TOKEN" \
  "http://127.0.0.1:18200/v1/coverage?team=fixture&environment=prod" | jq .
```

```json theme={null}
{
  "services": [
    {
      "service": "delivery-service",
      "environment": "prod",
      "traces_24h": 1,
      "marked_functions_seen": 17,
      "records_lost_24h": 0,
      "records_shed_24h": 0,
      "last_seen_at": "2026-10-20T01:50:27.911Z"
    }
  ]
}
```

The route does not enumerate a team's environments. Without `?environment=`, every environment
folds into one row per service that carries no `environment` field. Each row of
[`GET /v1/traces`](https://docs.vexlo.ai/api/traces#get-/v1/traces) carries its own `environment` instead. Per-trace
loss facts live in each trace's [coverage block](https://docs.vexlo.ai/api/conventions.md#the-coverage-block).

## GET /v1/health

Reports the server's storage state and, for the token's team-set, each service's recent loss.
The route is authenticated.

| Parameter | Meaning |
| - | - |
| `team`, `environment`, `environment_unset` | The shared filters. |
| `service` | One service name. |

```bash theme={null}
curl -s -H "Authorization: Bearer $READ_TOKEN" \
  "http://127.0.0.1:18200/v1/health?team=fixture" | jq .
```

```json theme={null}
{
  "status": "healthy",
  "mode": "normal",
  "shape_store": {
    "disk_used_bytes": 143360,
    "effective_retention_days": 7
  },
  "value_store": {
    "bytes_used": 6168,
    "byte_budget": 21474836480,
    "effective_retention_estimate_hours": 0
  },
  "stubs_swept_24h": 0,
  "services": [
    {
      "service": "delivery-service",
      "records_lost_24h": 0,
      "records_shed_24h": 0,
      "last_seen_at": "2026-10-20T01:50:27.911Z"
    }
  ]
}
```

| Field | Meaning |
| - | - |
| `status` | `healthy` or `degraded`. |
| `mode` | `normal`, or `shape_only` once the value store has reached its byte budget and the server keeps ingesting shape without values. |
| `shape_store.disk_used_bytes` | Bytes the shape store occupies. |
| `shape_store.effective_retention_days` | Reports 7, the default shape retention in days. |
| `value_store.bytes_used`, `value_store.byte_budget` | Value bytes held against the configured budget. |
| `value_store.effective_retention_estimate_hours` | Reports 0: the route has no write rate to estimate from. `vexlo check` computes the estimate from an expected write rate instead. |
| `stubs_swept_24h` | Traces retention swept in the token's team-set because no `trace-open` ever arrived for them. |
| `services[]` | One row per service with activity in the token's team-set: `service`, `environment` (when filtered), `records_lost_24h`, `records_shed_24h`, `last_seen_at`. |

`stubs_swept_24h` is team-level rather than per service: a trace whose `trace-open` never
arrived has no service, because that is the record the field lives on. A non-zero value with no
matching `records_lost_24h` means records are reaching the server whose `trace-open` did not.

A healthy server answers `200`. A degraded one answers `503` with the same body shape and
`"status": "degraded"`; no degraded response is shown here because none was captured. The
`503` body is data, not the error envelope.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.