Polygon node Prometheus metrics mirror
https://api.triport.io/v1/polygon/metrics/bor-eu-1/borProxies the raw Prometheus exposition from a specific Polygon node (Bor, Heimdall, or an aggregator Prometheus) so you can scrape per-node chain metrics through the Triport edge.
The metrics mirror fetches the Prometheus text exposition from a single Polygon node and streams it back to you unchanged (after a light sanitization pass). It covers three node layers:
bor— the Bor execution client (Geth-style metrics).heimdall— the Heimdall consensus client (CometBFT default metrics).aggregator— an operator-side Prometheus that already aggregates a pool of nodes.
This is not an OpenAPI-defined product endpoint; it is an operational surface for teams that want to pull node-level chain metrics (block height, peer counts, txpool depth, consensus round timings, etc.) into their own Prometheus or Grafana without direct network access to the nodes.
Responses are served from a short-lived cache. The X-Cache response header tells
you whether the body was a fresh upstream fetch (MISS), a cache hit (HIT), or a
stale copy served because the node was briefly unavailable (STALE). The body is
standard Prometheus exposition (text/plain; version=0.0.4), not JSON — point a
scrape job at it directly.
Gotcha: the path is two segments —
{host_id}then{layer}. A request to/v1/polygon/metrics/heimdall(layer only, no host id) returns404 path_invalid.
Parameters
Path parameters
host_idstringrequiredlayerstringrequiredbor, heimdall, aggregator.Response
On success the body is raw Prometheus exposition:
Response headers
| Header | Example | Description |
|---|---|---|
Content-Type | text/plain; version=0.0.4 | Prometheus exposition format. |
X-Cache | MISS | Cache state of this body: HIT, MISS, or STALE. |
X-Mesh-Source | polygon-prom-mirror | Identifies the serving subsystem. |
Content-Length | 2048 | Body length in bytes. |
Errors
The error body is the shared JSON envelope: {"error":{"code":"...","message":"..."}}.
See errors.md for the full envelope.
| Code | HTTP | Meaning | When it happens |
|---|---|---|---|
unauthorized | 401 | Missing or invalid credentials | No valid session/API key on the request. |
tier_locked | 403 | Plan lacks polygon.chain_metrics | Plan does not include the feature. Currently returned for all callers while the gate is a stub. |
| — | 429 | Rate limit exceeded | Per-tier RPS (with burst) exhausted. Retry after backoff. |
Additional non-success codes you may encounter once authorized:
| Code | HTTP | When it happens |
|---|---|---|
path_invalid | 404 | Path is not exactly /{host_id}/{layer}. |
unknown_layer | 404 | layer is not bor / heimdall / aggregator. |
host_not_found | 404 | No node with host_id exists in that layer. |
host_no_capability | 404 | The node does not expose Prometheus for that layer. |
method_not_allowed | 405 | Only GET is supported. |
host_quarantined | 503 | Node unavailable and no cached body to fall back to. |
upstream_error | 502 | Upstream scrape failed and no stale cache available. |
Examples
JavaScript (fetch)
const res = await fetch(
"https://api.triport.io/v1/polygon/metrics/bor-eu-1/bor",
{ headers: { Authorization: `Bearer ${process.env.TRIPORT_API_KEY}` } }
);
if (!res.ok) throw new Error(`metrics mirror: ${res.status}`);
console.log(res.headers.get("X-Cache")); // HIT | MISS | STALE
const exposition = await res.text();
console.log(exposition);TypeScript SDK (@triport/sdk)
import { Triport } from "@triport/sdk";
const triport = new Triport({ apiKey: process.env.TRIPORT_API_KEY! });
const { body, cache } = await triport.polygon.metrics.mirror({
hostId: "bor-eu-1",
layer: "bor",
});
console.log(cache); // "MISS"
console.log(body); // Prometheus exposition textPython (triport-sdk)
import os
from triport import Triport
triport = Triport(api_key=os.environ["TRIPORT_API_KEY"])
result = triport.polygon.metrics.mirror(host_id="bor-eu-1", layer="bor")
print(result.cache) # "MISS"
print(result.body) # Prometheus exposition textNotes
- Cache & staleness: bodies are cached briefly. When a node is quarantined or
degraded, the mirror serves the last good body with
X-Cache: STALErather than failing — useful for keeping dashboards populated through short blips. Only when no cached body exists does the call return503 host_quarantined. - Scrape interval: because responses are cached, scraping faster than the cache
TTL yields repeated
HITbodies; align your Prometheus scrape interval with how fresh you actually need the data. - Layers are independent: each
{host_id, layer}pair is mirrored from a different upstream path and port. A node may exposebormetrics but notaggregatormetrics — expecthost_no_capabilityin that case. - No daily cap: rate limiting is RPS-per-tier with burst; there is no daily quota header or daily-quota error.
- Related: the loopback-only mesh health endpoint and the Polygon WebSocket firehose handlers live alongside this mirror in the same Polygon node-mesh surface.