Get a single chain
https://api.triport.io/v1/chains/ethFetch one chain's static descriptor — identity, protocols, required scope, UI hints — plus its latest live health metrics, by chain id.
Returns the ChainDescriptor for a single chain identified
by its stable id (eth, polygon, sol, …), wrapped together with the
chain's most recent metrics snapshot. Use it to render a single chain's detail
page or to confirm a chain id is part of the catalogue before composing
endpoint URLs.
The descriptor itself is public: if you know a chain's id you get its descriptor, regardless of authentication or scope. The catalogue is treated as marketing/discovery data — scope gating happens on the list endpoint and on the per-key endpoints surface, not here. The only reason this endpoint returns 404 is an unknown id.
The metrics block is best-effort. It carries the latest health snapshot when
the metrics aggregator is wired in; if metrics are unavailable the field is
null and the descriptor still returns 200. A chain's runtime health is
expressed by metrics.status, a closed union — see
Response fields.
scope_missingis a status, not an error.scope_missingis one of the values in themetrics.statusunion. It marks a chain as visible but permission-gated — your key does not hold the chain'srequired_scope— rather than hiding it. It describes permission, never upstream health (contrastdegraded/down). For a key-specific view of which chains you can actually call, useGET /v1/keys/{id}/endpoints.
Parameters
Path parameters
idstringrequiredeth, polygon, sol, base, bsc, arbitrum, op, bitcoin, sol-devnet.Response
200 OK — the descriptor paired with the latest metrics snapshot:
When no metrics aggregator is configured, metrics is null:
{ "chain": { "id": "eth", "...": "..." }, "metrics": null }chainobjectChainDescriptor. Immutable for the lifetime of a release.chain.idstringchain.namestringchain.chain_idnumbereth=1, polygon=137). Synthetic for non-EVM (sol=101, sol-devnet=103); -1 for bitcoin (no EIP-155 id).chain.netstringmainnet | testnet | devnet.chain.kindstringevm | l2 | non-evm.chain.symbolstringETH, POL, SOL, …).chain.protocolsarraykind (https | wss | grpc), path, optional note. The path is internal — compose public URLs from your key's endpoints, not from this field.chain.required_scopestringeth:rpc).chain.uiobjectcolor, glow, logo_bg, initials.chain.capabilitiesarray?Archive, Trace API, WebSocket, …). Omitted when empty.metricsobject | nullnull when metrics are unavailable.metrics.statusstringmetrics.latency_p50_ms / latency_p95_msnumber | nullnull until samples exist.metrics.uptime_24h_pct / uptime_7d_pctnumber | nullnull for empty windows.metrics.block_height / block_finalizednumber | nullmetrics.peersnumber | nullnull on non-EVM.metrics.sync_statusboolean | nullmetrics.gas_price_nativestring | null"12.4 Gwei"). EVM/L2 only.metrics.epochnumber | nullmetrics.tpsnumber | nullmetrics.last_seen_ago_secnumber | nullmetrics.measured_atstringErrors
The error envelope is { "error": "<code>" }.
| Code | HTTP | Meaning | When it happens |
|---|---|---|---|
chain_not_found | 404 | Unknown chain id | The {id} segment is not a registered chain. |
method_not_allowed | 405 | Wrong HTTP method | Any verb other than GET. |
See errors.md for the shared error envelope and conventions.
Examples
JavaScript (fetch)
const res = await fetch("https://api.triport.io/v1/chains/eth", {
headers: { Authorization: `Bearer ${process.env.TRIPORT_API_KEY}` },
});
if (!res.ok) {
const { error } = await res.json(); // e.g. "chain_not_found"
throw new Error(error);
}
const { chain, metrics } = await res.json();
console.log(chain.name, metrics?.status ?? "no-metrics");TypeScript SDK (@triport/sdk)
import { Triport } from "@triport/sdk";
const triport = new Triport({ apiKey: process.env.TRIPORT_API_KEY! });
const { chain, metrics } = await triport.chains.get("eth");
// chain: ChainDescriptor, metrics: ChainMetrics | null
if (metrics && metrics.status === "scope_missing") {
console.warn(`${chain.name}: key is missing scope ${chain.required_scope}`);
}Python (triport-sdk)
from triport import Triport
triport = Triport(api_key=os.environ["TRIPORT_API_KEY"])
result = triport.chains.get("eth")
print(result.chain.name)
if result.metrics is not None:
print(result.metrics.status, result.metrics.latency_p50_ms)Notes
- Descriptor is public; metrics are best-effort. A known id always yields
200with the descriptor;metricsmay benullif the aggregator is not wired. Only an unknown id produces404. - Don't build URLs from
protocols[].path. Those paths are internal backend routes. Get callable, key-scoped URLs fromGET /v1/keys/{id}/endpoints. - Related endpoints:
GET /v1/chains(list / scope-filtered catalogue),GET /v1/chains/{id}/metrics(metrics only),GET /v1/chains/{id}/metrics/series(bucketed history), andGET /v1/chains/events(live SSE status + metric ticks).