monad-ops · API reference

monad-ops API reference

Public REST API

Read-only JSON endpoints over a single validator's execution-log telemetry. All data paths accept GET/HEAD/OPTIONS and set Access-Control-Allow-Origin: * — external dashboards may fetch directly from the browser.

Base URL for this instance: https://ops.rustemar.dev

Endpoints

PathPurpose
GET /api/state Live snapshot: uptime, blocks seen, rolling averages (1min/5min retry, TPS, gas), current epoch, reference-chain lag.
GET /api/blocks/sampled?from_ts_ms=&to_ts_ms=&points=300 Server-aggregated time-series for charts. Returns ≤points bins regardless of span, so an arbitrary window is safe.
GET /api/blocks?limit=N Recent blocks from the in-memory buffer (last ~5 min). For historical blocks, use window_summary with include_blocks=true.
GET /api/contracts/top_retried?since_ts_ms=&until_ts_ms=&min_appearances=&limit= Contracts ranked by appearance in blocks with retry_pct>0. Reads the hourly rollup — sub-50 ms for any window up to the data-retention horizon.
GET /api/contracts/labels Human-name registry for known contracts (empty unless the operator has populated labels.json).
GET /api/window_summary?from_ts_ms=&to_ts_ms=&top_contracts_limit=&include_blocks= Single-call report. Default = aggregate metrics + top contracts, any span ≤ 30 days, ~3.6 kB. include_blocks=true adds per-block series; span capped at 2 h (the length of one stress-test batch).
GET /api/alerts?limit=N Recent in-memory alerts.
GET /api/alerts/history?from_ts_ms=&to_ts_ms=&severity=&limit= Persisted alerts from SQLite. Filter by severity (warn/critical/recovered).
GET /api/reorgs?limit=N All observed reorgs (same-block-number, different-block-id events), newest-first. Each row reconstructs both block_ids (before = original observation, after = winning fork) plus the reorged block's metrics.
GET /api/reorgs/{block_number}?window=N Forensic trace around a specific reorg — the reorged block plus ±window neighbors (default 30, max 500). Returns chain-derived fields (block_number, block_id, timestamp_ms, tx_count, retried, retry_pct, gas_used). Add &level=full to include per-block execution phase timings in microseconds (tx_exec_us, commit_us, chunks). 404 if no reorg alert exists for this block.
GET /api/reorgs/{block_number}/journal Sanitized monad-bft journal lines around a reorg event — gzipped JSONL covering ~10 s before and after the block's wall-clock timestamp. Peer IPs and the local OTLP loopback are scrubbed at write time; validator pubkeys, block ids, rounds, votes and base fees pass through unchanged. 404 when the reorg pre-dates the capture feature or the journal had already rotated past the event window when the snapshot ran.
GET /api/blocks/range?from_block=&to_block=&from_ts_ms=&to_ts_ms=&limit= Historical block query backed by persistent storage. Use for post-event analysis (e.g. querying a stress-test window by block_number or ms timestamp).
GET /api/enrichment/status Operator status of the receipts-enrichment worker — enabled, attempts/succeeded/failed/dropped counters.
GET /api/probes Sanitized host-probe status (service/key/disk/fd) — name, status, summary.
GET /healthz Liveness — returns {"ok": true}.

Stress-test replay (Foundation, 2026-04-20)

Replay the three 2-hour stress batches Monad Foundation ran on testnet (epochs 532 / 533 / 534, ~3–5 k TPS at ~400 M gas/s, block utilisation touching 100 %). Each curl below pulls the aggregate summary for the epoch window this node observed: retry-rate profile, peak / average TPS and gas, top retried contracts, and an optional per-block series. Timestamps are fixed so a fresh reader gets reproducible numbers without looking up epoch boundaries.

Epoch 532 — 2026-04-20 00:00 → 05:37 UTC (batch 1)
curl -s "https://ops.rustemar.dev/api/window_summary\
?from_ts_ms=1776643200000&to_ts_ms=1776663420000&top_contracts_limit=20" \
  | jq '.aggregate'
Epoch 533 — 2026-04-20 05:37 → 11:14 UTC (batch 2)
curl -s "https://ops.rustemar.dev/api/window_summary\
?from_ts_ms=1776663420000&to_ts_ms=1776683640000&top_contracts_limit=20" \
  | jq '.aggregate'
Epoch 534 — 2026-04-20 11:14 → 16:50 UTC (batch 3)
curl -s "https://ops.rustemar.dev/api/window_summary\
?from_ts_ms=1776683640000&to_ts_ms=1776703800000&top_contracts_limit=20" \
  | jq '.aggregate'

Add &include_blocks=true to any of the above for the per-block series within a batch (capped at 2 h span on the server, so split a full epoch in half if you want the full trace). The .top_contracts array on every response ranks the heaviest re-execution contributors for that window.

Examples

Replace the base URL below with your own if running a fork.
Note: date +%s%3N is GNU coreutils. On macOS/BSD use python3 -c 'import time; print(int(time.time()*1000))' or gdate +%s%3N (from coreutils).

Current retry rate (1 m / 5 m) + epoch progress
curl -s https://ops.rustemar.dev/api/state | jq '{rtp_1m, rtp_5m, epoch}'
Aggregate summary for the last 24 hours
NOW=$(date +%s%3N)
DAY=$((24 * 3600 * 1000))
curl -s "https://ops.rustemar.dev/api/window_summary?from_ts_ms=$((NOW - DAY))&to_ts_ms=$NOW" \
  | jq '.aggregate'
Post-event block trace for a 2-hour stress batch
curl -s "https://ops.rustemar.dev/api/window_summary\
?from_ts_ms=1776531600000&to_ts_ms=1776538800000\
&include_blocks=true&top_contracts_limit=50" \
  | jq '{agg: .aggregate, contracts: (.top_contracts|length), blocks: (.blocks|length)}'
Top retried contracts in the last hour
SINCE=$(( $(date +%s%3N) - 3600000 ))
curl -s "https://ops.rustemar.dev/api/contracts/top_retried?since_ts_ms=$SINCE&limit=10" \
  | jq '.rows[] | {addr: .to_addr, ret: .retried_blocks, rtp: .avg_rtp_of_blocks}'
Retry-rate chart data for a custom window (300 bins)
curl -s "https://ops.rustemar.dev/api/blocks/sampled\
?from_ts_ms=1776531600000&to_ts_ms=1776538800000&points=300" \
  | jq '.bins | length'
All observed reorgs — compact index
curl -s https://ops.rustemar.dev/api/reorgs \
  | jq '.reorgs[] | {n: .block_number, ts: .alert_ts_ms, tx: .block.tx_count, rtp: .block.retry_pct}'
Forensic trace around a specific reorg (±30 blocks)
curl -s "https://ops.rustemar.dev/api/reorgs/26543283?window=30" \
  | jq '{before: .block_id_before, after: .block_id_after, neighbors: (.blocks|length)}'
Sanitized monad-bft journal lines around a reorg
curl -s -o reorg-27868954.jsonl.gz "https://ops.rustemar.dev/api/reorgs/27868954/journal"
zcat reorg-27868954.jsonl.gz | head -3

Response shapes — selected fields

/api/state

/api/window_summary (aggregate tier)

/api/blocks/sampled

Error responses

Scope and limitations

Source: github.com/rustemar/monad-ops. Issues / PRs welcome.