Skip to main content
This guide covers every endpoint in the Earn Data API with full parameter documentation and response examples. The Earn Data API handles vault discovery, analytics, and portfolio tracking. For executing deposits and withdrawals, see the Composer API Integration Guide.

Base URL

https://earn.li.fi
All endpoints are prefixed with /v1/earn/.
The Earn Data API and Composer use different base URLs. Earn Data API endpoints use https://earn.li.fi, while Composer endpoints (e.g., GET /v1/quote) use https://li.quest. See the overview for details.

API Overview

EndpointDescription
GET /v1/earn/vaultsList vaults with filtering and pagination
GET /v1/earn/vaults/:chainId/:addressGet a single vault’s full details
GET /v1/earn/chainsList chains with active vaults
GET /v1/earn/protocolsList protocols with active vaults
GET /v1/earn/portfolio/:userAddress/positionsGet a user’s DeFi positions

Authentication

The Earn Data API uses the same authentication as the rest of the LI.FI API. Pass your API key via the x-lifi-api-key header:
curl -X GET 'https://earn.li.fi/v1/earn/vaults' \
  --header 'x-lifi-api-key: YOUR_API_KEY'
API keys are created via the LI.FI Partner Portal. See Authentication for full details.

Rate Limits

The default rate limit for Earn Data API endpoints is 50 requests per minute per API key. If you need higher limits, contact our team via the LI.FI Partner Portal. If you exceed the limit, you’ll receive a 429 Too Many Requests response. See Rate Limits for details on rate limit headers and best practices.

List Vaults

GET /v1/earn/vaults
Returns a paginated list of vaults with optional filtering and sorting.

Query Parameters

ParameterTypeRequiredDefaultDescription
chainIdintegerNoFilter by EVM chain ID (e.g., 8453 for Base, 1 for Ethereum)
assetstringNoFilter by underlying token symbol (e.g., "USDC", "ETH")
protocolstringNoFilter by protocol name (e.g., "morpho-v1", "aave-v3")
minTvlUsdnumberNoMinimum TVL in USD (e.g., 1000000 for $1M+)
sortBystringNoSort order: "apy" (highest first) or "tvl" (highest first)
limitintegerNo50Results per page (1–100)
cursorstringNoPagination cursor from a previous response’s nextCursor

Example Request

curl -X GET 'https://earn.li.fi/v1/earn/vaults?\
chainId=8453&\
asset=USDC&\
sortBy=apy&\
minTvlUsd=100000&\
limit=10'

Response

{
  "data": [
    {
      "address": "0x7BfA7C4f149E7415b73bdeDfe609237e29CBF34A",
      "network": "base",
      "chainId": 8453,
      "slug": "morpho-base-usdc-0x7bfa",
      "name": "Morpho USDC Vault",
      "description": "Optimized USDC lending vault on Morpho",
      "protocol": {
        "name": "Morpho",
        "logoUri": "https://example.com/morpho-logo.png",
        "url": "https://morpho.org"
      },
      "underlyingTokens": [
        {
          "address": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
          "symbol": "USDC",
          "decimals": 6,
          "weight": 1.0
        }
      ],
      "lpTokens": [
        {
          "address": "0x7BfA7C4f149E7415b73bdeDfe609237e29CBF34A",
          "symbol": "mUSDC",
          "decimals": 18,
          "priceUsd": "1.02"
        }
      ],
      "rewardTokens": [],
      "tags": ["stablecoin", "lending"],
      "analytics": {
        "apy": {
          "base": 0.0534,
          "reward": null,
          "total": 0.0534
        },
        "apy1d": 0.0521,
        "apy7d": 0.0538,
        "apy30d": 0.0545,
        "tvl": {
          "usd": "12500000.00",
          "native": "12500000000000"
        },
        "updatedAt": "2026-03-31T14:30:00.000Z"
      },
      "caps": {
        "totalCap": "50000000000000",
        "maxCap": "100000000000000"
      },
      "timeLock": 0,
      "kyc": false,
      "isTransactional": true,
      "isRedeemable": true,
      "depositPacks": [
        { "name": "morpho-deposit", "stepsType": "instant" }
      ],
      "redeemPacks": [
        { "name": "morpho-redeem", "stepsType": "instant" }
      ],
      "syncedAt": "2026-03-31T14:30:00.000Z"
    }
  ],
  "nextCursor": "eyJpZCI6MTAwfQ",
  "total": 47
}
Some fields may be null in the response: description (absent for ~70% of vaults), apy.base, apy.reward, apy1d, apy7d, and caps. Always handle nullable fields in your integration.

Pagination

The API uses cursor-based pagination. To fetch the next page, pass the nextCursor value from the response as the cursor query parameter:
TypeScript
// Fetch all vaults across pages
let cursor: string | undefined;
const allVaults = [];

do {
  const params = new URLSearchParams({ limit: '100' });
  if (cursor) params.set('cursor', cursor);

  const response = await fetch(`https://earn.li.fi/v1/earn/vaults?${params}`);
  const { data, nextCursor } = await response.json();

  allVaults.push(...data);
  cursor = nextCursor;
} while (cursor);

Get Vault by Chain and Address

GET /v1/earn/vaults/:chainId/:address
Returns the full details for a single vault.

Path Parameters

ParameterTypeRequiredDescription
chainIdintegerYesEVM chain ID
addressstringYesVault contract address (0x-prefixed, 40 hex characters)

Example Request

curl -X GET 'https://earn.li.fi/v1/earn/vaults/8453/0x7BfA7C4f149E7415b73bdeDfe609237e29CBF34A'

Response

Returns a single NormalizedVault object (same shape as items in the list endpoint).

Errors

StatusDescription
400Invalid chain ID or address format
404Vault not found

List Supported Chains

GET /v1/earn/chains
Returns the list of chains that have at least one vault available. Derived from current vault data.

Example Request

curl -X GET 'https://earn.li.fi/v1/earn/chains'

Response

[
  {
    "name": "Ethereum",
    "chainId": 1,
    "networkCaip": "eip155:1"
  },
  {
    "name": "Base",
    "chainId": 8453,
    "networkCaip": "eip155:8453"
  },
  {
    "name": "Arbitrum One",
    "chainId": 42161,
    "networkCaip": "eip155:42161"
  }
]

List Supported Protocols

GET /v1/earn/protocols
Returns the list of protocols that have at least one vault available. Derived from current vault data.

Example Request

curl -X GET 'https://earn.li.fi/v1/earn/protocols'

Response

[
  {
    "name": "Morpho",
    "logoUri": "https://example.com/morpho-logo.png",
    "url": "https://morpho.org"
  },
  {
    "name": "Aave V3",
    "logoUri": "https://example.com/aave-logo.png",
    "url": "https://aave.com"
  },
  {
    "name": "Euler",
    "logoUri": "https://example.com/euler-logo.png",
    "url": "https://www.euler.finance"
  }
]

Get User Portfolio Positions

GET /v1/earn/portfolio/:userAddress/positions
Returns a user’s DeFi positions across all supported protocols.

Path Parameters

ParameterTypeRequiredDescription
userAddressstringYesUser’s wallet address (0x-prefixed, 40 hex characters)

Example Request

curl -X GET 'https://earn.li.fi/v1/earn/portfolio/0x1234567890abcdef1234567890abcdef12345678/positions'

Response

{
  "positions": [
    {
      "chainId": 1,
      "protocolName": "aave-v3",
      "asset": {
        "address": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
        "name": "USD Coin",
        "symbol": "USDC",
        "decimals": 6
      },
      "balanceUsd": "1523.45",
      "balanceNative": "1523450000"
    },
    {
      "chainId": 8453,
      "protocolName": "morpho",
      "asset": {
        "address": "0x7BfA7C4f149E7415b73bdeDfe609237e29CBF34A",
        "name": "Morpho USDC Vault",
        "symbol": "mUSDC",
        "decimals": 18
      },
      "balanceUsd": "5000.00",
      "balanceNative": "4901960784313725490196"
    }
  ]
}

Errors

StatusDescription
400Invalid wallet address format

Error Handling

All Earn Data API endpoints return standard HTTP error responses:
StatusMeaning
200Success
400Bad request. Invalid parameters (check the error message for details).
404Resource not found (vault does not exist)
500Internal server error
Error responses include a message describing the issue:
{
  "statusCode": 400,
  "message": "Invalid Ethereum address"
}

Next Steps

Discover and Deposit Recipe

End-to-end recipe combining Earn discovery with Composer deposits

Composer API Guide

Execute deposits and withdrawals via the Composer API