> For the complete documentation index, see [llms.txt](https://docs.veda.tech/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.veda.tech/api/vaults.md).

# Vaults

Endpoints for discovering the vaults that belong to your organization and inspecting state on a specific vault. The API uses a "tenant" to represent your organization. All endpoints are tenant-scoped — the tenant is resolved from your API key, and vaults outside your tenancy are not visible.

For authentication, base URL, request/response conventions, and the error envelope, see the [API Reference](/api/api-reference.md). Create an API key first via [Quick Start](/api/quick-start.md). Examples below assume the key is in `$VEDA_API_KEY`.

## Concepts

A **vault** is a set of smart contracts — built on Veda's BoringVault architecture — that abstracts DeFi complexity via a risk manager (also referred to as a curator), and adds enterprise compliance controls. A vault generates yield by allocating depositor funds, per the curator's instructions, to trusted DeFi protocols using predefined yield strategies. Depositors receive **vault receipt tokens** that prove ownership of their deposited funds, and only depositors can withdraw — not Veda, not the curator.

A vault can be deployed on one or more chains; the same `vault_address` appears on each chain it's been deployed to. Its Manager contract on each chain holds that chain's current **merkle root** — a single onchain commitment to the allowlist of actions the curator (or a delegated strategist) is permitted to execute there. For how the allowlist works and how the underlying tree is structured, see [Policy Manager & Merkle Trees](/api/policy-manager-and-merkle-trees.md).

{% hint style="info" %}
**Tenant denial returns 404, not 403.** Asking for a vault that isn't part of your tenant returns `404 vault_not_found` — the API does not distinguish "doesn't exist" from "exists but not yours."
{% endhint %}

***

## 1. List vaults

```
GET /v1/vaults
```

Returns the vaults that belong to the tenant on your API key, across every chain.

### Query parameters

| Name     | Type   | Required | Notes                                                                                 |
| -------- | ------ | -------- | ------------------------------------------------------------------------------------- |
| `cursor` | string | No       | Opaque cursor from a previous response's `page.next_cursor` — omit on the first call. |

### Example request

```bash
curl https://api.veda.tech/v1/vaults \
  -H "Authorization: Bearer $VEDA_API_KEY"
```

### Example response

```json
{
  "data": [
    {
      "vault_address": "0xFDea370fa75353e650Cd6b8055600B04a47F68c2",
      "name":          "Veda Demo Vault",
      "chains":        ["ethereum", "monad"],
      "tenant":        "veda-demo",
      "deployed_at":   "2026-06-03T07:16:26.467008Z",
      "status":        "active",
      "links": {
        "ethereum": {
          "self":  "/vaults/ethereum/0xFDea370fa75353e650Cd6b8055600B04a47F68c2",
          "roots": "/vaults/ethereum/0xFDea370fa75353e650Cd6b8055600B04a47F68c2/roots"
        },
        "monad": {
          "self":  "/vaults/monad/0xFDea370fa75353e650Cd6b8055600B04a47F68c2",
          "roots": "/vaults/monad/0xFDea370fa75353e650Cd6b8055600B04a47F68c2/roots"
        }
      }
    }
  ],
  "page": {
    "next_cursor": "AXsiYWZ0ZXIiOnsiZGVwbG95ZWRfYXQiOiIyMDI2…",
    "page_size":   20,
    "has_more":    true
  }
}
```

* `chains` is the set of chains the vault is deployed on.
* `links` is keyed by chain — each chain has its own `self` and `roots` resource. The link strings are returned unversioned (no `/v1/` prefix); they're resource paths relative to the API host. Prepend `/v1` (or the base URL) when calling them.

### Errors

| Status | Code              | Cause                                |
| ------ | ----------------- | ------------------------------------ |
| `401`  | `unauthenticated` | Missing, expired, or revoked API key |
| `429`  | `rate_limited`    | API key rate limit exceeded          |

See [API Reference → Errors](/api/api-reference.md#errors) for the envelope and the shape of authentication / rate-limit responses.

***

## 2. Get the latest metrics snapshot

```
GET /v1/vaults/{chain}/{vault_address}/metrics/snapshot/latest
```

Returns the most recent metrics snapshot for a vault on a given chain. Snapshots are produced daily by the share-price runner and capture share price, total assets, total supply, per-protocol position breakdown, and asset prices — all at a specific block.

### Path parameters

| Name            | Type   | Notes                                                                   |
| --------------- | ------ | ----------------------------------------------------------------------- |
| `chain`         | string | Lowercase chain slug — see [Chain Support](/resources/chain-support.md) |
| `vault_address` | string | The BoringVault contract address                                        |

### Example request

```bash
curl https://api.veda.tech/v1/vaults/monad/0x1C8a336051D2024E318A229d01F9F6CF96efD316/metrics/snapshot/latest \
  -H "Authorization: Bearer $VEDA_API_KEY"
```

### Example response

```json
{
  "data": {
    "chain":         "monad",
    "vault_address": "0x1C8a336051D2024E318A229d01F9F6CF96efD316",
    "block_number":  84732067,
    "as_of":         "2026-06-30T18:12:51Z",
    "snapshot_type": "yield_streaming",
    "share_price":   "1.001557",
    "total_assets":  "6749.023149",
    "total_supply":  "6737.890909",
    "positions": [
      { "protocol": "ERC20Position",          "asset": "USDC", "balance": "0.00861"     },
      { "protocol": "ERC20Position",          "asset": "mUSD", "balance": "337.201012"  },
      { "protocol": "SteakhouseCorePosition", "asset": "USDC", "balance": "1320.265712" },
      { "protocol": "SteakhouseCorePosition", "asset": "mUSD", "balance": "5091.547819" }
    ],
    "prices": {
      "monad": {
        "USDC": "1",
        "mUSD": "1"
      }
    },
    "base_asset": "mUSD",
    "yield_streaming": {
      "vested_amount":            "0.641343854687",
      "vesting_duration_seconds": 43200
    }
  }
}
```

* `as_of` is the ISO-8601 UTC timestamp of the snapshot's source block; `block_number` is that block.
* `snapshot_type` indicates the metric model used for this vault (e.g. `yield_streaming`). Type-specific fields (like the `yield_streaming` block below) only appear when the corresponding `snapshot_type` is active.
* `share_price`, `total_assets`, `total_supply`, position `balance`s, prices in `prices`, and `yield_streaming.vested_amount` are returned as **strings** to preserve full precision for assets whose values can fall outside safe float ranges.
* `positions` is the per-protocol breakdown of vault holdings as of `block_number`. Each entry is `{ protocol, asset, balance }`. To value a position in the vault's base asset, look up its price at `prices[chain][asset]` and multiply: `balance × price`.
* `prices` is a top-level chain → asset → string-price map. The base case is one chain (the vault's own); the structure leaves room for cross-chain holdings.
* `base_asset` is the asset that `share_price`, `total_assets`, and `total_supply` are denominated in. May come back as `"unknown"` for snapshots where the base asset hasn't been resolved yet.
* `yield_streaming` is present only when `snapshot_type` is `yield_streaming` — see [About yield streaming](#about-yield-streaming) below for what these fields represent and why the vault uses this model.

### About yield streaming

Yield-streaming vaults distribute earned yield linearly into the share price over a configurable vesting window, instead of applying it as a single rate jump. This defends against MEV and other value-extraction attacks on discrete rate updates — an attacker who front-runs a rate jump only captures the sliver of yield that has vested between their deposit and its execution, so the attack isn't profitable.

When `snapshot_type` is `yield_streaming`, the `yield_streaming` block on the response reports the current vesting tranche:

* **`vested_amount`** (string, denominated in `base_asset`) — the size of the yield tranche being streamed into the share price over the current window. This entire amount accrues into `share_price` linearly across the window.
* **`vesting_duration_seconds`** (int) — length of the vesting window in seconds. Production vaults typically use `43200` (12 hours).

### Errors

| Status | Code              | Cause                                                        |
| ------ | ----------------- | ------------------------------------------------------------ |
| `401`  | `unauthenticated` | Missing, expired, or revoked API key                         |
| `404`  | `vault_not_found` | Vault does not exist on this chain, or is not in your tenant |
| `429`  | `rate_limited`    | API key rate limit exceeded                                  |

***

## 3. List metrics snapshot history

```
GET /v1/vaults/{chain}/{vault_address}/metrics/snapshot
```

Returns the history of metrics snapshots for a vault on a given chain — newest first. Each entry has the same shape as [Get the latest metrics snapshot](#id-2.-get-the-latest-metrics-snapshot). Cursor-paginated.

### Path parameters

| Name            | Type   | Notes                                                                   |
| --------------- | ------ | ----------------------------------------------------------------------- |
| `chain`         | string | Lowercase chain slug — see [Chain Support](/resources/chain-support.md) |
| `vault_address` | string | The BoringVault contract address                                        |

### Query parameters

| Name     | Type   | Required | Notes                                                                                 |
| -------- | ------ | -------- | ------------------------------------------------------------------------------------- |
| `cursor` | string | No       | Opaque cursor from a previous response's `page.next_cursor` — omit on the first call. |

### Example request

```bash
curl https://api.veda.tech/v1/vaults/monad/0x1C8a336051D2024E318A229d01F9F6CF96efD316/metrics/snapshot \
  -H "Authorization: Bearer $VEDA_API_KEY"
```

### Example response (abbreviated)

```json
{
  "data": [
    {
      "chain":           "monad",
      "vault_address":   "0x1C8a336051D2024E318A229d01F9F6CF96efD316",
      "block_number":    84732067,
      "as_of":           "2026-06-30T18:12:51Z",
      "snapshot_type":   "yield_streaming",
      "share_price":     "1.001557",
      "total_assets":    "6749.023149",
      "total_supply":    "6737.890909",
      "positions":       [ /* … */ ],
      "prices":          { "monad": { "USDC": "1", "mUSD": "1" } },
      "base_asset":      "mUSD",
      "yield_streaming": { "vested_amount": "0.641343854687", "vesting_duration_seconds": 43200 }
    },
    {
      "chain":           "monad",
      "vault_address":   "0x1C8a336051D2024E318A229d01F9F6CF96efD316",
      "block_number":    84620800,
      "as_of":           "2026-06-30T05:51:27Z",
      "snapshot_type":   "yield_streaming",
      "share_price":     "1.001501",
      "total_assets":    "6642.001144",
      "total_supply":    "6631.681047",
      "positions":       [ /* … */ ],
      "prices":          { "monad": { "mUSD": "1", "USDC": "1" } },
      "base_asset":      "mUSD",
      "yield_streaming": { "vested_amount": "0.365943748453", "vesting_duration_seconds": 43200 }
    }
  ],
  "page": {
    "next_cursor": null,
    "page_size":   20,
    "has_more":    false
  }
}
```

### Errors

| Status | Code              | Cause                                                        |
| ------ | ----------------- | ------------------------------------------------------------ |
| `401`  | `unauthenticated` | Missing, expired, or revoked API key                         |
| `404`  | `vault_not_found` | Vault does not exist on this chain, or is not in your tenant |
| `429`  | `rate_limited`    | API key rate limit exceeded                                  |

***

## 4. List roots set on a vault

```
GET /v1/vaults/{chain}/{vault_address}/roots
```

Returns the roots that have been set on a vault on a given chain — both current and historical. Tenant-scoped: a vault outside your tenant (or a chain the vault isn't deployed on) returns `404 vault_not_found`. Cursor-paginated. Default sort: `active DESC` — active roots first, then inactive.

### Path parameters

| Name            | Type   | Notes                                                                   |
| --------------- | ------ | ----------------------------------------------------------------------- |
| `chain`         | string | Lowercase chain slug — see [Chain Support](/resources/chain-support.md) |
| `vault_address` | string | The BoringVault contract address                                        |

### Query parameters

| Name     | Type   | Required | Notes                                                                                 |
| -------- | ------ | -------- | ------------------------------------------------------------------------------------- |
| `cursor` | string | No       | Opaque cursor from a previous response's `page.next_cursor` — omit on the first call. |

### Example request

```bash
curl https://api.veda.tech/v1/vaults/ethereum/0x6fDcB0654B4814c2eC1E7e9dbC4cEBf1a2038a84/roots \
  -H "Authorization: Bearer $VEDA_API_KEY"
```

### Example response

```json
{
  "data": [
    {
      "root_hash":   "0xb8b546c6ea05423782d5dcdf55f0153dbdbb7b9877c72b8d06ae689db9751a68",
      "strategist":  "0x3000D05DFb41171c1cE9fED802C6fC77cb8e0C69",
      "active":      true,
      "set_at":      null,
      "set_tx_hash": null,
      "leaf_count":  null,
      "links": { "tree": "/trees/0xb8b546c6ea05423782d5dcdf55f0153dbdbb7b9877c72b8d06ae689db9751a68" }
    }
  ],
  "page": {
    "next_cursor": null,
    "page_size":   20,
    "has_more":    false
  }
}
```

* One entry is returned per `(root_hash, strategist)` pair — a vault that authorizes multiple strategists under the same root appears multiple times, once per strategist.

### Errors

| Status | Code              | Cause                                                            |
| ------ | ----------------- | ---------------------------------------------------------------- |
| `401`  | `unauthenticated` | Missing, expired, or revoked API key                             |
| `404`  | `vault_not_found` | Vault does not exist on this chain, **or** is not in your tenant |
| `429`  | `rate_limited`    | API key rate limit exceeded                                      |

***

## 5. List daily data

```
GET /v1/vaults/{chain}/{vault_address}/dailyData
```

Returns the daily share-price, APY, TVL, and base-asset accounting series for a vault over a date range. Cursor-paginated; the requested range is echoed back on `meta` so the response is self-describing.

{% hint style="info" %}
This endpoint uses the camel-case path segment `dailyData` to match the upstream contract; the rest of the API uses snake\_case in paths.
{% endhint %}

### Path parameters

| Name            | Type   | Notes                                                                   |
| --------------- | ------ | ----------------------------------------------------------------------- |
| `chain`         | string | Lowercase chain slug — see [Chain Support](/resources/chain-support.md) |
| `vault_address` | string | The BoringVault contract address                                        |

### Query parameters

| Name     | Type   | Required | Notes                                                                                                                        |
| -------- | ------ | -------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `from`   | string | No       | Start of the range, ISO-8601 UTC (e.g. `2026-05-01T00:00:00Z`). Omit to default to the earliest available day for the vault. |
| `to`     | string | No       | End of the range, ISO-8601 UTC (e.g. `2026-06-12T00:00:00Z`). Omit to default to the latest available day for the vault.     |
| `cursor` | string | No       | Opaque cursor from a previous response's `page.next_cursor` — omit on the first call.                                        |

Calling the endpoint without `from` / `to` returns the full series for the vault, paginated. The `meta` block on the response reflects the **effective** range applied by the server, so you can tell what window the data actually covers even when you omit one or both params.

### Example request

```bash
curl 'https://api.veda.tech/v1/vaults/ethereum/0x13Cc1b39cb259BA10cd174EAe42012e698ed7c51/dailyData?from=2026-05-01T00:00:00Z&to=2026-06-12T00:00:00Z' \
  -H "Authorization: Bearer $VEDA_API_KEY"
```

### Example response

```json
{
  "data": [
    {
      "vault_address": "0x13Cc1b39cb259BA10cd174EAe42012e698ed7c51",
      "chain":         "ethereum",
      "as_of":         "2026-06-12T00:00:00Z",
      "block_number":  22489231,
      "daily_apy":     0.015506100540390087,
      "price_usd":     "1.00",
      "share_price":   1.082341,
      "total_assets":  "4250000.000000",
      "tvl_usd":       "4250000.00"
    }
  ],
  "meta": {
    "from": "2026-05-01T00:00:00Z",
    "to":   "2026-06-12T00:00:00Z"
  },
  "page": {
    "next_cursor": null,
    "page_size":   90,
    "has_more":    false
  }
}
```

* One entry per day in the requested range, in chronological order.
* `share_price` and `daily_apy` are floats; `total_assets`, `tvl_usd`, and `price_usd` are returned as strings to preserve full precision for assets whose value can fall outside safe float ranges.
* `daily_apy` is fractional — `0.015506…` means `1.55%`, not `155%`.
* `meta.from` / `meta.to` report the **effective** range the server applied — either the values you supplied, or the defaults (earliest and latest available days) when omitted.

### Errors

| Status | Code                | Cause                                                        |
| ------ | ------------------- | ------------------------------------------------------------ |
| `401`  | `unauthenticated`   | Missing, expired, or revoked API key                         |
| `404`  | `vault_not_found`   | Vault does not exist on this chain, or is not in your tenant |
| `422`  | `validation_failed` | `from` / `to` malformed, or `to` ≤ `from`                    |
| `429`  | `rate_limited`      | API key rate limit exceeded                                  |

***

## 6. Get performance

```
GET /v1/vaults/{chain}/{vault_address}/performance
```

Returns the vault's yield performance — a top-level annualized APY plus a breakdown of where that yield comes from.

{% hint style="info" %}
All APY and fee values in the response are **expressed as decimals**. Multiply by `100` to get a percentage — `0.043` = `4.3%`.
{% endhint %}

For a longer walkthrough of each field, see the [Performance APY User Guide](https://help.veda.tech/article/veda-api-user-guide#performance-api).

### Path parameters

| Name            | Type   | Notes                                                                   |
| --------------- | ------ | ----------------------------------------------------------------------- |
| `chain`         | string | Lowercase chain slug — see [Chain Support](/resources/chain-support.md) |
| `vault_address` | string | The BoringVault contract address                                        |

### Example request

```bash
curl https://api.veda.tech/v1/vaults/ethereum/0x13Cc1b39cb259BA10cd174EAe42012e698ed7c51/performance \
  -H "Authorization: Bearer $VEDA_API_KEY"
```

### Example response

```json
{
  "data": {
    "vault_address":    "0x13cc1b39cb259ba10cd174eae42012e698ed7c51",
    "chain":            "ethereum",
    "as_of":            "2026-07-17T00:00:00Z",
    "window_days":      7,
    "apy":              0.008445101089285182,
    "fees":             0.0025,
    "performance_fees": 0.1,
    "global_apy_breakdown": {
      "fee":          0.003438344565476132,
      "maturity_apy": 0,
      "real_apy":     0.008445101089285182
    },
    "maturity_apy_breakdown": [],
    "real_apy_breakdown": [
      {
        "allocation": 0.9999999916128769,
        "apy":        0.012062023778707017,
        "apy_net":    0.010855821400836315,
        "chain":      "ethereum",
        "protocol":   "morpho"
      }
    ]
  }
}
```

### Top-level APY

The top-level `apy` field is the vault's annualized yield based on share-price changes over a **trailing 7-day window**. It's the source of truth for vault performance:

* **Share price is the foundation.** The vault's share price reflects total assets divided by total shares outstanding — as the vault earns yield, share price increases.
* **Daily-updated.** The share price on the API reflects the daily-updated share price.
* **7-day trailing average.** Rather than showing day-to-day volatility, the APY is smoothed over the past 7 days to give a more stable, representative number.
* **Net of fees.** The top-level APY is already net of fees.

### APY components

`global_apy_breakdown` decomposes the vault's return into three contributions:

* **`real_apy`** — variable-rate real yield
* **`maturity_apy`** — fixed-rate maturity products (e.g. dated lending)
* **`fee`** — total fees deducted, expressed as an APY drag

`real_apy_breakdown` lists per-protocol APY contributions with allocation weights. Each entry shows:

* **`allocation`** — a point-in-time snapshot of what share of vault assets is currently in that position. This is a **daily** snapshot.
* **`apy`** — the position's 7-day trailing APY, **gross** of position-level fees.
* **`apy_net`** — the same rate net of position-level fees. Only present when position-level fees apply.
* **`chain`**, **`protocol`** — where the position lives.

The time periods are intentionally different — allocation is today's snapshot, APY is a 7-day trailing average.

`maturity_apy_breakdown` lists fixed-rate maturity positions individually. Empty when the vault holds none.

### Fees

Three fee-related fields appear in the response:

* **`fees`** — platform fee, as an annual rate.
* **`performance_fees`** — performance fee, the rate applied to generated yield. **Nullable** — comes back as `null` for vaults with no performance fee configured.
* **`fee`** (inside `global_apy_breakdown`) — total fees deducted, expressed as an APY drag.

Fees are stored in **basis points** on-chain (1 bps = 0.01%) and converted to **decimals** in the API response.

### Other response fields

* `as_of` is the ISO-8601 UTC timestamp the summary is anchored to (start of the day it was computed for).
* `window_days` is fixed at `7 days`.
* `vault_address` may come back lowercased today rather than EIP-55 checksummed — compare case-insensitively.

### Errors

| Status | Code              | Cause                                                        |
| ------ | ----------------- | ------------------------------------------------------------ |
| `401`  | `unauthenticated` | Missing, expired, or revoked API key                         |
| `404`  | `vault_not_found` | Vault does not exist on this chain, or is not in your tenant |
| `429`  | `rate_limited`    | API key rate limit exceeded                                  |

***

**Go on to next:** [Policy Manager & Merkle Trees](/api/policy-manager-and-merkle-trees.md) — how a vault's allowlist is encoded as a merkle tree and committed onchain.
