> For the complete documentation index, see [llms.txt](https://docs.lagoon.finance/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.lagoon.finance/developer-hub/lagoon-api/common-queries.md).

# Common queries

Copy-pasteable curl recipes for the queries integrators reach for first.

Every recipe below shows the query itself in a `graphql` block, a one-click link that opens [Apollo Sandbox](https://api.lagoon.finance/query) with the query pre-loaded, and the equivalent `curl` call. Replace the example vault address, chain ID, or user address with your own and the queries will return live data.

## Recipes

| # | Recipe                                                                            | What it returns                                                            |
| - | --------------------------------------------------------------------------------- | -------------------------------------------------------------------------- |
| 1 | [List vaults on a chain](#list-vaults-on-a-chain)                                 | Paginated vaults filtered by chain & visibility, with state and APR.       |
| 2 | [Get a single vault by address](#get-a-single-vault-by-address)                   | One vault with full current state, asset, and chain.                       |
| 3 | [Get a user's positions across vaults](#get-a-users-positions-across-vaults)      | A user's share balance and pending/claimable deposits and redeems.         |
| 4 | [Stream vault events](#stream-vault-events)                                       | Recent on-chain events for a vault, typed via the `TransactionData` union. |
| 5 | [Historical vault state at a timestamp](#historical-vault-state-at-a-timestamp)   | Point-in-time reconstruction via `stateAt`.                                |
| 6 | [Global Lagoon TVL](#global-lagoon-tvl)                                           | Aggregate USD TVL across all Lagoon vaults.                                |
| — | [How the Lagoon dApp uses these queries](#how-the-lagoon-dapp-uses-these-queries) | Patterns from the production frontend worth copying.                       |

## List vaults on a chain

Top vaults on Ethereum by USD TVL, paginated, only those visible on the Lagoon frontend:

```graphql
query ListVaults {
  vaults(
    first: 10
    skip: 0
    orderBy: totalAssetsUsd
    orderDirection: desc
    where: { chainId_eq: 1, isVisible_eq: true }
  ) {
    items {
      address
      name
      symbol
      state {
        totalAssetsUsd
        pricePerShareUsd
        yearlyApr { linearNetApr twrrNetApr }
      }
    }
    pageInfo { hasNextPage totalCount }
  }
}
```

[**Try in Apollo Sandbox →**](https://api.lagoon.finance/query?document=query%20ListVaults%20%7B%0A%20%20vaults%28%0A%20%20%20%20first%3A%2010%0A%20%20%20%20skip%3A%200%0A%20%20%20%20orderBy%3A%20totalAssetsUsd%0A%20%20%20%20orderDirection%3A%20desc%0A%20%20%20%20where%3A%20%7B%20chainId_eq%3A%201%2C%20isVisible_eq%3A%20true%20%7D%0A%20%20%29%20%7B%0A%20%20%20%20items%20%7B%0A%20%20%20%20%20%20address%0A%20%20%20%20%20%20name%0A%20%20%20%20%20%20symbol%0A%20%20%20%20%20%20state%20%7B%0A%20%20%20%20%20%20%20%20totalAssetsUsd%0A%20%20%20%20%20%20%20%20pricePerShareUsd%0A%20%20%20%20%20%20%20%20yearlyApr%20%7B%20linearNetApr%20twrrNetApr%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%20%20pageInfo%20%7B%20hasNextPage%20totalCount%20%7D%0A%20%20%7D%0A%7D)

```bash
curl -sS -X POST https://api.lagoon.finance/query \
  -H "Content-Type: application/json" \
  -d '{"query":"query ListVaults { vaults(first: 10, skip: 0, orderBy: totalAssetsUsd, orderDirection: desc, where: { chainId_eq: 1, isVisible_eq: true }) { items { address name symbol state { totalAssetsUsd pricePerShareUsd yearlyApr { linearNetApr twrrNetApr } } } pageInfo { hasNextPage totalCount } } }"}'
```

Returns `items` (the vaults) plus `pageInfo.totalCount` for total match count and `pageInfo.hasNextPage` for paging.

## Get a single vault by address

Fetch one vault with its current state, underlying asset, and chain:

```graphql
query GetVault {
  vaultByAddress(
    address: "0x936facdf10c8c36294e7b9d28345255539d81bc7"
    chainId: 1
  ) {
    address
    name
    symbol
    creationDate
    asset { address symbol decimals }
    chain { id name }
    state {
      totalAssets
      totalSupply
      pricePerShare
      pricePerShareUsd
      totalAssetsUsd
      managementFee
      performanceFee
      syncMode
    }
  }
}
```

[**Try in Apollo Sandbox →**](https://api.lagoon.finance/query?document=query%20GetVault%20%7B%0A%20%20vaultByAddress%28%0A%20%20%20%20address%3A%20%220x936facdf10c8c36294e7b9d28345255539d81bc7%22%0A%20%20%20%20chainId%3A%201%0A%20%20%29%20%7B%0A%20%20%20%20address%0A%20%20%20%20name%0A%20%20%20%20symbol%0A%20%20%20%20creationDate%0A%20%20%20%20asset%20%7B%20address%20symbol%20decimals%20%7D%0A%20%20%20%20chain%20%7B%20id%20name%20%7D%0A%20%20%20%20state%20%7B%0A%20%20%20%20%20%20totalAssets%0A%20%20%20%20%20%20totalSupply%0A%20%20%20%20%20%20pricePerShare%0A%20%20%20%20%20%20pricePerShareUsd%0A%20%20%20%20%20%20totalAssetsUsd%0A%20%20%20%20%20%20managementFee%0A%20%20%20%20%20%20performanceFee%0A%20%20%20%20%20%20syncMode%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D)

```bash
curl -sS -X POST https://api.lagoon.finance/query \
  -H "Content-Type: application/json" \
  -d '{"query":"query GetVault { vaultByAddress(address: \"0x936facdf10c8c36294e7b9d28345255539d81bc7\", chainId: 1) { address name symbol creationDate asset { address symbol decimals } chain { id name } state { totalAssets totalSupply pricePerShare pricePerShareUsd totalAssetsUsd managementFee performanceFee syncMode } } }"}'
```

`state` carries every live metric (TVL, supply, price-per-share, fees, sync mode, guardrails, roles). Pick only the fields you need.

## Get a user's positions across vaults

A user's full position on a given chain — share balance, pending and claimable deposits, pending and claimable redeems — in one round trip:

```graphql
query GetUserPositions($address: Address!, $chainId: Int!) {
  userByAddress(address: $address, chainId: $chainId) {
    address
    vaultPositions {
      vault { address name symbol }
      state {
        balance
        usd
        pendingDeposit { assets shares }
        pendingRedeem { assets shares isCancelable }
        claimableDeposit { assets shares assetsActualized }
        claimableRedeem { assets shares }
      }
    }
  }
}
```

[**Try in Apollo Sandbox →**](https://api.lagoon.finance/query?document=query%20GetUserPositions%28%24address%3A%20Address%21%2C%20%24chainId%3A%20Int%21%29%20%7B%0A%20%20userByAddress%28address%3A%20%24address%2C%20chainId%3A%20%24chainId%29%20%7B%0A%20%20%20%20address%0A%20%20%20%20vaultPositions%20%7B%0A%20%20%20%20%20%20vault%20%7B%20address%20name%20symbol%20%7D%0A%20%20%20%20%20%20state%20%7B%0A%20%20%20%20%20%20%20%20balance%0A%20%20%20%20%20%20%20%20usd%0A%20%20%20%20%20%20%20%20pendingDeposit%20%7B%20assets%20shares%20%7D%0A%20%20%20%20%20%20%20%20pendingRedeem%20%7B%20assets%20shares%20isCancelable%20%7D%0A%20%20%20%20%20%20%20%20claimableDeposit%20%7B%20assets%20shares%20assetsActualized%20%7D%0A%20%20%20%20%20%20%20%20claimableRedeem%20%7B%20assets%20shares%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D)

```bash
curl -sS -X POST https://api.lagoon.finance/query \
  -H "Content-Type: application/json" \
  -d '{
    "query": "query GetUserPositions($address: Address!, $chainId: Int!) { userByAddress(address: $address, chainId: $chainId) { address vaultPositions { vault { address name symbol } state { balance usd pendingDeposit { assets shares } pendingRedeem { assets shares isCancelable } claimableDeposit { assets shares assetsActualized } claimableRedeem { assets shares } } } } }",
    "variables": { "address": "0xUSER", "chainId": 1 }
  }'
```

This is the off-chain equivalent of the three on-chain calls described in [Get a user position](/developer-hub/integration/get-a-user-position.md) (`balanceOf` + `maxMint` + `pendingRedeemRequest`), plus the dollar value and the claimable-deposit current-price actualization.

## Stream vault events

Most recent settlement events for a vault, with the event payload pulled from the `TransactionData` union via inline fragments:

```graphql
query StreamVaultEvents {
  transactions(
    first: 20
    skip: 0
    orderBy: timestamp
    orderDirection: desc
    where: {
      vault_in: ["0x936facdf10c8c36294e7b9d28345255539d81bc7"]
      type_in: [TotalAssetsUpdated, SettleDeposit, SettleRedeem, FeeTaken]
    }
  ) {
    items {
      timestamp
      blockNumber
      hash
      type
      data {
        __typename
        ... on TotalAssetsUpdated { totalAssets }
        ... on SettleDeposit { totalAssets totalSupply }
        ... on SettleRedeem { totalAssets totalSupply }
        ... on FeeTaken { feeType totalShares }
      }
    }
    pageInfo { hasNextPage totalCount }
  }
}
```

[**Try in Apollo Sandbox →**](https://api.lagoon.finance/query?document=query%20StreamVaultEvents%20%7B%0A%20%20transactions%28%0A%20%20%20%20first%3A%2020%0A%20%20%20%20skip%3A%200%0A%20%20%20%20orderBy%3A%20timestamp%0A%20%20%20%20orderDirection%3A%20desc%0A%20%20%20%20where%3A%20%7B%0A%20%20%20%20%20%20vault_in%3A%20%5B%220x936facdf10c8c36294e7b9d28345255539d81bc7%22%5D%0A%20%20%20%20%20%20type_in%3A%20%5BTotalAssetsUpdated%2C%20SettleDeposit%2C%20SettleRedeem%2C%20FeeTaken%5D%0A%20%20%20%20%7D%0A%20%20%29%20%7B%0A%20%20%20%20items%20%7B%0A%20%20%20%20%20%20timestamp%0A%20%20%20%20%20%20blockNumber%0A%20%20%20%20%20%20hash%0A%20%20%20%20%20%20type%0A%20%20%20%20%20%20data%20%7B%0A%20%20%20%20%20%20%20%20__typename%0A%20%20%20%20%20%20%20%20...%20on%20TotalAssetsUpdated%20%7B%20totalAssets%20%7D%0A%20%20%20%20%20%20%20%20...%20on%20SettleDeposit%20%7B%20totalAssets%20totalSupply%20%7D%0A%20%20%20%20%20%20%20%20...%20on%20SettleRedeem%20%7B%20totalAssets%20totalSupply%20%7D%0A%20%20%20%20%20%20%20%20...%20on%20FeeTaken%20%7B%20feeType%20totalShares%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%20%20pageInfo%20%7B%20hasNextPage%20totalCount%20%7D%0A%20%20%7D%0A%7D)

```bash
curl -sS -X POST https://api.lagoon.finance/query \
  -H "Content-Type: application/json" \
  -d '{"query":"query StreamVaultEvents { transactions(first: 20, skip: 0, orderBy: timestamp, orderDirection: desc, where: { vault_in: [\"0x936facdf10c8c36294e7b9d28345255539d81bc7\"], type_in: [TotalAssetsUpdated, SettleDeposit, SettleRedeem, FeeTaken] }) { items { timestamp blockNumber hash type data { __typename ... on TotalAssetsUpdated { totalAssets } ... on SettleDeposit { totalAssets totalSupply } ... on SettleRedeem { totalAssets totalSupply } ... on FeeTaken { feeType totalShares } } } pageInfo { hasNextPage totalCount } } }"}'
```

`TransactionData` is a union — request only the variants you care about with `... on EventName` fragments. The full list of event types is in the `TransactionType` enum (browsable in Sandbox). See [Key data structures and epoch mechanism](/developer-hub/key-data-structures-and-epoch-mechanism.md) for the semantics of each event.

## Historical vault state at a timestamp

Reconstruct a vault as it existed at a past Unix timestamp:

```graphql
query HistoricalVaultState {
  vaultByAddress(
    address: "0x936facdf10c8c36294e7b9d28345255539d81bc7"
    chainId: 1
  ) {
    stateAt(timestamp: 1780000000) {
      totalAssets
      totalSupply
      pricePerShare
      pricePerShareUsd
      totalAssetsUsd
      managementFee
      performanceFee
      state
    }
  }
}
```

[**Try in Apollo Sandbox →**](https://api.lagoon.finance/query?document=query%20HistoricalVaultState%20%7B%0A%20%20vaultByAddress%28%0A%20%20%20%20address%3A%20%220x936facdf10c8c36294e7b9d28345255539d81bc7%22%0A%20%20%20%20chainId%3A%201%0A%20%20%29%20%7B%0A%20%20%20%20stateAt%28timestamp%3A%201780000000%29%20%7B%0A%20%20%20%20%20%20totalAssets%0A%20%20%20%20%20%20totalSupply%0A%20%20%20%20%20%20pricePerShare%0A%20%20%20%20%20%20pricePerShareUsd%0A%20%20%20%20%20%20totalAssetsUsd%0A%20%20%20%20%20%20managementFee%0A%20%20%20%20%20%20performanceFee%0A%20%20%20%20%20%20state%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D)

```bash
curl -sS -X POST https://api.lagoon.finance/query \
  -H "Content-Type: application/json" \
  -d '{"query":"query HistoricalVaultState { vaultByAddress(address: \"0x936facdf10c8c36294e7b9d28345255539d81bc7\", chainId: 1) { stateAt(timestamp: 1780000000) { totalAssets totalSupply pricePerShare pricePerShareUsd totalAssetsUsd managementFee performanceFee state } } }"}'
```

`stateAt` returns `null` (or a `BAD_USER_INPUT` error) for timestamps before the vault's first indexed state. For a time series of any of these fields, use `stateHistory` instead — see [Conventions → Historical data](/developer-hub/lagoon-api/conventions.md#historical-data).

## Global Lagoon TVL

```graphql
{
  getGlobalTVL
}
```

[**Try in Apollo Sandbox →**](https://api.lagoon.finance/query?document=%7B%0A%20%20getGlobalTVL%0A%7D)

```bash
curl -sS -X POST https://api.lagoon.finance/query \
  -H "Content-Type: application/json" \
  -d '{"query":"{ getGlobalTVL }"}'
```

Returns a single `Float` — the aggregate USD TVL across all Lagoon vaults, sourced from DeFiLlama.

## How the Lagoon dApp uses these queries

The production [app.lagoon.finance](https://app.lagoon.finance) frontend is built on exactly this API. A few patterns from that integration that are worth copying:

* **Server-side fetch, no client library.** The dApp uses plain `fetch` with `cache: 'no-store'` from Next.js route handlers — no Apollo or urql. Letting the framework handle revalidation (ISR / `revalidate` directives) is simpler than maintaining a normalized cache, and the API returns whole entities anyway.
* **Compose queries from fragments.** Vault listing pages and vault detail pages share a `VaultFields` fragment but pick different sub-fragments (`VaultFieldsListLight` skips APR data for fast homepage rendering; `VaultFieldsDetail` adds composition, fees, and roles). Define one fragment per logical view and interpolate into multiple queries.
* **`isVisible_eq: true` for frontend listings.** Vaults flagged as not visible are still indexed and queryable, but should be filtered out of any list shown to end users.
* **Page with `pageInfo.totalCount` and `hasNextPage`.** The dApp's transaction-history view does offset pagination with a small `first` value (e.g. 10) and uses `totalCount` to render the page count up-front.
* **Health-check on every request batch.** Route handlers that fan out to multiple queries include `_meta { lastIndexedBlocks { chainId number } }` so the UI can surface "data may be stale" when a chain is more than \~1 hour behind.
* **Lowercased addresses in filters.** Always normalize address inputs (e.g. with viem's `getAddress` / `.toLowerCase()`) before passing them to `_eq` / `_in` filters.
