Skip to content

Monitor HTTP API

The Blop collector exposes a loopback HTTP API for standard OpenTelemetry ingestion and bounded JSON queries. Coding agents should normally call the blop CLI because it supplies stable blop.cli/v1 envelopes, safe defaults, and documented exit codes. Use the HTTP API for SDK export, integrations, or clients that need direct access.

The default base URL is http://127.0.0.1:27686. A running collector provides:

Route Purpose
GET /api/health Liveness, collector identity, store path, retention, and row counts
GET /openapi.json Machine-readable OpenAPI 3.0.3 document
GET /docs Dependency-free HTML route index

Set BLOP_MONITOR_URL when a client should target a non-default collector. The CLI can also discover registered local instances by working directory; direct HTTP clients must choose their base URL explicitly.

Route Accepted payloads Success
POST /v1/traces OTLP/HTTP JSON or Protobuf { "accepted": SPAN_COUNT }
POST /v1/logs OTLP/HTTP JSON or Protobuf { "accepted": LOG_COUNT }

Use Content-Type: application/json or application/x-protobuf. Both routes accept Content-Encoding: gzip. Blop applies the request-size cap after decompression as well as on the transferred body. Invalid payloads return 400, oversized payloads return 413, and storage failures return 500.

Ingestion is idempotent for the same OpenTelemetry identifiers. SQLite writes run in a dedicated worker thread and complete before the response is sent, so a successful response establishes query visibility without blocking health and query handling on the HTTP event loop.

All list routes are time- and result-bounded. Durations use values such as 15m, 2h, and 1d; cursors are opaque and should be copied from meta.nextCursor without decoding them.

Route Purpose Main query parameters
GET /api/services Active service names lookback
GET /api/traces Trace summaries service, status, operation, durationMin, lookback, limit, cursor, attr.KEY
GET /api/traces/search Alias of /api/traces Same as /api/traces
GET /api/traces/stats Grouped trace aggregates groupBy, agg, plus trace filters
GET /api/traces/:traceId Full trace and span tree include
GET /api/traces/:traceId/spans Flat span list for one trace None
GET /api/traces/:traceId/logs Correlated logs lookback, limit, cursor
GET /api/spans/search Direct span search service, traceId, operation, parentOperation, status, lookback, limit, attr.KEY, attrContains.KEY
GET /api/spans/:spanId One span with trace context None
GET /api/spans/:spanId/logs Correlated logs lookback, limit, cursor
GET /api/logs Log search service, severity, traceId, spanId, body or contains, lookback, limit, cursor, attr.KEY, attrContains.KEY
GET /api/logs/search Alias of /api/logs Same as /api/logs
GET /api/logs/stats Grouped log counts groupBy, agg=count, plus log filters
GET /api/facets Facet values and counts type, field, key, service, lookback, limit
GET /api/audit Deterministic audit findings service, lookbackMinutes, baselineMinutes, durationMin

Trace groupBy values are service, operation, status, or attr.KEY. Trace agg values are count, avg_duration, p95_duration, and error_rate. Log groups are service, severity, scope, or attr.KEY; log aggregation currently supports count.

Set type=traces with field=service|operation|status|attribute_keys|attribute_values. attribute_values also requires key. Set type=logs with field=service|severity|scope.

List routes return data plus page metadata in the collector’s camelCase HTTP format:

{
"data": [],
"meta": {
"limit": 20,
"lookback": "15m",
"returned": 0,
"truncated": false,
"nextCursor": null
}
}

The CLI translates this to its versioned snake_case envelope. HTTP errors are JSON objects with an error string.

The default collector binds only to 127.0.0.1. Binding to another interface is an explicit trust decision: this first release has no HTTP authentication or TLS. The collector parses telemetry and serves stored evidence; it does not execute application code, agent commands, scripts, or browser actions.