---
title: "Get an ObolValidatorManager (OVM) in one call"
method: GET
path: "/v1/ovm/{network}/{address}"
tags: ["OVM"]
---

# Get an ObolValidatorManager (OVM) in one call

`GET /v1/ovm/{network}/{address}`

## Request

- Base URL: `https://api.obol.tech`
- URL: `https://api.obol.tech/v1/ovm/{network}/{address}`
- Auth: none declared

Provenance (CreateObolValidatorManager from the network OVM factory), state (one Multicall3 read), role holders (RolesUpdated candidates, rolesOf at the same block), the 0xSplits v2 params of its recipients (verified against splitHash) and the validators whose credentials point at it. Every chain read is made at `blockNumber`. Amounts are wei decimal strings; addresses checksummed. Validators come from the goteth registry snapshot in ClickHouse (daily), the beacon registry past it and the pending deposit queue, with current status from the head state. Roles, splits and validators are only read for a verified Obol OVM (provenance `obol`); for any other contract they are null and only provenance and state are returned. Sections that could not be read are null and explained in `notes`. An address without code is 200 with provenance `notObol`. Complete answers, and answers for `notObol` addresses, are cached for one slot; answers with a section that could not be read are not cached.

## Path parameters

- `network` string, required
- `address` string, required

## Response `200`

The OVM

- OvmResponse
  - `address` string, required
  - `network` string, required
  - `blockNumber` number, required: Block every chain read (state, roles, splits) was made at
  - `provenance` OvmProvenance, required
    - `status` 'obol' | 'notObol' | 'unknown', required: `obol` iff the network OVM factory emitted CreateObolValidatorManager for this address; `notObol` if it did not (or the address has no contract code); `unknown` if it could not be checked.
    - `factoryAddress` string, required: The OVM factory of this network
    - `creationTxHash` string, nullable, required: Transaction that created the OVM (status `obol` only)
    - `creationBlock` number, nullable, required: Block the OVM was created in (status `obol` only)
    - `reason` string, required: Why the status was given
  - `owner` string, nullable, required
  - `principalRecipient` string, nullable, required
  - `rewardRecipient` string, nullable, required
  - `principalThreshold` string, nullable, required: wei (the contract stores gwei)
  - `amountOfPrincipalStake` string, nullable, required: wei. A routing counter raised by OVM.deposit, not a measure of stake: compare with `principalOnBeaconChain`.
  - `fundsPendingWithdrawal` string, nullable, required
  - `balance` string, nullable, required: OVM ETH balance, wei
  - `version` string, nullable, required: `version()`, null if the contract has none
  - `pullBalances` OvmPullBalances, required
    - `principalRecipient` string, required: wei
    - `rewardRecipient` string, required: wei
  - `roles` OvmRoleHolder[], nullable, required: Owner first (with its roles, possibly 0), then every other RolesUpdated candidate with roles at `blockNumber`. null if the role events or rolesOf could not be read, and for an address whose provenance is not `obol`.
    - `address` string, required
    - `roles` string, required: `rolesOf(address)` at `blockNumber` (bit mask), as a decimal string: the owner can set any of the 256 bits, beyond what a JSON number holds exactly
    - `roleNames` string[], required: Names of the set bits: WITHDRAWAL 0x01, CONSOLIDATION 0x02, SET_BENEFICIARY 0x04, RECOVER_FUNDS 0x08, SET_REWARD 0x10, DEPOSIT 0x20
    - `isOwner` boolean, required: Whether this holder is the owner (always the first entry)
    - `publicForwarder` boolean, required: True when the holder is a public call forwarder (Multicall3 0xcA11bde05977b3631167028862bE2a173976CA11, or, where they have code, Multicall2 0x5BA1e12693Dc8F9c48aAD8770482f4739bEeD696 and Multicall 0xeefBa1e63905eF1D7ACbA5a8513c70307C1cE441): anyone can call role-gated functions through it, so the role is effectively public.
    - `grantedAtBlock` number, nullable, required: Block of the most recent RolesUpdated log for this holder at or before `blockNumber` (each log sets the full role mask, so this is when its current roles were set). null when no RolesUpdated log names the holder (an owner without roles).
    - `grantedAtTimestamp` number, nullable, required: Unix timestamp (seconds) of `grantedAtBlock`; null when `grantedAtBlock` is null or the block header could not be read.
  - `splits` OvmSplit[], nullable, required: The recipients that are 0xSplits v2 PullSplits, with params whose hash equals their `splitHash()`. null if they could not be checked, and for an address whose provenance is not `obol`.
    - `address` string, required
    - `kind` 'principal' | 'reward', required: Which OVM recipient this split is
    - `splitHash` string, required: `splitHash()` at `blockNumber`; the params hash to it
    - `recipients` string[], required
    - `allocations` string[], required
    - `totalAllocation` string, required
    - `distributionIncentive` number, required
    - `source` 'SplitUpdated' | 'SplitCreated', required: The log the params were read from
  - `validators` OvmValidator[], nullable, required: Validators whose credentials (or queued deposit credentials) point at this OVM, plus undeposited validators of locks for it. null if the beacon node could not be read, and for an address whose provenance is not `obol`.
    - `pubkey` string, required
    - `index` number, nullable, required
    - `status` 'new' | 'queued' | 'active' | 'exited', required: `new` (in a lock for this OVM, no deposit seen), `queued` (in the pending deposit queue or pending activation), `active`, `exited` (exited or withdrawable/withdrawn)
    - `beaconStatus` string, nullable, required: Beacon API status; `pending_deposit` when only in the deposit queue; null for `new`
    - `balance` string, nullable, required: wei
    - `effectiveBalance` string, nullable, required: wei
    - `withdrawalCredentials` string, required: Registry credentials; for a queued validator the credentials it will be created with; for `new` the credentials in its lock
    - `lockHash` string, nullable, required: Lock hash, when the validator is in a lock whose withdrawal address is this OVM
    - `clusterName` string, nullable, required: Name in that lock's cluster definition; null when `lockHash` is null or the definition has no name
  - `principalOnBeaconChain` string, nullable, required: wei. The principal this OVM is responsible for: the sum of processed beacon-chain deposits credited to validators whose withdrawal credentials point at this OVM (by the validator's current credentials), adjusted for consolidations into/out of those validators, minus principal already paid out by the OVM (sum of DistributeFunds.principalPayout). null until processed deposits are indexed (see `notes`).
  - `notes` string[], required: Anything partial or unavailable in this answer

## Other responses

- `400`: Unsupported network or malformed address
- `429`: Rate limited (either this API or the upstream)
- `500`: Internal server error
- `502`: The execution RPC request failed

## Changes

- **2026-10-28** `c545dd14c211`: 4 info
  - added the media type `application/json` for the response with the status `400`
  - added the media type `application/json` for the response with the status `429`
  - added the media type `application/json` for the response with the status `500`
  - added the media type `application/json` for the response with the status `502`
- **2026-10-22** `ffbd09536a1a`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/obol/apis/obol-api/changes/v1/ovm/:network/:address/get.md)

---

[API](https://skmtc.dev/obol/apis/obol-api.md) - [All operations](https://skmtc.dev/obol/apis/obol-api/llms.txt) - [OpenAPI document](https://skmtc.dev/obol/apis/obol-api/revisions/74b8e410bd85?raw)
