# On-chain data

> Total value locked in DeFi protocols, by protocol and chain.

Page: https://docs.aggre.org/api/data/onchain · Section: API reference · All pages: https://docs.aggre.org/llms.txt

On-chain datasets. See the [on-chain guide](https://docs.aggre.org/datasets/onchain.md).

On this page:

- [DeFi protocol total value locked](#listOnchainProtocolTvl): `GET /v1/onchain/defi/protocol_tvl`

## DeFi protocol total value locked {#listOnchainProtocolTvl}

`GET /v1/onchain/defi/protocol_tvl`

One row per protocol per UTC day (`as_of` is the day Aggre read the figure; history starts the day the worker first ran, nothing is backfilled). Two shapes, chosen by `slug`. **A day** (no `slug`): every protocol of one day ordered by TVL rank (1 is the largest), the newest stored day unless `as_of` names one; `category` (exact, case-sensitive) and `chain` (one element of `chains`, exact) narrow it; `from`, `to` and `order` are 400 here. **A history** (`slug`): that protocol's rows over time, newest first unless `order=asc`; `from` is inclusive and `to` exclusive, both `YYYY-MM-DD`; `as_of`, `category` and `chain` are 400 there. A cursor pins its day. `tvl_usd` is a JSON number (a double), a figure the source leaves out is `null`, never zero. Whoever shows a row shows `meta.dataset.credit`. `meta.status`: `empty` for no rows, `stale` when the answer follows the newest data and our newest successful read is more than 3 days old, otherwise `ok`. 503 `terms_unread` until a person has read the publisher's terms; the route then reads no row. Dataset `onchain.defi.protocol_tvl`, also listed under `finance.market`. [the on-chain guide](https://docs.aggre.org/datasets/onchain.md).

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `slug` | query | no | string, pattern `^[a-z0-9][a-z0-9._-]{0,127}$` | One protocol's history, as listed in `slug`: lower-case letters, digits, `.`, `_`, `-`. |
| `as_of` | query | no | string, date | A day: the UTC day to list, YYYY-MM-DD. Default the newest stored day. Not with `slug`. |
| `from` | query | no | string, date | A history: first day (inclusive), YYYY-MM-DD. Needs `slug`. |
| `to` | query | no | string, date | A history: last day (exclusive), YYYY-MM-DD, after `from`. Needs `slug`. |
| `category` | query | no | string | A day: only this category, exact as the source writes it (1-100 characters). Not with `slug`. |
| `chain` | query | no | string | A day: only protocols deployed on this chain, exact as the source writes it (1-100 characters). Not with `slug`. |
| `order` | query | no | `asc` \| `desc` (default `desc`) | A history: sort direction (default newest first). Needs `slug`; a day is always by rank. |
| `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. |
| `limit` | query | no | integer, 1–1000, default `100` | Rows per page. |

**Example**

```bash
curl -s "https://api.aggre.org/v1/onchain/defi/protocol_tvl?limit=3" \
  -H "Authorization: Bearer $AGGRE_API_KEY"
```

**Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`onchain_protocol_tvl`](https://docs.aggre.org/api/schemas.md#onchain_protocol_tvl).

**Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)).
