# TVL-weighted realized vs quoted APR over a cut

Endpoint reference for the 1delta API. Index: https://docs.1delta.io/llms.txt · every endpoint: https://docs.1delta.io/llms-full.txt

---

### GET /v1/data/lending/realized

- operationId: `lending-realized`
- docs: https://docs.1delta.io/1delta-api/lending-realized/
- markdown: https://docs.1delta.io/1delta-api/lending-realized.md
- tags: Lending (Data)

TVL-weighted realized vs quoted APR over a cut

**What did a venue actually pay, as opposed to advertise?** Realized APR from each market's own accumulator (supply index / share price), weighted by size, rolled up over one cut — `by=lender` (e.g. `AAVE_V3`), `by=chain` or `by=asset` (asset group). Each row carries `realizedAprPct`, `quotedAprPct` (the same weighting over the quoted rate) and `gapPp` — realized minus quoted, in percentage points.

**Two guards, and both are COUNTED on the row rather than applied silently** (`excluded`):

- `unrealizableRate` — a market pinned at 100 % utilization with a runaway IRM publishes hundreds of percent against a few dollars of withdrawable liquidity. It is a real market and it belongs in the withdrawability metrics, but in a size-weighted rate mean it would dominate whatever it survived into. The test needs BOTH halves (over 100 % APR **and** under a thousandth of the market withdrawable): a high rate alone can be a genuine incentive campaign, and zero liquidity alone is an ordinary fully-lent pool.
- `nominalAccrualBadDebt` — markets whose "interest" is accrued book value on a defaulted, fully-utilized position. Not capital anyone received, so excluded outright.
- `noAccumulator` — no recorded index over the window. Those markets contribute **nothing**, never their quote, so a thin cut reads as thin instead of as agreement between realized and quoted.

Realized coverage follows the accumulator: vault rows have hourly share prices, lending rows have an index only where the live writer or a backfill has produced one.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `by` | query | string | no | The cut: `lender`, `chain` or `asset`. |
| `days` | query | integer | no | Window in days (1–1095). |
| `chainId` | query | string | no | Restrict to one chain. See the `ChainId` schema for the full set of supported chains. |
| `minTvlUsd` | query | number | no | Drop markets smaller than this before weighting. |

**Response `200`** — Rows of `{ key, markets, tvlUsd, realizedAprPct, quotedAprPct, gapPp, excluded }`, largest cut first.

| Field | Type | Description |
| --- | --- | --- |
| `success` | true |  |
| `data` | object | Informational payload. `null` when the endpoint only builds calldata. |
| `actions` | null |  |

**Example response**

```json
{
  "success": true,
  "data": {}
}
```

**Response `400`** — Validation error

**Response `429`** — Rate limited. Unauthenticated callers share a per-IP budget; send an `x-api-key` header to lift it. Retry with exponential backoff.

**Response `500`** — Unexpected server error. Safe to retry with backoff.

**Response `502`** — An upstream data source or protocol origin failed (`error.code` is `ORIGIN_FAILED`). `error.details` carries the per-origin status. This is also what a missing or malformed required parameter currently returns, rather than a 400.
