Desk facet: money → credit desk → strategies
GET/v1/data/earn/desks
One entry per (credit desk, denomination): the tokens that put you on that desk, what DEPOSITING them pays, and what LOOPING them pays. Built from the same data as /v1/data/earn (its cached catalogue, with its default exclusions — deposit.count is what a bare listing request shows) and /v1/data/lending/pairs/optimize (at its defaults). Cached 5 min, served stale while refreshing.
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.
Deposit rows are bucketed by their deposit token's desk; loop rows by their COLLATERAL's desk. A loop counts in a money only when its collateral AND its debt are that money (wstETH/WETH is an ether loop, sUSDe/USDC a dollar loop); a cross-money loop (sUSDe/WETH) is a price bet and appears in no entry.
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
exposureblock. 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.
Tokens with no desk are reported rather than dropped: plain ETH / WETH (nobody's liability) under { id: 'plain:ETH', name: 'Ether', kind: 'plain' }; every other one under { id: 'sym:<SYMBOL>', name: <symbol>, kind: 'unattributed' } — a curation gap, not an issuer (there is no plain BTC: every BTC token is someone's IOU).
[{ "desk": { "id": "ethena", "name": "Ethena", "kind": "protocol" },
"denomination": "USD",
"members": [{ "assetGroup": "USDE", "symbol": "USDe", "role": "base" },
{ "assetGroup": "SUSDE", "symbol": "sUSDe", "role": "savings" },
{ "assetGroup": "Ethereum::PT-sUSDE-…", "symbol": "PT-sUSDE-…", "role": "pt", "via": "pendle" }],
"deposit": { "count": 19, "maxApr": 11.2, "tvlUsd": 4.1e9 },
"loop": { "count": 55, "maxNetApr": 33.1, "maxLeverage": 17.6 } }]
members[].role:base(the desk's own money),savings(its yield-bearing wrapper),pt(a principal token over it),wrapper(any other wrapper).vianames the instrument issuer when it is not the desk.deposit.maxAprandloop.maxNetAprare PERCENT (the units ofrate.totalandaprTotal);nullwhen the count is 0.loop.maxNetApris the bestaprTotal(net, at max leverage, incl. rewards).partial: trueondeposit/loopwhen a source was unavailable or a walk hit its cap — the figures are then a lower bound.- Sorted by
deposit.tvlUsd, thenloop.count.
Plain-text reference — GET /v1/data/earn/desks
Parameters
| Parameter | 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. |
denomination | query | string | no | Money to keep, uppercase-insensitive: USD, EUR, ETH, BTC, … (ETH groups LSTs/LRTs by their desk — Lido, ether.fi, Rocket Pool, Coinbase, …; BTC likewise — BitGo, Coinbase, Lombard, …). Omit for every denomination (deposit tokens with none are then reported with denomination: null). |
Response 200
| Field | Type | Description |
|---|---|---|
success | True | |
data | object | Informational payload. null when the endpoint only builds calldata. |
actions | null |
Example response
{
"success": true,
"data": {}
}
Request
Responses
- 200
- 400
- 429
- 500
- 502
Array of { desk: {id,name,kind?}, denomination, members: [{assetGroup,symbol,role,via?}], deposit: {count,maxApr,tvlUsd,partial?}, loop: {count,maxNetApr,maxLeverage,partial?} }.
Validation error
Rate limited. Unauthenticated callers share a per-IP budget; send an x-api-key header to lift it. Retry with exponential backoff.
Unexpected server error. Safe to retry with backoff.
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.