Docs

Public API

The data behind the public pages is a read-only JSON API at https://app.roundbeat.com/api. No key, no sign-in. The examples below are real mainnet responses captured on 13 Oct 2026 (a snapshot, not live), trimmed to the fields that matter.

Basics

Base URL
https://app.roundbeat.com. Every path starts with /api.
Methods
GET only. Responses are JSON, gzip-compressed when you ask for it.
Errors
A 4xx with {"error": "…"}: 400 for a bad parameter (an unknown module, an invalid slot), 404 for something that does not exist.
Modules
A module parameter takes the ID or a slug: 1/curated (also curated-v1), 2/simpledvt (also dvt), 3/csm, 4/curated-v2 (also cmv2). An unknown value is a 400.
Operator IDs
Unique only inside a module. Always pass moduleId to the operator endpoints; without it the API merges that ID across modules and answers with the header Warning: 299 - "moduleId required".
Time windows
time takes 1h, 6h, 24h, 7d or 30d; anything else means all time. An operator’s proposals and events lists echo the window they applied as time (null for all time).
Numbers
ETH amounts are numbers in ETH. Wei and gwei amounts (balances, rewards, bids) are strings, so they keep full precision. Some counts and epochs are strings too, as shown.
Caching
The aggregate endpoints are cached on the server (overview 2 minutes, module summaries 2 minutes, health 1 minute, migration 5 minutes) and send Cache-Control and ETag; repeat a request with If-None-Match to get a 304. Polling faster than the cache gains nothing.
Browsers
The API does not send CORS headers for other sites, so a web page on another domain cannot call it from the browser. Call it from a server, a script or curl.

Network

Data freshness

GET /api/status

How far Roundbeat’s beacon node trails the wall clock. stale turns true when it is more than 64 slots behind; the app then shows its “Chain data delayed” banner.

Request
curl -s 'https://app.roundbeat.com/api/status'
Response (trimmed)
{
  "network": "mainnet",
  "dataFreshness": {
    "beaconHeadSlot": 15421335,
    "expectedSlot": 15421335,
    "lagSlots": 0,
    "stale": false,
    "staleSince": null,
    "checkedAt": "2026-10-13T08:27:33.683378348Z",
    "known": true
  }
}

Network overview

GET /api/indexed/overview

Lido-wide totals, per-module validator counts and how far indexing trails the head (lag, in epochs). liveOperators counts operators with validators on the beacon chain; operators counts every registered operator, including those with none yet or none left. depositedKeys is the keys Lido has deposited to, and totalValidators the Lido validators on the beacon chain; both include exited ones. alerts counts events by severity, all time and over the last 24 h, from beacon-chain events only: the event feed also counts on-chain contract events, so its totals can be higher. The response also lists the latest events.

Request
curl -s 'https://app.roundbeat.com/api/indexed/overview'
Response (trimmed)
{
  "network": "mainnet",
  "overview": {
    "epoch": 481915,
    "operators": 793,
    "liveOperators": 509,
    "activeValidators": 233680,
    "totalValidators": 493140,
    "depositedKeys": 502022,
    "totalEffectiveEth": 9250776,
    "totalStakedEth": 9253766.831017949,
    "proposalsMade": 304763,
    "proposalsMissed": 536
  },
  "modules": [
    { "moduleId": 4, "total": 4567, "active": 4442, "slashed": 0 }
  ],
  "indexer": {
    "running": true,
    "lastIndexedEpoch": 481915,
    "currentEpoch": 481916,
    "lag": 1,
    "headKnown": true
  },
  "alerts": {
    "critical": { "total": 292111, "last24h": 1012 },
    "warning": { "total": 28186, "last24h": 1 },
    "info": 817608
  }
}

Modules

GET /api/modules

The staking modules with their IDs, slugs, contract addresses and credentials type (wcType 1 is 0x01, 2 is 0x02).

Request
curl -s 'https://app.roundbeat.com/api/modules'
Response (trimmed)
{
  "network": "mainnet",
  "modules": [
    {
      "id": 4,
      "slug": "curated-v2",
      "name": "Curated v2",
      "wcType": 2,
      "address": "0xda5f930ce326eb5205085d66c72a4e79d60cb8c1",
      "indexed": true,
      "activeValidators": 4442,
      "balanceEth": 1916036.69,
      "effectiveEth": 1915160
    }
  ]
}

Contract addresses

GET /api/network

The Lido contract addresses the Contracts page lists.

Request
curl -s 'https://app.roundbeat.com/api/network'
Response (trimmed)
{
  "network": "mainnet",
  "contracts": {
    "StakingRouter": "0xFdDf38947aFB03C621C71b06C9C70bce73f12999",
    "…": "…"
  },
  "modules": [
    { "id": 4, "slug": "curated-v2", "name": "Curated v2", "address": "0xda5f930ce326eb5205085d66c72a4e79d60cb8c1", "withdrawalCredentialsType": 2 }
  ]
}

Modules and operators

Operators of a module

GET /api/modules/{module}/summary

Every operator of one module with its validators and stake: the module pages’ tables. On 0x02 modules depositable is null and each row has an effective-balance histogram; Curated v1 rows carry their migration status.

Request
curl -s 'https://app.roundbeat.com/api/modules/curated-v2/summary'
Response (trimmed)
{
  "network": "mainnet",
  "moduleId": 4,
  "moduleSlug": "curated-v2",
  "moduleName": "Curated v2",
  "operators": [
    {
      "operatorId": 36,
      "name": "ChainSafe - PGO",
      "operatorType": "PGO",
      "groupName": "ChainSafe",
      "legacyOperatorId": 26,
      "active": true,
      "activeValidators": 135,
      "exitingValidators": 0,
      "totalExited": 0,
      "balanceEth": 4326.16,
      "effectiveEth": 4320,
      "avgEffectiveEth": 32,
      "validatorsAtMaxEB": 0,
      "depositable": null,
      "effectivenessEpochs": 223
    }
  ]
}

Operator effectiveness

GET /api/health/operators

Each operator’s effectiveness over the last 225 epochs (attestationRate, 0 to 1) and its proposals in the same window. state is active, no_active_validators or migrated. The module totals are at /api/health/summary.

/api/health/operators parameters
ParameterMeaning
moduleThe module (default Curated v1).
Request
curl -s 'https://app.roundbeat.com/api/health/operators?module=curated-v2'
Response (trimmed)
{
  "network": "mainnet",
  "moduleId": 4,
  "windowEpochs": 225,
  "operators": [
    {
      "operatorId": 36,
      "name": "ChainSafe - PGO",
      "state": "active",
      "attestationRate": 0.9999,
      "epochs": 223,
      "proposalsMade": 0,
      "proposalsMissed": 0,
      "consecutiveMissed": 0,
      "aum": { "validators": 135, "totalEth": 4326.16, "effectiveEth": 4320 }
    }
  ]
}

One operator

GET /api/operator/{module}/{id}/info

The operator page’s header. Note that the key counts here are strings. operator is null (with HTTP 200) for an unknown operator.

Request
curl -s 'https://app.roundbeat.com/api/operator/curated-v2/36/info'
Response (trimmed)
{
  "network": "mainnet",
  "moduleId": 4,
  "moduleName": "Curated v2",
  "operatorId": 36,
  "operator": {
    "name": "ChainSafe - PGO",
    "active": true,
    "activeValidators": "135",
    "totalDeposited": "135",
    "totalExited": "0",
    "exitingValidators": 0,
    "aumEth": 4326.1602,
    "effectiveEth": 4320,
    "rewardAddress": "0x29d5a9917A82Dbb77e3362128C425d3a63eE8E6F",
    "successorOf": { "moduleId": 1, "operatorId": 26, "name": "ChainSafe" }
  }
}

An operator’s validators

GET /api/indexed/operator/{id}/validators

The Validators tab. Balances are in gwei. display_status adds consolidating and consolidated for Curated v1 validators moving into Curated v2.

/api/indexed/operator/{id}/validators parameters
ParameterMeaning
moduleIdThe module. Pass it always.
limit, offsetPage size (default 50, at most 500) and offset.
statusBeacon status, for example active_ongoing; repeat or comma-separate for several.
searchAn index or pubkey.
eb_min, eb_maxEffective balance range, in whole ETH.
sort, dirindex, status, balance, effective_balance, activation_epoch or exit_epoch; asc (default) or desc.
Request
curl -s 'https://app.roundbeat.com/api/indexed/operator/36/validators?moduleId=4&limit=1'
Response (trimmed)
{
  "total": 135,
  "validators": [
    {
      "validator_index": 2367208,
      "pubkey": "0x982b2eaf973c144dca8e26acddf3cb4258228cccaa19afbe88bedd40eede3ff5d3331b3d657d69e36d125912f95d18fd",
      "status": "active_ongoing",
      "display_status": "active_ongoing",
      "balance": "32044339978",
      "effective_balance": "32000000000",
      "slashed": false,
      "activation_epoch": "476509",
      "exit_epoch": null
    }
  ]
}

An operator’s proposals

GET /api/indexed/operator/{id}/proposals

The Proposals tab: every proposal duty, proposed or missed, with its MEV. mev_status is one of the MEV classes. total counts the whole window, and time echoes it. A missed slot has no block, so its block fields are null.

/api/indexed/operator/{id}/proposals parameters
ParameterMeaning
moduleIdThe module. Pass it always.
timeA window, by slot; without it, every proposal on record.
limit, offsetDefault 50, at most 500.
statusproposed or missed.
relayA relay name, or local for every proposed block with no relay (see Local in the tables).
sort, dirslot, epoch, validator, gas_used, txs or mev_reward_wei; desc by default.
Request
curl -s 'https://app.roundbeat.com/api/indexed/operator/36/proposals?moduleId=4&time=7d&limit=1'
Response (trimmed)
{
  "total": 5,
  "time": "7d",
  "proposals": [
    {
      "slot": 15410402,
      "epoch": 481575,
      "validator_index": 2367350,
      "proposed": true,
      "fee_recipient": "0x388c818ca8b9251b393131c08a736a67ccb19297",
      "gas_used": "27388941",
      "transaction_count": 330,
      "mev_status": "relayed",
      "mev_reward_wei": "10424105614537579",
      "relay_name": "ultrasound",
      "relay_names": ["ultrasound", "aestus", "titan-global"],
      "missed_best_bid_wei": null,
      "timestamp_unix": "1791748847"
    }
  ]
}

An operator’s events

GET /api/indexed/operator/{id}/events

The operator’s event feed: the Events tab without its On-chain events panel, whose events are at …/contract-events and take no window.

/api/indexed/operator/{id}/events parameters
ParameterMeaning
moduleIdThe module. Pass it always.
timeA window, by the event’s epoch; without it, every event.
limit, offsetDefault 50, at most 500.
type, exclude_typeComma-separated event types without the eth. prefix, for example missed_proposal,likely_offline.
Request
curl -s 'https://app.roundbeat.com/api/indexed/operator/36/events?moduleId=4&type=upcoming_proposal&time=7d&limit=1'
Response (trimmed)
{
  "total": 5,
  "time": "7d",
  "events": [
    {
      "id": 1119068,
      "event_type": "upcoming_proposal",
      "validator_index": 2367350,
      "operator_id": 36,
      "module_id": 4,
      "epoch": "481575",
      "created_at": "2026-10-11T19:54:50Z",
      "details": { "slot": 15410402, "epochs_away": 1, "approx_minutes": 7, "operator_name": "ChainSafe - PGO" }
    }
  ]
}

Blocks and proposals

Proposal statistics

GET /api/blocks/stats

Block Analysis’s figures: success rate, relays and per-operator results. successRate is proposed blocks out of all proposal duties, to 4 decimals. mevRate is blocks that paid an MEV-Boost reward (mevBlocks) out of all proposed blocks in the window (successfulProposals), including blocks whose relay data is still pending or unknown; here 1,480 of 1,609. The operator page’s MEV-Boost rate is different: relayed out of relayed plus local blocks (MEV classes).

/api/blocks/stats parameters
ParameterMeaning
timeA window.
moduleLimit to one module.
Request
curl -s 'https://app.roundbeat.com/api/blocks/stats?time=24h'
Response (trimmed)
{
  "network": "mainnet",
  "time": "24h",
  "totalProposals": 1614,
  "successfulProposals": 1609,
  "missedSlots": 5,
  "successRate": 0.9969,
  "mevBlocks": 1480,
  "mevRate": 0.9198259788688626,
  "relayedBlocks": 1480,
  "builderBlocks": 0,
  "localBlocks": 129,
  "pendingBlocks": 0,
  "unknownBlocks": 0,
  "totalMevWei": "23303112100516462561",
  "relayBreakdown": [{ "relay": "ultrasound", "count": 1274, "blockShare": 0.8608 }],
  "byOperator": [{ "moduleId": 1, "operatorId": 31, "operatorName": "SenseiNode", "proposed": 61, "missed": 0, "successRate": 1 }]
}

Blocks

GET /api/blocks

The Blocks table, newest first, across every Lido operator.

/api/blocks parameters
ParameterMeaning
time, moduleWindow and module, as above.
limit, offsetDefault 50, at most 500.
status, relayproposed or missed; a relay name, or local for every proposed block with no relay.
Request
curl -s 'https://app.roundbeat.com/api/blocks?time=24h&limit=1'
Response (trimmed)
{
  "network": "mainnet",
  "total": 1614,
  "blocks": [
    {
      "slot": 15421306,
      "epoch": 481915,
      "validatorIndex": 2223874,
      "moduleId": 1,
      "operatorId": 5,
      "operatorName": "Blockscape",
      "proposed": true,
      "timestamp": "2026-10-13T08:21:35Z",
      "executionBlockNumber": "26182339",
      "mevStatus": "relayed",
      "mevRewardWei": "5306657124144750",
      "relayNames": ["titan-global"],
      "missedBestBidWei": null
    }
  ]
}

One slot

GET /api/blocks/{slot}

The slot page. A slot more than 14,400 slots ahead (about two days) is a 404. /api/blocks/{slot}/missed-bids lists the relay bids for a locally built block.

Request
curl -s 'https://app.roundbeat.com/api/blocks/15381999'
Response (trimmed)
{
  "network": "mainnet",
  "slot": 15381999,
  "epoch": 480687,
  "time": "2026-10-07T21:20:11Z",
  "future": false,
  "block": {
    "operatorId": 36,
    "moduleId": 4,
    "operatorName": "ChainSafe - PGO",
    "validatorIndex": 2369163,
    "proposed": true,
    "feeRecipient": "0x388c818ca8b9251b393131c08a736a67ccb19297",
    "mevStatus": "relayed",
    "mevRewardWei": "7683998740404956",
    "relayNames": ["ultrasound", "aestus", "titan-global"],
    "transactionCount": 249
  },
  "lidoPolicy": {
    "vault": "0x388c818ca8b9251b393131c08a736a67ccb19297",
    "feeRecipient": "0x388c818ca8b9251b393131c08a736a67ccb19297",
    "feeRecipientOk": true,
    "relayChecked": true,
    "offListRelays": []
  }
}

Upcoming proposals

GET /api/blocks/upcoming

Lido proposals scheduled in the current and next epoch: the beacon chain does not publish proposers further ahead.

/api/blocks/upcoming parameters
ParameterMeaning
moduleLimit to one module.
Request
curl -s 'https://app.roundbeat.com/api/blocks/upcoming?module=csm'
Response (trimmed)
{
  "network": "mainnet",
  "moduleId": 3,
  "currentSlot": 15421336,
  "currentEpoch": 481916,
  "upcoming": [
    { "slot": 15421337, "epoch": "481916", "validatorIndex": 2281413, "moduleId": 3, "operatorId": 35, "operatorName": "CSM Operator 35", "secondsAway": 12, "minutesAway": 0 }
  ]
}

Events

Event feed

GET /api/indexed/alerts

The feed behind app.roundbeat.com/alerts. category is the event type; source is beacon or contract (on-chain events, whose id is a string). The types and severities are those of the alert types, under their feed names. Its window counts events by when Roundbeat recorded them, while an operator’s events list counts them by epoch, so the two can differ slightly.

/api/indexed/alerts parameters
ParameterMeaning
limitDefault 50, at most 500.
beforeCursor for the next page: pass the previous response’s nextCursor. offset works up to 20,000.
severitycritical, warning or info.
time, moduleWindow and module.
typeOne event type, for example eth.missed_proposal.
searchMatches the operator name.
Request
curl -s 'https://app.roundbeat.com/api/indexed/alerts?severity=critical&time=24h&limit=1'
Response (trimmed)
{
  "network": "mainnet",
  "total": 1012,
  "hasMore": true,
  "nextCursor": "1791877125658771.b.1140432",
  "alerts": [
    {
      "id": 1140432,
      "source": "beacon",
      "severity": "critical",
      "category": "eth.likely_offline",
      "operatorId": 39,
      "moduleId": 3,
      "operatorName": "CSM Operator 39",
      "validatorIndex": 1631660,
      "epoch": "481907",
      "timestamp": "2026-10-13T07:38:45Z",
      "details": {
        "consecutive_missed_epochs": 3,
        "message": "Validator #1631660 missed attestations for 3 consecutive epochs (epoch 481907)"
      }
    }
  ]
}

Sync committees

Lido sync committee members

GET /api/sync-committees

Lido validators in each sync committee period, by operator. The first period is the next one.

/api/sync-committees parameters
ParameterMeaning
limit, offsetPeriods per page (default 10, at most 50), newest first.
module, searchLimit to one module, or to operators whose name matches.
Request
curl -s 'https://app.roundbeat.com/api/sync-committees?limit=1'
Response (trimmed)
{
  "currentEpoch": 481915,
  "currentPeriod": 1882,
  "epochsPerPeriod": 256,
  "totalPeriods": 175,
  "syncCommittees": [
    {
      "period": 1883,
      "startEpoch": 482048,
      "endEpoch": 482304,
      "isCurrent": false,
      "totalMembers": 115,
      "byOperator": [
        { "moduleId": 1, "operatorId": 0, "operatorName": "Staking Facilities", "validators": [343240] }
      ]
    }
  ]
}

Curated v2 migration

Migration progress

GET /api/lido/cmv2-migration

The Curated v1 to v2 migration for the whole module and per Curated v1 operator: consolidation counts by step (pending is requested but not queued yet), the operator’s stage (awaiting_pair, not_started, submitted, in_progress, done, exiting, left, inactive) and its Curated v2 targets with their share in basis points. This endpoint promises to only ever add fields.

Request
curl -s 'https://app.roundbeat.com/api/lido/cmv2-migration'
Response (trimmed)
{
  "network": "mainnet",
  "updatedAt": "2026-10-13T08:27:49Z",
  "totals": {
    "legacyActive": 199453,
    "total": 72505,
    "pending": 0,
    "queued": 13129,
    "exited": 3283,
    "completed": 56093,
    "rejected": 0,
    "ethMoved": 1794976,
    "queueTailEpoch": 483710,
    "completionRate": { "windowDays": 7, "completed": 16019, "perDay": 2288.43 }
  },
  "operators": [
    {
      "legacy": { "operatorId": 26, "name": "ChainSafe", "activeValidators": 7832, "exitingValidators": 0 },
      "group": { "id": 32, "name": "ChainSafe" },
      "status": "migrating",
      "stage": "submitted",
      "targets": [
        { "moduleId": 4, "operatorId": 36, "name": "ChainSafe - PGO", "operatorType": "PGO", "shareBp": 10000, "activeValidators": 135, "effectiveEth": 4320 }
      ],
      "progress": { "pairsAllowed": 1, "submitted": 63, "total": 0, "requested": 0, "pending": 0, "queued": 0, "exited": 0, "completed": 0, "rejected": 0, "ethMoved": 0, "nextEtaEpoch": null }
    }
  ]
}

Written for Roundbeat 1.28. Facts checked against the app source on 13 Oct 2026.