Beacon API reverse proxy (CL path router)
https://api.triport.io/rpc/eth-beacon/eth/v1/node/syncingForwards Ethereum Consensus-Layer (Beacon) REST calls through to Triport's pooled CL nodes (Prysm / Lighthouse / Nimbus), with tier, family, and rate-limit enforcement applied per path.
This endpoint is a path router that sits in front of Triport's Consensus-Layer
node pool. You issue a normal Beacon Node REST API
request, but prefixed with /rpc/eth-beacon/, and the platform picks a healthy
CL host, forwards your GET, and streams the upstream response back to you with
provider-identifying headers and fields removed.
The router exposes a curated whitelist of standard CL paths rather than the entire Beacon API surface. Paths fall into two groups:
- Any-family standard paths (
/eth/v1/node/*,/eth/v1/debug/*) — served by whatever CL client is healthy. - Client-specific namespaces (
/lighthouse/*,/prysm/*+/eth/v1alpha1/*,/nimbus/*) — routed only to a host of the matching family.
A request to a path that is not on the whitelist returns 404 route_not_found;
the surface is intentionally closed. The router accepts GET only — every
other HTTP method returns 405 method_not_allowed.
Two behaviours are worth calling out up front:
- The Server-Sent Events stream
/rpc/eth-beacon/eth/v1/eventsis handled by a separate, higher-specificity handler — see the Beacon events (SSE) page. If that handler is not mounted, the path router returns501 sse_handler_not_wiredfor it rather than attempting a normal forward. - Tier and per-path rate limits are enforced here. Heavy amplifier paths (state dumps, Lighthouse analysis) require higher tiers and have much lower per-customer RPS ceilings (see Notes).
Parameters
The "parameter" is the Beacon API path you append after /rpc/eth-beacon/, plus
any query string, which is forwarded verbatim to the upstream node. Only the
paths below are routable.
Path: any CL familyobjectPath: Lighthouse familyobjectPath: Prysm familyobjectPath: Nimbus familyobjectHeadersobjectResponse
The upstream Beacon API response body is returned unchanged except that
operator-identifying fields are stripped. Headers are passed through, except that
Server is replaced with Triport and hop-by-hop / Content-Length headers
are recomputed.
data.head_slotstringdata.sync_distancestring0 when fully synced).data.is_syncingbooleandata.is_optimisticbooleandata.el_offlinebooleanErrors
Errors use a stable typed envelope:
{ "error": "route_not_found", "code": 404 }| Code | error value | When it happens |
|---|---|---|
| 403 | namespace_disabled | Path resolves to a classified/admin capability that is not exposed. |
| 404 | route_not_found | Path is not on the routable whitelist (or is exactly /rpc/eth-beacon/). |
| 405 | method_not_allowed | Any HTTP method other than GET. |
| 500 | router_not_initialized | CL pool is not configured on this deployment. |
| 501 | sse_handler_not_wired | /eth/v1/events reached the path router with no SSE handler mounted. |
| 503 | cl_beacon_unavailable | No healthy CL host of the required family after a retry. |
| 503 | cl_archive_unavailable | Same as above for archive state-dump paths when strict archive routing is on. |
4xx responses produced by the upstream Beacon node (e.g. 404 for an unknown
slot, 400 for a malformed query) are forwarded to you as-is — those are
legitimate Beacon API responses, not Triport errors. See the shared
Errors page for the full envelope contract.
Examples
JavaScript (fetch)
const res = await fetch(
"https://api.triport.io/rpc/eth-beacon/eth/v1/node/syncing",
{ headers: { Authorization: `Bearer ${process.env.TRIPORT_API_KEY}` } }
);
if (!res.ok) {
const { error, code } = await res.json();
throw new Error(`beacon proxy error ${code}: ${error}`);
}
const { data } = await res.json();
console.log("head slot:", data.head_slot, "syncing:", data.is_syncing);TypeScript SDK (@triport/sdk)
import { Triport } from "@triport/sdk";
const tp = new Triport({ apiKey: process.env.TRIPORT_API_KEY! });
// Generic Beacon REST passthrough — path is appended to /rpc/eth-beacon/
const { data } = await tp.ethereum.beacon.get("/eth/v1/node/syncing");
console.log(data.head_slot, data.is_syncing);Python (triport-sdk)
import os
from triport import Triport
tp = Triport(api_key=os.environ["TRIPORT_API_KEY"])
resp = tp.ethereum.beacon.get("/eth/v1/node/syncing")
print(resp["data"]["head_slot"], resp["data"]["is_syncing"])Notes
- Closed whitelist. Only the paths listed under Parameters are
routable; this is not an open passthrough of the entire Beacon API. Anything
else returns
404 route_not_found. - GET only. The router never forwards mutating methods.
- Family routing.
/lighthouse/*,/prysm/*+/eth/v1alpha1/*, and/nimbus/*are routed only to a CL host of the matching client family. If no such host is healthy, you get503 cl_beacon_unavailablerather than a cross-family response. - Failover. The router tries up to two healthy hosts per request before
returning
503. - Rate limits are per-path classes, not a daily quota:
light— 5 rps per customer (most node/diagnostic reads).state_dump— 0.5 rps per customer + 5 rps aggregate per host (/eth/v1/debug/beacon/states/{slot}, bodies up to ~226 MiB).lh_analysis— 0.2 rps per customer + 10 rps aggregate per host (/lighthouse/analysis/*, bodies up to ~230 MB). Response bodies are capped at 256 MiB.
- Related pages: Beacon events (SSE) for the
/eth/v1/eventslive stream, and the Ethereum JSON-RPC transport for Execution-Layer calls.