# Enumerate available lenders

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/lenders

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

Enumerate available lenders

Lightweight enumeration of every `(chainId, lenderKey)` pair that has data for the requested chains, sorted by `tvlUsd` descending.

Use this endpoint to discover the lender keys to page through [`GET /v1/data/lending/latest`](https://docs.1delta.io/1delta-api/lending-latest/), which is hard-capped at 20 lender keys per request.

```
GET /v1/data/lending/lenders?chains=1,8453            → enumerate keys
GET /v1/data/lending/latest?chains=1,8453&lenders=k1,…,k20    → page 1
GET /v1/data/lending/latest?chains=1,8453&lenders=k21,…,k40   → page 2
```

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `chains` | query | string[] | yes | Chain IDs to query (repeatable, CSV also accepted) |
| `lenders` | query | string[] | no | Filter by lender keys (repeatable, CSV also accepted). Defaults to all lenders. See the `LenderId` schema for the full set of accepted values. |
| `maxRiskScore` | query | integer | no | Max risk score (1–5). Defaults to 4. |
| `minTvl` | query | number | no | Filter out lender entries with `tvlUsd` below this USD threshold. Applied as a HAVING clause after aggregation. Returns 400 if non-numeric. |
| `count` | query | integer | no | Optional cap on the number of items returned. |

**Response `200`** — Available lenders sorted by TVL

| Field | Type | Description |
| --- | --- | --- |
| `success` | true |  |
| `data` | object | Enumeration of available (chainId, lenderKey) pairs sorted by tvlUsd descending. |
| `data.count` | integer | Number of items returned |
| `data.items` | object[] | Lender entries sorted by tvlUsd descending |
| `data.items[].chainId` | string | EVM chain id, as a decimal string. See the `ChainId` schema. |
| `data.items[].lenderInfo` | object | Protocol/lender metadata (name, logo). |
| `data.items[].lenderInfo.key` | string | Lender key identifier |
| `data.items[].lenderInfo.name` | string | Human-readable lender name |
| `data.items[].lenderInfo.logoURI` | string | Lender logo URL |
| `data.items[].tvlUsd` | number | Σ totalDepositsUsd − Σ totalDebtUsd over the lender's markets on this chain |
| `data.items[].lastFetched` | number | Epoch ms of latest snapshot |
| `data.items[].loop` | object | Which loop actions this lender can build, by which route — the lender → loopable list. Read this BEFORE rendering any loop CTA for the lender; a null here is a refusal the loop endpoints will repeat. |
| `data.items[].loop.family` | string | Which family row of the matrix answered (stable, lower-kebab): `aave-v2`, `aave-v3`, `aave-v4`, `compound-v3`, `compound-v2-venus`, `compound-v2`, `silo`, `fluid`, `gearbox-v3`, `euler-v2`, `init`, `dolomite`, `morpho-blue`, `lista-dao`, `midnight`, `exactly`, `llamalend`, `twyne`, `flying-tulip`, `curvance`, `fraxlend`, `resupply`, `term`, `teller`, `liquity-v2`, `river`, `inverse`, `cooler`, `dss`, `frankencoin`, `termmax`. |
| `data.items[].loop.open` | "composer" \| "bundler3" \| "native" \| "two-step" \| null | Route for `/v1/actions/loop/leverage`, or null. |
| `data.items[].loop.close` | "composer" \| "bundler3" \| "native" \| "two-step" \| null | Route for `/v1/actions/loop/close`, or null. |
| `data.items[].loop.collateralSwap` | "composer" \| "bundler3" \| "native" \| "two-step" \| null | Route for `/v1/actions/loop/collateral-swap`, or null. |
| `data.items[].loop.debtSwap` | "composer" \| "bundler3" \| "native" \| "two-step" \| null | Route for `/v1/actions/loop/debt-swap`, or null. |
| `data.items[].loop.marketGate` | string | A per-market descriptor field that must ALSO be true for a given market of this lender — see `MarketCapability.marketGate`. |
| `data.items[].loop.notes` | string | What a null is missing, or what a non-null route depends on — protocol facts, for the human reading the table. |
| `actions` | null |  |

**Example response**

```json
{
  "success": true,
  "data": {
    "count": 1,
    "items": [
      {
        "chainId": "1",
        "lenderInfo": {
          "key": "AAVE_V3",
          "name": "Aave V3",
          "logoURI": "https://raw.githubusercontent.com/1delta-DAO/protocol-icons/main/lender/aave_v3.webp"
        },
        "tvlUsd": 1234567890.12,
        "lastFetched": 1,
        "loop": {
          "family": "aave-v3",
          "open": "composer",
          "close": "composer",
          "collateralSwap": "composer",
          "debtSwap": "composer",
          "marketGate": "string",
          "notes": "string"
        }
      }
    ]
  }
}
```

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