Skip to main content
All endpoints are under https://api.mirador.org and require a server key. Responses are scoped to the key’s project.
This page is the practical reference. For the exact, always-current contract — including every schema, bound, and enum — use the Swagger UI, OpenAPI spec, or llms.txt.

Endpoint map

Required parameters are bold; (value) is the default when the parameter is omitted.
When composing requests with filters, PromQL, or timestamps, use curl -G --data-urlencode rather than hand-escaping query strings. And prefer -sS --fail-with-body over -f — bare -f discards the response body on errors, hiding the typed {"error": ...} envelope that tells you what to fix.

Time windows

Where supported, since/until, start/end, and metric time accept RFC 3339 (2026-07-27T14:00:00Z) or a relative age (90s, 15m, 2h, 7d). Relative values mean “that long ago.” Pin absolute timestamps when comparing multiple queries — relative windows move between requests. Telemetry since/until windows are half-open: [since, until). Metric range queries follow Prometheus semantics and include both start and end when they land on the step. Responses echo the window actually read where their schema provides range_start/range_end — trust those values over client-side arithmetic.

Pagination

Trace and log lists are newest-first and use page_size (default 100, range 1–1000) plus an opaque next_page_token. This is cursor pagination, not numbered pagination — there is no page, per_page, or total_pages.
  • Continue until next_page_token is absent. A short or empty page may still carry a token.
  • A token carries its resolved window, filter, and page size — GET ...?page_token=<token> is a complete next request. Don’t add since/until alongside a token.
  • Tokens are signal-specific: never exchange them between trace and log endpoints, and never parse them.
Counting: trace pages include an exact top-level total, so page_size=1 plus total is the cheapest trace count. Log pages have no total — use /v1/logs/stats?interval=whole when you need a log count.

Filtering

Trace and log filter parameters use AIP-160 expressions. The filterable fields differ per signal — see trace filters and log filters — but the grammar rules are shared:
  • Quote every value: status="completed", never status=completed.
  • AND combines fields. OR groups must stay on one fieldstatus="running" OR status="completed" ✅; status="running" OR severity="error" ❌ (400, never silently broadened).
  • NOT inverts a single leaf.
  • Attribute dots are literal key characters, not paths. attribute.header.country="US" and the canonical attribute."header.country"="US" both address the key header.country. Quote keys containing hyphens.
  • Missing and empty compare equally with =: attribute.k="" matches records where k is absent, and attribute.k!="x" includes them. Use attribute.k:* (present) and NOT attribute.k:* (absent) to distinguish presence from absence.
  • The decoded expression may contain at most 4096 UTF-8 bytes; an OR group holds at most 64 values of ≤256 bytes each; at most 16 attribute-equality predicates per query.
  • Discover keys before filtering — use the trace and log catalogues rather than guessing names. Sampled values are hints, not exhaustive sets.
URL-encode the filter value when issuing the request — or let curl -G --data-urlencode do it.

Errors

Every error, including rate limiting, uses a typed envelope. Switch on the stable error.code, not the human-readable message. Every 500 includes error.details[0].request_id — quote it when reporting an issue.

Next Steps

Traces

Discovery, trace filters, aggregates, and events

Logs

Stats, records, log filters, and the SSE stream

Metrics

The metric catalogue and PromQL queries