# The unified earn listing

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

- operationId: `the-unified-earn-listing`
- docs: https://docs.1delta.io/1delta-api/the-unified-earn-listing/
- markdown: https://docs.1delta.io/1delta-api/the-unified-earn-listing.md
- tags: Earn

The unified earn listing

Lending supply sides and vaults as ONE paginated row shape (`EarnMarket`), every rate in PERCENT (`rateUnit: "percent"`). Served from the origin's `/earn/latest` when it can answer, else from an edge merge of `/pools/latest` + `/vaults/latest`; the shape is identical either way and a failing source is reported in `sources[]`.

## Issuer fields on `asset`
- `asset.issuer` `{id,name,kind?}` — whose INSTRUMENT the deposit token is.
- `asset.issuerExposures` `[{id,name,kind?,hops}]` — whose credit a wrapper leaves you holding; absent on a spot token.
- `asset.desk` — the credit desk (`CreditDesk`), `null` when the token names no issuer (WETH).
- `asset.denomination` — the MONEY the token is worth, uppercase (`USD`, `EUR`, `ETH`, `BTC`, …): `props.stablecoin.base`, else `props.savings.base`, else `props.lst.asset` (an LST/LRT — wstETH, weETH, LBTC), else `props.denomination` (WETH → `ETH`, WBTC → `BTC`), else — for a PT or other wrapper, or a native token — its underlying's / wrapped twin's; `null` when none. `props.stablecoin` is believed only when the token names an issuer (or exposure) or its asset group / `chainId-address` is in token-lists' identity-keyed stablecoin snapshot (`scripts/stablecoin/stablecoin.json`): the lists also stamp it by bare ticker, which tags non-dollars as `USD`. Not `risk.denomination`, which is `stable`/`volatile`.

All four are stamped from the token map by chainId + address on BOTH serving paths. `null` means "resolved: none"; an absent field means the token map was unavailable for that chain.

A token's **credit desk** (see `CreditDesk`) is the token's own `issuer`, unless that issuer is a pure instrument wrapper (Pendle, Spectra, Exponent, or any token carrying a `pendle`/`spectra`/`exponent`/`receipt` prop) — then its fewest-hop non-instrument `issuerExposures` entry, with the instrument issuer as `via`. A PT-sUSDe is `{ id: 'ethena', via: 'pendle', hops: 1 }` — Pendle's instrument, Ethena's credit; Strata's srUSDe is `{ id: 'strata', hops: 0 }` — its own issuer's token, even though it is exposed to Ethena. An instrument issuer is never a desk.

**Two things are deliberately NOT a desk:**
- **A loop's debt.** A stablecoin you owe is not an exposure to its issuer: a USDC-funded sUSDe loop is Ethena credit, not Circle credit. Strategies group by their COLLATERAL's desk.
- **A vault's `exposure` block.** That is the curator's current allocation (one Fluid USDC vault spans eight collaterals and six desks), a DISCLOSURE about the position that moves on every rebalance. A vault row's desk is its deposit token's (`asset.desk`): a Steakhouse USDC vault is on Circle's desk.

## `issuers` and `issuerMatch`
`issuers=sky,ethena` keeps rows whose deposit token answers to one of the ids under `issuerMatch`: `any` (default — own issuer or any exposure leg), `direct`, `exposure`, or `credit` (exactly `asset.desk`; the one mode under which `issuers` PARTITIONS the listing). On the origin path `any`/`exposure` ALSO match a vault through its allocation (`exposure.legs`). On the edge merge only the deposit token's desks are known, so the response then carries `issuerScope: "deposit-token"`. `credit` is always answered by the edge merge (it filters the whole catalogue, then pages).

## Asset class (`asset.assetClass`, `asset.underlyingTicker`)
- `asset.assetClass` — WHAT KIND of real-world asset the deposit token is: `stock` · `etf` · `pre-ipo` · `fund` · `credit` · `commodity`, read verbatim off token-lists `props.rwa` (`type` + `subType`: equity/stock → `stock`, equity/pre-ipo → `pre-ipo`, fund/etf → `etf`, other funds → `fund`, credit → `credit`, commodity → `commodity`). Never guessed from a ticker. `null` = not a tokenized real-world asset (crypto); absent = the token map was unavailable for that chain.
- `asset.underlyingTicker` — the real-world instrument a tokenized equity / ETF tracks, upper-cased (`TSLA` on TSLAx, TSLAon and Dinari's TSLA alike); `null` on every other class.

`assetClasses=stocks` keeps rows whose deposit token is of one of the classes; aliases `stocks` = `equity` = stock + etf + pre-ipo, `rwa` = every class. `underlyingTickers=TSLA,NVDA` keeps rows whose `asset.underlyingTicker` is one of them. Both together AND. A token with no class never matches. Forwarded to the origin; an origin that does not apply them is detected on the page and the request is answered by the edge merge instead. An unknown class or a malformed ticker is a 400 naming the valid values.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `chainIds` | query | string | yes | CSV of chain ids (alias `chainId`). See the `ChainId` schema for the full set of supported chains. |
| `issuers` | query | string | no | CSV of issuer ids (alias `issuer`) — WHOSE CREDIT the deposit asset is, not the money it is worth and not the venue or curator hosting it. |
| `issuerMatch` | query | "any" \| "direct" \| "exposure" \| "credit" | no | Which desk `issuers` matches — see the description. `credit` = exactly `asset.desk`. |
| `assetClasses` | query | string | no | CSV of asset classes — `stock`, `etf`, `pre-ipo`, `fund`, `credit`, `commodity` — or the aliases `stocks` / `equity` (stock + etf + pre-ipo) and `rwa` (all). Matches `asset.assetClass`; an unknown value is a 400. |
| `underlyingTickers` | query | string | no | CSV of real-world tickers a tokenized equity / ETF tracks (`asset.underlyingTicker`, case-insensitive). ANDed with `assetClasses`. |
| `venueKind` | query | "lending" \| "vault" | no | `lending` or `vault`. |
| `assetGroup` | query | string | no | Exact asset group of the deposit token. |
| `shareGroup` | query | string | no | Exact asset group of the SHARE token a vault mints (`shareToken.assetGroup`): the vaults that leave you holding that token, e.g. Nest's savings vault for nOPAL. Vault rows only. |
| `assetSymbol` | query | string | no | Exact symbol of the deposit token. |
| `denomination` | query | string | no | Filters `risk.denomination` (`stable` / `volatile`) — NOT `asset.denomination`. |
| `q` | query | string | no | Free-text search across names, brands, symbols and addresses. |
| `sort` | query | "rate" \| "marketRate" \| "tvl" \| "liquidity" | no | Sort key, descending. |
| `start` | query | integer | no | Page offset. |
| `limit` | query | integer | no | Page size, 1–1000 (alias `count`). |
| `terms` | query | "none" \| "digest" \| "full" | no | Term-sheet depth on each row. A row whose floating yield IS perp funding (sUSDe, stUSR, wstUSR) also gets `termSheet.hedge`: the Pendle Boros fixed-rate lock for that funding (SHORT YU on Arbitrum), priced per unit of notional at a $10k reference — see `TermFundingHedge`. Never on a principal token or a fixed-maturity row. |
| `maxRiskScore` | query | integer | no | Risk ceiling on `risk.score` (1–5; 6 = compromised — drained / insolvent / abandoned). Defaults to 5, so a 6 is only returned when set to 6 explicitly. A row with no score is kept. A market inherits the risk of its config: on a pooled or cross-margin lender every collateral in the config counts, so one high-risk collateral (e.g. an oracle that has not moved in a week) raises every market borrowable there. |
| `minTvlUsd` | query | number | no | TVL floor in USD. `0` = no floor. An unpriced row (no TVL) is kept. |
| `minLiquidityUsd` | query | number | no | Withdrawable-liquidity floor in USD. |
| `depositable` | query | "true" | no | Only rows that accept deposits right now (`availability.canDeposit`). Off by default. |
| `passthrough` | query | "include" | no | Include PASSTHROUGH rows, hidden by default: a market whose quoted rate is only the deposit token's own yield (an LST pool paying 0 % of its own). `excluded.passthrough` counts what the default hid. |
| `illiquid` | query | "include" | no | Include rows flagged `risk.illiquid`, hidden by default. |
| `lp` | query | "include" | no | Include rows whose position is a multi-token LP (the asset column names one leg only), hidden by default. |
| `includeExpired` | query | "true" \| "false" | no | Include matured fixed-maturity rows (e.g. an expired PT), hidden by default. |
| `protocol` | query | string | no | CSV of protocol names or keys (`protocol.name` / `protocol.key`; alias `protocols`). |
| `venue` | query | string | no | CSV of venues, matched on `venue` (alias `venues`). |
| `brand` | query | string | no | CSV of brands, matched on `brand` (alias `brands`). |
| `curator` | query | string | no | CSV of curator names, matched on `curator.name` (alias `curators`). |
| `yieldProfile` | query | string | no | Exact `risk.yieldProfile` (e.g. `yield-bearing`, `volatile`). |
| `includeFixedTerm` | query | "true" \| "false" | no | Show FIXED-YIELD order-book / auction rows: Morpho Midnight, Term Finance, TermMax, Loopscale, Jupiter Offerbook. Hidden by default because they are not pools — the rate is the best executable quote for ONE maturity (on Midnight, the cheapest borrower ask), `rate.kind` is `fixed-term`, and the size is that book's depth. `excluded.fixedTerm` counts what the default hid. Midnight collateral legs are never listed (`excluded.collateralLeg`). |

**Response `200`** — The earn envelope: `items` (EarnMarket rows, with `asset.issuer` / `issuerExposures` / `desk` / `denomination` / `assetClass` / `underlyingTicker`), `total`, `sources`, `excluded`, `appliedDefaults`, `facets`, and `issuerScope` when the issuer filter was answered over deposit-token desks only.

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

**Response `503`** — `FILTER_UNAVAILABLE` — `issuers` (or `assetClasses` / `underlyingTickers`) was asked, the origin could not answer, and the token map for a requested chain could not be loaded, so the edge merge cannot answer either.
