> ## 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.

# Track Staking Inflows & Outflows

> Measure ETH in transit — pending deposits entering staking and pending exits and withdrawals leaving it

## Overview

ETH does not enter or leave Ethereum staking instantly. Deposits wait in the deposit queue before becoming active stake (**ETH in activation — not yet staked**), and exiting stake passes through the exit queue, the withdrawal eligibility delay, and the withdrawal sweep before it can be redeemed (**ETH in withdrawal — not yet redeemed**). This pending ETH is often called **ETH in transit**.

The Queue APIs expose both directions of this flow: network-wide totals and per-validator positions, each with estimated processing times. Use them to report pending balances to customers, forecast liquidity, or analyze staking supply dynamics.

<Note>
  **API Endpoints:** This guide uses the Queue API family:

  | Endpoint                                                                          | Best For                                          |
  | --------------------------------------------------------------------------------- | ------------------------------------------------- |
  | [`/api/v2/ethereum/queues`](/api-reference/ethereum/queues)                       | Network-wide totals for inflow/outflow snapshots  |
  | [`/api/v2/ethereum/validators/queues`](/api-reference/ethereum/validators/queues) | Queue overview for selected validators, with ETAs |
</Note>

***

## Why Track Staking Flows?

<CardGroup cols={2}>
  <Card title="Pending Balance Reporting" icon="building-columns">
    Show customers ETH that is deposited but not yet earning, or exiting but not yet redeemable, as distinct balance states.
  </Card>

  <Card title="Liquidity Forecasting" icon="droplet">
    Predict when exiting ETH becomes liquid and when queued deposits start earning, down to the epoch.
  </Card>

  <Card title="Customer ETAs" icon="clock">
    Give per-validator activation and withdrawal estimates instead of network-wide averages.
  </Card>

  <Card title="Market & Supply Analytics" icon="chart-line">
    Track net pending flow (inflows minus outflows) as a leading indicator of staking supply changes.
  </Card>
</CardGroup>

***

## Mapping "Pending ETH" to Queue Data

All balance fields are returned in wei (1 ETH = 10¹⁸ wei).

| Metric                       | Definition                                        | Source Fields                                                                                                     |
| ---------------------------- | ------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
| **ETH in activation**        | Deposited, not yet active stake                   | `deposit_queue.deposit_balance` (new validators) + `deposit_queue.topup_balance` (top-ups to existing validators) |
| **ETH in exit**              | Exit requested, validator still active            | `exit_queue.balance`                                                                                              |
| **ETH in manual withdrawal** | Withdrawal requests queued on the execution layer | `manual_withdrawal_queue.balance`                                                                                 |
| **Pending inflow**           | All ETH entering staking                          | `deposit_balance` + `topup_balance`                                                                               |
| **Pending outflow**          | All ETH leaving staking                           | `exit_queue.balance` + `manual_withdrawal_queue.balance`                                                          |
| **Net pending flow**         | Direction of staking supply                       | Pending inflow − pending outflow                                                                                  |

<Note>
  **Don't count consolidations as flows.** The `consolidation_queue` and `compounding_switch_queue` track validators moving stake between validators or switching to compounding credentials — that ETH stays staked and is neither an inflow nor an outflow.
</Note>

<Note>
  **The last leg of an outflow:** after a validator exits, its balance waits through the eligibility delay (\~27 hours) and the withdrawal sweep before being credited. The network endpoint exposes the current sweep duration via `withdrawal_sweep.estimated_sweep_delay`, and the [per-validator overview](#per-validator-tracking) returns min/max sweep estimates for each exiting validator.
</Note>

***

## Network-Wide Snapshot

Get the total pending inflow and outflow for the entire network:

```bash theme={null}
curl --request POST \
  --url https://beaconcha.in/api/v2/ethereum/queues \
  --header 'Authorization: Bearer <YOUR_API_KEY>' \
  --header 'Content-Type: application/json' \
  --header 'Accept: application/vnd.beaconcha.in.v2.1+json' \
  --data '{"chain": "mainnet"}'
```

### Response

```json theme={null}
{
  "data": {
    "deposit_queue": {
      "deposit_count": 1184,
      "deposit_balance": "37888000000000000000000",
      "topup_count": 243,
      "topup_balance": "1850000000000000000000",
      "estimated_processed_at": {
        "epoch": 454155,
        "timestamp": 1781099520
      },
      "churn": {
        "amount": "256000000000000000000",
        "interval_seconds": 384
      }
    },
    "exit_queue": {
      "count": 420,
      "balance": "13440000000000000000000",
      "estimated_processed_at": {
        "epoch": 454053,
        "timestamp": 1781060352
      },
      "churn": {
        "amount": "256000000000000000000",
        "interval_seconds": 384
      }
    },
    "manual_withdrawal_queue": {
      "count": 310,
      "balance": "5120000000000000000000",
      "estimated_processed_at": {
        "epoch": 454210,
        "timestamp": 1781120640
      }
    },
    "withdrawal_sweep": {
      "estimated_sweep_delay": 777600,
      "last_swept_validator_index": 1284503
    },
    "consolidation_queue": {
      "count": 18,
      "balance": "1152000000000000000000",
      "estimated_processed_at": {
        "epoch": 454060,
        "timestamp": 1781063040
      },
      "churn": {
        "amount": "256000000000000000000",
        "interval_seconds": 384
      }
    },
    "compounding_switch_queue": {
      "count": 25,
      "estimated_processed_at": {
        "epoch": 454048,
        "timestamp": 1781058432
      },
      "churn": {
        "amount": "256000000000000000000",
        "interval_seconds": 384
      }
    },
    "finality": "not_finalized"
  }
}
```

In this example: pending inflow = 37,888 + 1,850 = **39,738 ETH**, pending outflow = 13,440 + 5,120 = **18,560 ETH**, net pending flow = **+21,178 ETH** entering staking.

### Inflow Fields (Deposit Queue)

| Field                                  | Description                                                                   |
| -------------------------------------- | ----------------------------------------------------------------------------- |
| `deposit_queue.deposit_count`          | Number of new validator deposits waiting (excludes top-ups)                   |
| `deposit_queue.deposit_balance`        | Total ETH of new validator deposits, in wei                                   |
| `deposit_queue.topup_count`            | Number of top-up deposits waiting (excludes new validator deposits)           |
| `deposit_queue.topup_balance`          | Total ETH of top-ups, in wei                                                  |
| `deposit_queue.estimated_processed_at` | Epoch and Unix timestamp when the **entire** deposit queue will be processed  |
| `deposit_queue.churn`                  | Balance the protocol can process per interval (e.g. wei per 384-second epoch) |

### Outflow Fields (Exit Queue, Manual Withdrawals, Sweep)

| Field                                         | Description                                                                                     |
| --------------------------------------------- | ----------------------------------------------------------------------------------------------- |
| `exit_queue.count`                            | Number of validators waiting to exit                                                            |
| `exit_queue.balance`                          | Total ETH waiting to exit, in wei                                                               |
| `manual_withdrawal_queue.count`               | Pending withdrawal requests (partial withdrawals and exits triggered via withdrawal request)    |
| `manual_withdrawal_queue.balance`             | Total ETH in pending manual withdrawals, in wei                                                 |
| `withdrawal_sweep.estimated_sweep_delay`      | Estimated maximum seconds for the sweep to complete a full rotation and credit withdrawable ETH |
| `withdrawal_sweep.last_swept_validator_index` | Current position of the sweep clock                                                             |

<Note>
  `estimated_processed_at` always refers to the **very last item** in the queue — i.e. when the queue as it stands right now would be fully drained. Queues are `null` when empty.
</Note>

***

## Per-Validator Tracking

Track queue positions for your own validator set — including validators that are still in the deposit queue and have no index yet (select them by public key):

```bash theme={null}
curl --request POST \
  --url https://beaconcha.in/api/v2/ethereum/validators/queues \
  --header 'Authorization: Bearer <YOUR_API_KEY>' \
  --header 'Content-Type: application/json' \
  --data '
{
  "chain": "mainnet",
  "validator": {
    "validator_identifiers": ["0x93247f22...09abcaf5", 1284503]
  },
  "page_size": 10
}
'
```

### Response

```json theme={null}
{
  "data": [
    {
      "validator": {
        "index": null,
        "public_key": "0x93247f22...09abcaf5"
      },
      "deposit_queue": {
        "deposit_count": 1,
        "deposit_balance": "32000000000000000000",
        "topup_count": 0,
        "topup_balance": "0",
        "estimated_processed_at": {
          "epoch": 454102,
          "timestamp": 1781079168
        },
        "churn": {
          "amount": "256000000000000000000",
          "interval_seconds": 384
        }
      },
      "exit_queue": null,
      "manual_withdrawal_queue": null,
      "withdrawal_sweep": null,
      "consolidation_queue": null,
      "compounding_switch_queue": null,
      "finality": "not_finalized"
    },
    {
      "validator": {
        "index": 1284503,
        "public_key": "0xb5a3c901...77fe12d4"
      },
      "deposit_queue": null,
      "exit_queue": {
        "count": 1,
        "balance": "32890000000000000000",
        "estimated_processed_at": {
          "epoch": 454031,
          "timestamp": 1781051904
        },
        "churn": {
          "amount": "256000000000000000000",
          "interval_seconds": 384
        }
      },
      "manual_withdrawal_queue": null,
      "withdrawal_sweep": {
        "min": {
          "estimated_processed_at": {
            "epoch": 454800,
            "timestamp": 1781347200
          }
        },
        "max": {
          "estimated_processed_at": {
            "epoch": 455400,
            "timestamp": 1781577600
          }
        }
      },
      "consolidation_queue": null,
      "compounding_switch_queue": null,
      "finality": "not_finalized"
    }
  ],
  "paging": {
    "next_cursor": ""
  }
}
```

How to read this:

* The first validator is **in activation**: 32 ETH deposited, expected to be processed at epoch 454102. Its `index` is `null` because it has not been activated yet.
* The second validator is **in withdrawal**: its exit is expected at epoch 454031, and the sweep is expected to credit its balance between epochs 454800 and 455400.
* Queues a validator is not part of are returned as `null`.
* If a validator has multiple pending items (e.g. several queued top-ups), `estimated_processed_at` refers to its **last** one.

<Tip>
  **Track whole fleets without index lists:** on [Scale & Enterprise plans](https://beaconcha.in/pricing), the `validator` selector also accepts a `withdrawal` credential/address, a `deposit_address`, or an `entity` name — convenient when your validators all share withdrawal credentials.
</Tip>

***

## Building Historical Snapshots

The Queue APIs return the **current** queue state. To analyze trends — daily net flow, queue growth, average wait times — poll on a schedule and store each snapshot:

```python theme={null}
import csv
import requests
from datetime import datetime, timezone

API_KEY = "<YOUR_API_KEY>"
URL = "https://beaconcha.in/api/v2/ethereum/queues"

headers = {
    "Authorization": f"Bearer {API_KEY}",
    "Content-Type": "application/json",
    "Accept": "application/vnd.beaconcha.in.v2.1+json",  # pin the unified schema
}

data = requests.post(URL, headers=headers, json={"chain": "mainnet"}).json()["data"]

def balance(queue, *fields):
    """Sum wei string fields of a possibly-null queue object."""
    if queue is None:
        return 0
    return sum(int(queue.get(field) or 0) for field in fields)

def eta(queue):
    if queue and queue.get("estimated_processed_at"):
        return queue["estimated_processed_at"]["timestamp"]
    return None

inflow_wei = balance(data["deposit_queue"], "deposit_balance", "topup_balance")
outflow_wei = balance(data["exit_queue"], "balance") + balance(
    data["manual_withdrawal_queue"], "balance"
)

with open("staking_flow_snapshots.csv", "a", newline="") as f:
    csv.writer(f).writerow([
        datetime.now(timezone.utc).isoformat(),
        inflow_wei,
        outflow_wei,
        inflow_wei - outflow_wei,  # net pending flow
        eta(data["deposit_queue"]),
        eta(data["exit_queue"]),
    ])
```

Run it from a scheduler (cron, Airflow, etc.). Queue state changes every epoch (\~6.4 minutes), so per-epoch polling is the maximum useful resolution; **hourly snapshots** are enough for most reporting, and daily snapshots already reveal supply trends.

<Info>
  Snapshots only exist from the moment you start collecting them — set up polling before you need the history.
</Info>

***

## Best Practices

<CardGroup cols={2}>
  <Card title="Treat ETAs as Estimates" icon="chart-simple">
    Estimates assume the current churn rate and queue composition. Re-poll regularly and present time ranges to customers, not exact times.
  </Card>

  <Card title="Sum in Wei, Not Floats" icon="calculator">
    Wei values exceed float64 precision. Parse the string amounts with arbitrary-precision integers and convert to ETH only for display.
  </Card>

  <Card title="Expect Nulls" icon="circle-question">
    Empty or not-applicable queues are returned as `null`. Treat them as zero when aggregating.
  </Card>
</CardGroup>

***

## Related Resources

* [Introduction](/use-cases/queue-tracking) — Overview of the Queue APIs and the staking queues
* [Estimate Queue Wait Times](/use-cases/queue-wait-times) — Turn queue statistics into activation and exit ETAs
* [Understanding Validator Queues](/faqs/understanding-validator-queues) — How the queues work at the protocol level
* [Deposit Process](/faqs/deposit-process) — The full lifecycle of a deposit
* [How Withdrawals Work](/faqs/how-withdrawals-work) — Eligibility delay and the withdrawal sweep
* [Pagination](/api/pagination) — Cursor-based pagination for the per-validator queue endpoint
