> ## Documentation Index
> Fetch the complete documentation index at: https://docs.beaconcha.in/llms.txt
> Use this file to discover all available pages before exploring further.

# APY & ROI

> Returns the annual percentage yield (APY) and return on investment (ROI) for a known collection or group of validators. Known collections are referenced by index, public key, deposit address, or withdrawal address.

**Use case guide:** [APY & ROI metrics](/use-cases/apy-roi) explains how to choose a window, interpret return metrics, and decide when BeaconScore is the better comparison.

For comparing performance across different staking providers, we recommend using the BeaconScore from the Performance Aggregated endpoints instead of APY or ROI, as BeaconScore normalizes for luck and provides a fairer comparison. Note that some residual luck factors outside a validator's control can still influence BeaconScore, especially over short evaluation windows. See the Residual Luck Factors section in the BeaconScore documentation for details.

**Coming Soon:** Support for querying arbitrary time ranges using Unix timestamps, epochs, or slots — exclusively for [Scale and Enterprise plans](https://beaconcha.in/pricing).




## OpenAPI

````yaml /v3/bundled.yaml post /api/v2/ethereum/validators/apy-roi
openapi: 3.0.4
info:
  title: External Service API
  version: 1.0.3
servers:
  - url: https://beaconcha.in
    description: Production API
security:
  - ApiKeyAuth: []
paths:
  /api/v2/ethereum/validators/apy-roi:
    post:
      tags:
        - Performance
      summary: APY & ROI
      description: >
        Returns the annual percentage yield (APY) and return on investment (ROI)
        for a known collection or group of validators. Known collections are
        referenced by index, public key, deposit address, or withdrawal address.


        **Use case guide:** [APY & ROI metrics](/use-cases/apy-roi) explains how
        to choose a window, interpret return metrics, and decide when
        BeaconScore is the better comparison.


        For comparing performance across different staking providers, we
        recommend using the BeaconScore from the Performance Aggregated
        endpoints instead of APY or ROI, as BeaconScore normalizes for luck and
        provides a fairer comparison. Note that some residual luck factors
        outside a validator's control can still influence BeaconScore,
        especially over short evaluation windows. See the Residual Luck Factors
        section in the BeaconScore documentation for details.


        **Coming Soon:** Support for querying arbitrary time ranges using Unix
        timestamps, epochs, or slots — exclusively for [Scale and Enterprise
        plans](https://beaconcha.in/pricing).
      operationId: GetValidatorApyRoi
      requestBody:
        $ref: '#/components/requestBodies/validatorChainEvaluationWindow'
      responses:
        '200':
          $ref: '#/components/responses/ValidatorApyRoi'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '429':
          $ref: '#/components/responses/RateLimitExceeded'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultError'
components:
  requestBodies:
    validatorChainEvaluationWindow:
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ValidatorChainEvaluationWindow'
  responses:
    ValidatorApyRoi:
      description: Successful response.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ValidatorApyRoi.Container'
    BadRequest:
      description: Bad Request
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: Bad request. Please check your input and try again.
    Unauthorized:
      description: Unauthorized
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: Unauthorized. Please provide a valid API key.
    Forbidden:
      description: Forbidden
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: >-
              endpoint not allowed for your subscription tier. upgrade your
              subscription at https://beaconcha.in/pricing.
    NotFound:
      description: Not Found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: The requested resource was not found.
    MethodNotAllowed:
      description: Method Not Allowed
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: 'method not allowed: GET. all public API endpoints use POST.'
    RateLimitExceeded:
      description: Rate Limit Exceeded
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: Rate limit exceeded. Please try again later.
    InternalServerError:
      description: Internal Server Error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: internal server error. please try again later.
    DefaultError:
      description: An unexpected error response.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: An unexpected error occurred.
  schemas:
    ValidatorChainEvaluationWindow:
      type: object
      properties:
        chain:
          $ref: '#/components/schemas/Chain'
        validator:
          $ref: '#/components/schemas/validatorsSelector'
        range:
          $ref: '#/components/schemas/timeRangeSelectorWithWindow'
          description: >
            Specify a date range to evaluate APY and ROI for that period — ideal
            for use cases like comparing staking returns across different time
            horizons. If not provided, defaults to the last 30 days.


            Support for querying arbitrary time ranges using Unix timestamps,
            epochs, or slots will be **coming soon**, exclusively for [Scale and
            Enterprise plans](https://beaconcha.in/pricing).
      required:
        - validator
        - range
    ValidatorApyRoi.Container:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/ValidatorApyRoi.Data'
        range:
          $ref: '#/components/schemas/ResultRange'
      description: Response containing apy and roi information of the validators.
      required:
        - data
        - range
    Error:
      type: object
      properties:
        error:
          type: string
    Chain:
      type: string
      enum:
        - mainnet
        - hoodi
      default: mainnet
      description: The Ethereum chain to query.
    validatorsSelector:
      description: >-
        Free selectors available to all users:

        - validator_identifiers: One or more validator indices or public keys to
        filter by.

        - dashboard_id: Your beaconcha.in dashboard ID (requires a free
        account).
          
        **Premium selectors** for Scale & Enterprise plans
        (https://beaconcha.in/pricing):

        - withdrawal: The validator's withdrawal credential or the Ethereum
        wallet address used for withdrawals.

        - deposit_address: The Ethereum wallet address used for the validator's
        deposit.

        - entity: The name of the assigned entity (e.g., "Lido", "Coinbase").
        Optionally include `sub_entity` for more specific filtering. Matching is
        case-sensitive.


        Note: The set of validators matched by `deposit_address` and
        `withdrawal` selectors is updated once per epoch (~6.4 minutes). Newly
        deposited validators may take up to one epoch to appear in query
        results.


        Note: The set of validators matched by `entity` selector is updated once
        per day.
          
      oneOf:
        - $ref: '#/components/schemas/ValidatorsByIdentifiers'
        - $ref: '#/components/schemas/ValidatorsByDashboard'
        - $ref: '#/components/schemas/ValidatorsByDeposit'
        - $ref: '#/components/schemas/ValidatorsByWithdrawal'
        - $ref: '#/components/schemas/ValidatorsByEntity'
    timeRangeSelectorWithWindow:
      description: >
        Specify a date range to receive aggregated data for that period — ideal
        for use cases like monitoring validator performance over time or
        comparing BeaconScore across different periods.


        Support for querying arbitrary time ranges using Unix timestamps,
        epochs, or slots will be **coming soon**, exclusively for [Scale and
        Enterprise plans](https://beaconcha.in/pricing).
      oneOf:
        - $ref: '#/components/schemas/NamedEvaluationWindow'
    ValidatorApyRoi.Data:
      type: object
      description: >
        Validator performance metrics, expressed both as ROI (Return on
        Investment) and APY (Annual Percentage Yield).


          - ROI represents the actual return over the selected evaluation window, not annualized.
          - APY is the same return but annualized to show the equivalent yearly rate.

        ROI helps understand raw performance during the evaluation range, while
        APY allows comparison against annualized benchmarks.

        Note that APY is an extrapolation and does not reflect future
        performance.
      properties:
        execution_layer:
          $ref: '#/components/schemas/RoiApyMetrics'
          description: >
            Reward performance from execution layer activities such as block
            proposals, MEV, and transaction fees. APY and ROI reflect the
            returns generated from these activities.
        consensus_layer:
          $ref: '#/components/schemas/RoiApyMetrics'
          description: >
            Reward performance from consensus layer activities such as
            attestations, sync committee participation, and block proposals.
            This includes rewards for timely and correct attestations,
            participation in sync committees, proposing blocks, and including
            attestations, sync duties, and slashing proofs in proposed blocks.
        combined:
          $ref: '#/components/schemas/RoiApyMetrics'
          description: Combined ROI and APY across execution and consensus layers.
        finality:
          $ref: '#/components/schemas/FinalityParamsOnlyFinalized'
      required:
        - execution_layer
        - consensus_layer
        - combined
        - finality
    ResultRange:
      type: object
      description: >
        The time span actually covered by the returned results — from the first
        to the last matching data point — specified in slots, epochs, and Unix
        timestamps.


        This reflects the data that was found, not the range that was queried.
        When no data is found, it falls back to the requested range, or to the
        full available history if no range was given.
      properties:
        slot:
          $ref: '#/components/schemas/SlotRange'
        epoch:
          $ref: '#/components/schemas/EpochRange'
        timestamp:
          $ref: '#/components/schemas/TimeRange'
      required:
        - slot
        - epoch
        - timestamp
    ValidatorsByIdentifiers:
      type: object
      title: Indices/Pubkeys
      properties:
        validator_identifiers:
          $ref: '#/components/schemas/validatorIndexPublicKeys'
      required:
        - validator_identifiers
    ValidatorsByDashboard:
      type: object
      title: Dashboard
      properties:
        dashboard_id:
          $ref: '#/components/schemas/dashboardID'
        group_id:
          $ref: '#/components/schemas/dashboardGroupID'
      required:
        - dashboard_id
    ValidatorsByDeposit:
      type: object
      title: 💎 Deposit
      properties:
        deposit_address:
          $ref: '#/components/schemas/ExecutionLayerAddress'
      required:
        - deposit_address
    ValidatorsByWithdrawal:
      type: object
      title: 💎 Withdrawal
      properties:
        withdrawal:
          $ref: '#/components/schemas/AddressOrCredential'
      required:
        - withdrawal
    ValidatorsByEntity:
      type: object
      title: 💎 Entity
      description: >
        Select validators by their assigned entity (e.g., staking provider) and
        optionally a sub-entity.

        Entity and sub-entity names are matched exactly and are case-sensitive.
      properties:
        entity:
          type: string
          description: >
            The name of the entity to filter validators by (e.g., "Lido",
            "Coinbase"). Matching is case-sensitive; use the exact name as
            returned by the entities overview endpoint.
        sub_entity:
          type: string
          description: >
            Optional sub-entity name to further filter validators within the
            entity. Matching is case-sensitive; use the exact name as returned
            by the sub-entities overview endpoint.
      required:
        - entity
    NamedEvaluationWindow:
      type: object
      title: Fixed Window
      properties:
        evaluation_window:
          $ref: '#/components/schemas/EvaluationWindow'
      required:
        - evaluation_window
    RoiApyMetrics:
      type: object
      properties:
        roi:
          $ref: '#/components/schemas/RoiApyMetrics.Roi'
          description: >-
            Return on investment during the selected evaluation window, without
            annualization.
        apy:
          $ref: '#/components/schemas/RoiApyMetrics.Apy'
          description: >-
            Annual percentage yield extrapolated from the selected evaluation
            window.
      required:
        - roi
        - apy
    FinalityParamsOnlyFinalized:
      type: string
      description: |
        Indicates the finality status of the data provided. 
          - Finalized data cannot be changed without slashing at least one-third of all validators, providing strong economic guarantees.
          - Data marked as not_finalized does not have this guarantee and may still change.
      enum:
        - finalized
    SlotRange:
      type: object
      properties:
        start:
          $ref: '#/components/schemas/Slot'
        end:
          $ref: '#/components/schemas/Slot'
      required:
        - start
        - end
    EpochRange:
      type: object
      properties:
        start:
          $ref: '#/components/schemas/Epoch'
        end:
          $ref: '#/components/schemas/Epoch'
      required:
        - start
        - end
    TimeRange:
      type: object
      properties:
        start:
          $ref: '#/components/schemas/timestamp'
        end:
          $ref: '#/components/schemas/timestamp'
      required:
        - start
        - end
    validatorIndexPublicKeys:
      description: >
        An array containing either validator indices or public keys. Index and
        public key can be mixed in the same array.


        Subscribed users (Hobbyist, Business, and Scale tiers) can include up to
        100 entries; free trial users and legacy subscription users (Sapphire,
        Emerald, Diamond) are limited to 20.
      type: array
      items:
        $ref: '#/components/schemas/validatorIndexPublicKey'
      minItems: 1
      maxItems: 100
    dashboardID:
      description: >
        beaconcha.in dashboard ID. You can find your dashboard ID in the URL of
        your dashboard page on beaconcha.in (e.g.,
        https://beaconcha.in/dashboard/12345).
      type: integer
      x-go-type: '*int'
      minimum: 0
    dashboardGroupID:
      description: >-
        Optional beaconcha.in dashboard group ID. If no group ID is provided,
        all validators in the dashboard are considered.
      type: integer
      minimum: 0
      nullable: true
    ExecutionLayerAddress:
      type: string
      pattern: ^0x[a-fA-F0-9]{40}$
      description: A standard Ethereum address (20-byte hex string with 0x prefix).
    AddressOrCredential:
      type: string
      pattern: ^(0x)?[0-9a-fA-F]{40}$|^(0x)?0[012][0-9a-fA-F]{62}$
      description: >
        Either an execution layer address (20-byte hex string with 0x prefix) or
        a full 32-byte withdrawal credential.
    EvaluationWindow:
      type: string
      enum:
        - 24h
        - 7d
        - 30d
        - 90d
        - all_time
      description: >
        The evaluation window for aggregating metrics. All windows except
        `all_time` are **rolling periods**—continuously moving time windows that
        always end at the current epoch.


        Rolling windows update every epoch (~6.4 minutes), so the data always
        reflects the most recent period. For example, `30d` returns rewards from
        exactly 30 days ago until now, not a fixed calendar month.


        - `24h`: Last 24 hours (rolling)

        - `7d`: Last 7 days (rolling)

        - `30d`: Last 30 days (rolling)

        - `90d`: Last 90 days (rolling)

        - `all_time`: Since validator activation (not rolling)
    RoiApyMetrics.Roi:
      type: object
      description: Raw performance in the evaluation window (not annualized).
      properties:
        total:
          type: number
          format: float
          description: >-
            Total return during the selected evaluation window for this layer or
            combined scope, expressed as a percentage.
          example: 0.15
        missed:
          type: number
          format: float
          description: >-
            Return not earned during the selected evaluation window because of
            missed duties, expressed as a non-positive percentage.
          maximum: 0
          example: -0.02
      required:
        - total
        - missed
    RoiApyMetrics.Apy:
      type: object
      description: Annualized performance extrapolated from the evaluation window.
      properties:
        total:
          type: number
          format: float
          description: >-
            Total annualized return for this layer or combined scope, expressed
            as a percentage.
          example: 2.76
        missed:
          type: number
          format: float
          description: >-
            Annualized return not earned because of missed duties, expressed as
            a non-positive percentage.
          maximum: 0
          example: -0.5
      required:
        - total
        - missed
    Slot:
      type: integer
      minimum: 0
      description: Slot by number.
    Epoch:
      type: integer
      minimum: 0
    timestamp:
      type: integer
      minimum: 0
    validatorIndexPublicKey:
      oneOf:
        - $ref: '#/components/schemas/validatorIndex'
        - $ref: '#/components/schemas/validatorPublicKey'
    validatorIndex:
      description: Validator Index
      type: integer
      minimum: 0
    validatorPublicKey:
      type: string
      description: Public key of a validator
      pattern: ^0x[a-fA-F0-9]{96}$
  securitySchemes:
    ApiKeyAuth:
      type: http
      scheme: bearer
      description: >-
        Authorization header with value: Bearer YOUR_TOKEN. Refer to the [API
        Keys](/api/overview#api-keys) section to create your API key.

````