Real-time streaming
OmbraChain exposes two streaming interfaces:
- SSE (Server-Sent Events) — uni-directional, easy via plain HTTP
- WebSocket — bi-directional, supports custom channel subscriptions
SSE: chain events
GET https://api.ombra-net.com/api/chain/events
Event format:
event: hello
data: {"height": 62512, "latestBlockHash": "8592559f..."}
event: block
data: {"index": 62513, "hash": "...", "timestamp": 1735389957000, "proposer": "...", "transactions": [...]}
event: ping
data: {"ts": 1735389959000}
block fires once per new block (~15s cadence). ping every 2s as heartbeat.
- cURL
- TypeScript
- Python
- Go
curl -N https://api.ombra-net.com/api/chain/events
import { OmbraClient } from "@ombrachain/sdk";
const client = new OmbraClient({ endpoint: "https://api.ombra-net.com" });
const sub = client.events.subscribeChain((event) => {
if (event.type === "block") {
console.log("new block", event.data.index);
}
});
// Later: sub.close();
import httpx
with httpx.stream("GET", "https://api.ombra-net.com/api/chain/events") as r:
for line in r.iter_lines():
if line.startswith("data:"):
print(line[6:])
client.StreamEvents(ctx, func(evt map[string]interface{}) bool {
fmt.Println(evt)
return true
})
SSE: mempool snapshots
GET https://api.ombra-net.com/api/mempool/events
Emits event: snapshot every 3s with {"total": N, "ts": ...}. Useful for live mempool counters.
WebSocket: multi-channel
WSS wss://api.ombra-net.com/api/ws
Bi-directional. Client subscribes to channels:
→ {"action": "subscribe", "channel": "blocks"}
← {"type": "subscribed", "channel": "blocks"}
← {"type": "block", "data": {...}}
← {"type": "block", "data": {...}}
→ {"action": "unsubscribe", "channel": "blocks"}
Channels:
blocks— every new blocktxs— every tx accepted to mempoolmempool— periodic mempool size snapshotsagent— Fork V6 agent run updates (claimed, step, finished)chat— Fork V6 chat turns
- Browser JS
- Node TypeScript
- Python
const ws = new WebSocket("wss://api.ombra-net.com/api/ws");
ws.onopen = () => ws.send(JSON.stringify({ action: "subscribe", channel: "blocks" }));
ws.onmessage = (e) => {
const msg = JSON.parse(e.data);
console.log(msg.type, msg.data);
};
import WebSocket from "ws";
const ws = new WebSocket("wss://api.ombra-net.com/api/ws");
ws.on("open", () => ws.send(JSON.stringify({ action: "subscribe", channel: "txs" })));
ws.on("message", (data) => console.log(JSON.parse(data.toString())));
import asyncio
import websockets
import json
async def main():
async with websockets.connect("wss://api.ombra-net.com/api/ws") as ws:
await ws.send(json.dumps({"action": "subscribe", "channel": "blocks"}))
async for msg in ws:
print(json.loads(msg))
asyncio.run(main())
Reconnection
SSE clients should reconnect on disconnect. The SDKs handle this automatically. Default backoff: 1s, 2s, 4s, 8s (cap 30s).
For WebSocket, send {"action": "ping"} every 30s to keep idle connections alive (server pings on its own too).
Rate limits
Streaming endpoints count toward your API key's RPM via opened connections. Tier 1 allows 10 concurrent SSE/WS connections per key.
See Recipes › Subscribe events for production patterns (retry, deduplication).