Overview
Most tax jurisdictions require you to report the fiat value of staking rewards at the time they were received. For that you need:- Reward amount for each day (or each epoch)
- Historical ETH price for that day
- Calculation:
fiat_value = reward_eth ร price_at_time
Choose Your Approach
For example, for 100 validators on the Scale plan (5 requests per second), the daily aggregate takes 365 requests (just over a minute), while per-epoch iteration takes about 820,000 requests (about 45 hours), because
rewards-list returns at most 10 validators per page.
Income Report (No Code)
The income report gives you daily rewards for up to 366 days, valued in a fiat currency at each dayโs historical price, with CSV exports for your tax return or tax software. It opens on your last finished tax year, whether it starts on January 1 or, as in the United Kingdom, on another date, so a full tax year is a single report. It needs a Premium monitoring plan.Daily Totals with Rewards Aggregate
With a Scale or Enterprise plan, call Rewards Aggregated once per UTC day with a customtimestamp range. Each call sums all validators the selector matches, so with a dashboard_id, withdrawal, or deposit_address selector the request count doesnโt grow with your validator count (validator_identifiers takes at most 100 validators per request).
Set start to 00:00:00 UTC and end to 23:59:59 UTC of the same day. Custom ranges are rounded outward to whole UTC days, so an end of 00:00:00 on the next day would add that whole day as well. This request covers January 1, 2025:
data.total is that dayโs net reward (rewards minus penalties) in wei. Divide by 10^18 for ETH and multiply by the dayโs price. Repeat for each day of the year, adding 86,400 seconds to both timestamps each time. The response range reports the range the data actually covers.
A day before the first of the selected validators had a validator index has no data, so the call answers 404 with no validator rewards data available for the requested range and validators. A selector that matches no validators gets the same answer. To tell the two apart, check the selector once with a named window, for example "range": { "evaluation_window": "24h" }. If that call returns 200, count a day before the first of your validators was activated that answers 404 as zero rewards. Any other 404 for a past day means the data is missing or not aggregated yet: retry later, and report it if it persists.
The rolling windows (
24h, 7d, 30d, 90d) and all_time return one total for the whole window, so you canโt match them with daily prices. A custom range of one UTC day can.Per-Epoch Iteration
On any plan, or when you need values per epoch, iterate the epochs of the year with the Rewards List endpoint. See Custom Range Rewards for the approach and performance estimates.Obtaining Historical ETH Prices
The rewards endpoints return amounts in wei, without fiat values. For the API approaches, you need historical ETH prices for each day. Common sources include:Common Tax Year Time Zone Offsets
The income report and custom ranges work in UTC days. If your tax year follows a local time zone, the first and last day of the year are shifted by your UTC offset. Where that matters, use per-epoch data for those boundary hours.For tax purposes, use your local time zoneโs standard offset (non-daylight-saving) or consult with your tax authority about which time zone to use. Some jurisdictions may require UTC.
Related Resources
- Income & Tax Report: Daily rewards with fiat values and CSV exports, no code
- Introduction: Overview and endpoint comparison
- Custom Range Rewards: Aggregated custom ranges and per-epoch iteration
- Epoch & Time Zone Conversion: Time constants for epoch and timestamp math
- Pagination Guide

