0x02 validators, and require APIv3 staking to be enabled for your organization. Every APIv2 and APIv3 endpoint on this page needs the Read vault activity permission on the vaults you report on. For how to grant it, see Permission groups.
The APIv2 reporting surface
Four endpoints carry everything APIv2 reports about staking.
A position row carries
stakingPositionId, assetType, stakedAmount, inactiveStakedAmount, status, providerName, sourceAddress, withdrawalAddress, and transactionId. Position status is one of PENDING, ACTIVE, or EXITED. Wallet and vault asset details carry availableBalance, stakedBalance, totalBalance, unclaimedBalance, unvestedBalance, and unvestedUnstakeableBalance, each as an amount with quantity, currentPrice, and currentUSDValue.
Constructing a position report on APIv2
1
List positions for each wallet
Call
GET /v2/wallets/{walletId}/staking/positions and follow page.next until it returns null.2
Read staked and inactive amounts per position
Take
stakedAmount and inactiveStakedAmount from each row, and group by assetType.3
Read the wallet rollup
Read
stakedBalance from GET /v2/wallets/{walletId}, which also supplies USD valuation. stakedBalance sums several underlying balances, so it need not equal your per-position total.4
Attach rewards
Call
GET /v2/wallets/{walletId}/staking/rewards and split by rewardType, which is CLAIMED or UNCLAIMED, using referenceDate for the period.The pending and exiting stake gap on APIv2
APIv2 does not return non-zero values for pending or exiting stake. A position appears withstatus set to PENDING while its deposit is confirmed but not yet active, and during that window its amount is not reported anywhere on APIv2.
The documented workaround was to recover the amount from the transaction that created the position:
- Call
GET /v2/wallets/{walletId}/staking/positionsand filter to rows wherestatusisPENDING. - For each row, take its
transactionIdand callGET /v2/transactions/{transactionId}to read that transaction’samount. - Sum those amounts by asset type, and treat the total as the pending stake missing from
stakedBalance.
amount.quantity as "0" on GET /v2/transactions/{transactionId}, so step 2 recovers nothing. They also carry transactionType "OTHER", because APIv2 reserves its specific types for deposits, withdrawals, and transfers. Identify a staking transaction by the position’s transactionId rather than by its type. The position’s status also stays PENDING after the transaction itself reads SUCCESS, so a reporting job that runs shortly after a stake request sees a pending position whose amount is unavailable from either endpoint.
What APIv3 replaces
APIv3 reports staking balances as typed buckets rather than two amount fields plus a status. Per-position balances come fromGET /v3/wallets/{walletId}/staking-positions/{positionId}/balances, and wallet-level figures for the same buckets come from GET /v3/wallets/{walletId}/balances.
Each row below is the nearest equivalent, not a rename. The two versions build these amounts from different underlying balances, so a figure can change when you switch versions even where the concept matches.
Field names and pagination also differ. An APIv2 amount names its value
quantity, while an APIv3 amount names it amount. APIv2 paginates with page.next, while APIv3 uses page.endCursor fed into an after parameter, with a first page size of 25 by default and 100 at most.
ACTIVE_STAKE is narrower than stakedBalance
The stake ACTIVE_STAKE leaves out on Ethereum includes restaked positions, stake restaked in the beacon chain, Alluvial staking, and delegated stake that remains usable. So an organization holding EigenLayer or Alluvial positions sees an ACTIVE_STAKE lower than its stakedBalance.
Adding the four APIv3 staking buckets together does not recover stakedBalance either. ACTIVATING_STAKE and DEACTIVATING_STAKE cover stake that stakedBalance never included, so the two sets overlap on the principal and diverge in both directions.
On assets that report claimable rewards as a position state, ACTIVE_STAKE folds those rewards in as well, where APIv2 reports them separately as unclaimedBalance.
Each asset defines its own composition, and there is no shared definition holding the two versions in step, so confirm the make-up of a figure for every asset you report on rather than generalizing from Ethereum.
Absent buckets mean zero
A balance type missing from an APIv3 response means zero, not unknown, so summing is safe on both endpoints. A report that treats an absent bucket as unreported will mis-total. The two endpoints differ in whether a zero appears at all.GET /v3/wallets/{walletId}/balances drops zero-valued entries, so a wallet with no activating stake has no ACTIVATING_STAKE row. The per-position endpoint applies no such filter and emits what the position reports, zeros included. So on a position, an explicit zero is meaningful while absence is not, and you cannot read “this position has no active stake” from a missing ACTIVE_STAKE entry.
Wallet balances and staking positions answer different questions
The two APIv3 balance endpoints read from different sources by design, so the numbers they return can differ.GET /v3/wallets/{walletId}/balances reads the wallet’s named balances. It does not consult validators, so staked balance is counted whatever created it.
GET /v3/wallets/{walletId}/staking-positions asks the Ethereum module for the validators it manages, and that lookup covers 0x02 validators only. This is deliberate. A wallet holding only 0x01 validators stays on the legacy Ethereum staking flow, and standardized staking applies to wallets that hold at least one 0x02 validator.
On a wallet that holds 0x01 validators, that stake is included in the wallet’s ACTIVE_STAKE and has no row in the position list. Both endpoints return what they are designed to return.
On such a wallet, the wallet figure and the sum of the per-position figures are not expected to agree. The difference is the 0x01 stake, and it reflects a difference in scope, not a shortfall.
APIv2 presented these as positions by synthesizing one from the validator record. APIv3 reports the validators the staking flow manages, so if you are moving a report across and relied on those synthesized rows, expect a shorter position list for the same wallet.
Bringing legacy validators into position-level reporting
If you want stake currently held by0x01 validators to appear in the APIv3 position list, consolidate those validators into a 0x02 validator. The stake then reports as an ordinary APIv3 staking position, and the wallet figure and the summed position figures line up again.
Consolidation runs on APIv2 through POST /v2/transactions/consolidate-stake. See Pre-Pectra staking, under “Consolidate Stake from Pre-Pectra to Pectra”, and Pectra staking, under “Consolidate to Pectra validator”. You can consolidate from a non-Pectra validator into a Pectra validator, across wallets and vaults, but not into a non-Pectra validator and not across staking providers.
Organization enablement
APIv3 staking is enabled per organization. A wallet whose organization does not have it enabled returns an error fromGET /v3/wallets/{walletId}/staking-positions rather than an empty list, so handle an error and an empty list as different outcomes. If you see the error, contact your client experience team to confirm enablement.
What APIv3 adds
These have no APIv2 equivalent.ACTIVATING_STAKEandDEACTIVATING_STAKEreport activating and exiting stake as amounts, per position and at wallet level. They close the APIv2 gap described above.GET /v3/wallets/{walletId}/balancesreturns all four staking buckets for a wallet in one call, so a wallet report does not need a call per position.HELDcovers holds on the wallet’s primary address, such as pending withdrawals and settlements.GET /v3/wallets/{walletId}/rewardsreturns individual reward events over a date range. Each event carriesstakingPositionIdandtransactionHashwhere applicable, so a reward can be attributed to a validator or stake account.GET /v3/wallets/{walletId}/daily-rewardsreturns one row per day per reward type, over a range of up to 31 days.- Both reward endpoints classify rewards by source rather than by claim state.
- A Solana position reports
stakeAuthority,withdrawAuthority, andvalidatorVoteAccount, which identifies positions delegated through a third-party staking product.
Querying rewards on APIv3
The two reward endpoints take their reward type differently, and accept different values.
Both accept
DELEGATION_REWARDS, DELEGATION_MEV_REWARDS, EXECUTION_LAYER_REWARDS, BLOCK_PROPOSER_REWARDS, ATTESTATION_REWARDS, and SYNC_COMMITTEE_REWARDS. The daily endpoint also accepts CONSENSUS_LAYER_REWARDS, which is an aggregate of BLOCK_PROPOSER_REWARDS, ATTESTATION_REWARDS, and SYNC_COMMITTEE_REWARDS.
What stays on APIv2
A complete report still calls APIv2 for the following.currentPriceandcurrentUSDValueexist on APIv2 only. An APIv3 amount carries onlyamountandassetType, so USD valuation comes from APIv2.- APIv2
rewardTypereports whether a reward is claimed. APIv3 reward types report where a reward came from, so one does not substitute for the other. unclaimedBalance,unvestedBalance, andunvestedUnstakeableBalancehave no APIv3 equivalent today.GET /v2/vaults/{vaultId}reports vault-level rollups withvaultIdandvaultName.GET /v2/transactions/{transactionId}reports a transaction’s status, one ofINITIATING,NEEDS_APPROVAL,INPROGRESS,SUCCESS,REJECTED,EXPIRED, andFAILURE, and itsblockchainTxId, the on-chain hash. The APIv3 read endpoints on this page report neither.- An APIv2 position carries the
transactionIdof the operation that created it, and the positions endpoint accepts it as a filter. The filter applies on ETH but not on SOL. See Getting started with staking API for the polling pattern.
A mixed reporting pattern
Both versions report on the same wallets and staking positions, so one report can take each figure from whichever version reports it best.SUCCESS on GET /v2/transactions/{transactionId} describes the transaction, not on-chain finality. Check blockchainTxId against your own node or a block explorer to confirm inclusion and depth before treating a position as settled in a report.