Beacon events SSE stream
https://api.triport.io/rpc/eth-beacon/eth/v1/events?topics=head&topics=finalized_checkpointSubscribe to Ethereum consensus-layer (beacon chain) events — new heads, finalized checkpoints, and more — as a live Server-Sent Events stream.
This endpoint opens a long-lived Server-Sent Events (SSE) stream of Ethereum consensus-layer (beacon chain) events. Rather than polling the beacon REST API for the latest head or checkpoint, you keep one HTTP connection open and receive events as they happen — for example a head event each time the chain advances, or a finalized_checkpoint event when finality moves forward.
The stream is served by a dedicated SSE handler, separate from the general beacon REST passthrough router. Internally it fans a single upstream event stream out to all subscribers, so it is the right tool for driving real-time UIs (block tickers, finality indicators) or triggering work when the chain head or finality changes.
Requests are routed to consensus-layer hosts advertising the beacon-events capability. If no such host is currently healthy, the request fails — see Errors.
Gotcha: This is a streaming response, not a one-shot JSON body. Your client must read the connection incrementally and keep it open. Standard JSON/
fetch().json()clients that wait for the body to close will hang. Use an SSE-aware client (EventSource,fetchwith a stream reader, orsseclientin Python).
Parameters
This endpoint follows the standard Ethereum Beacon API /eth/v1/events contract.
Query parametersobjecttopicsstring (repeatable)required?topics=head&topics=finalized_checkpoint. Common topics: head, finalized_checkpoint, block, attestation, voluntary_exit, chain_reorg, contribution_and_proof.Response
The response is an open stream with Content-Type: text/event-stream. Each event is delivered as an SSE frame: an event: line naming the topic followed by a data: line carrying a JSON payload, separated by a blank line.
slotstringblockstringstatestringepoch_transitionbooleantrue if this head crosses an epoch boundary.previous_duty_dependent_rootstringcurrent_duty_dependent_rootstringexecution_optimisticbooleantrue if the node has not yet fully validated the execution payload.Errors
| Code | Meaning | When it happens |
|---|---|---|
400 | Bad Request | The required topics query param is missing. |
401 | Unauthorized | Missing or invalid API key. |
500 | Internal Server Error | The connection does not support streaming (flushing). |
502 | Bad Gateway | The upstream consensus-layer connection failed while opening the stream. |
503 | Service Unavailable | No consensus-layer host with the beacon-events capability is currently available. |
Errors returned before the stream opens use the shared JSON error envelope — see errors.md. Once the stream is open, the connection may also be closed by the server or upstream; clients should reconnect.
Examples
JavaScript (fetch)
The browser EventSource API cannot set an Authorization header — for it, pass the key as ?api-key=$TRIPORT_API_KEY in the URL. To use the Bearer header instead, read the stream manually with fetch:
const res = await fetch(
"https://api.triport.io/rpc/eth-beacon/eth/v1/events?topics=head&topics=finalized_checkpoint",
{
headers: {
Authorization: `Bearer ${process.env.TRIPORT_API_KEY}`,
Accept: "text/event-stream",
},
}
);
const reader = res.body.getReader();
const decoder = new TextDecoder();
let buf = "";
while (true) {
const { value, done } = await reader.read();
if (done) break;
buf += decoder.decode(value, { stream: true });
let sep;
while ((sep = buf.indexOf("\n\n")) !== -1) {
const frame = buf.slice(0, sep);
buf = buf.slice(sep + 2);
const event = frame.match(/^event:\s*(.*)$/m)?.[1];
const data = frame.match(/^data:\s*(.*)$/m)?.[1];
if (data) console.log(event, JSON.parse(data));
}
}TypeScript SDK (@triport/sdk)
import { Triport } from "@triport/sdk";
const triport = new Triport({ apiKey: process.env.TRIPORT_API_KEY! });
const stream = triport.eth.beacon.events({
topics: ["head", "finalized_checkpoint"],
});
for await (const event of stream) {
console.log(event.topic, event.data);
}Python (triport-sdk)
import os
from triport import Triport
client = Triport(api_key=os.environ["TRIPORT_API_KEY"])
with client.eth.beacon.events(topics=["head", "finalized_checkpoint"]) as stream:
for event in stream:
print(event.topic, event.data)Notes
-
Max stream duration scales with plan. The server holds each stream open for a bounded window, after which it cleanly closes the connection and you should reconnect:
Plan Max duration per stream Starter (and Free / unrecognized) 60 seconds Growth 5 minutes Scale 1 hour This is a per-connection lifetime cap, not a request rate limit; reconnect when the stream closes to keep receiving events.
-
1:1 passthrough. Events are streamed straight from a consensus-layer host to your connection with no buffering or de-duplication. Responses set
Cache-Control: no-cacheand disable proxy buffering. -
One long-lived connection. Hold the stream open and consume events incrementally; do not poll this endpoint.
-
Subscribe to multiple topics by repeating
topicsin the query string. Each event frame names its topic in theevent:line so you can demultiplex client-side. -
Reconnect on drop. Networks and upstream hosts cycle; treat a closed stream as normal and reconnect with backoff. You may briefly miss events across a reconnect, so reconcile against the latest head if exact continuity matters.
-
For one-off reads of beacon chain state (rather than a live stream), use the general consensus-layer REST passthrough under
/rpc/eth-beacon/(any other/rpc/eth-beacon/*path). -
For execution-layer JSON-RPC, see the Ethereum RPC transport reference.