> ## Documentation Index
> Fetch the complete documentation index at: https://docs.li.fi/llms.txt
> Use this file to discover all available pages before exploring further.

# API Integration

> Full reference for the LI.FI Earn Data API. Covers all endpoints, query parameters, response schemas, pagination, and error handling.

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](/composer/guides/api-integration).

***

## Base URL

```
https://earn.li.fi
```

All endpoints are prefixed with `/v1/`.

<Note>
  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](/earn/overview#the-two-layers) for details.
</Note>

***

## API Overview

| Endpoint                                   | Description                               |
| ------------------------------------------ | ----------------------------------------- |
| `GET /v1/vaults`                           | List vaults with filtering and pagination |
| `GET /v1/vaults/:chainId/:address`         | Get a single vault's full details         |
| `GET /v1/chains`                           | List chains with active vaults            |
| `GET /v1/protocols`                        | List protocols with active vaults         |
| `GET /v1/portfolio/:userAddress/positions` | Get 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:

```bash theme={"system"}
curl -X GET 'https://earn.li.fi/v1/vaults' \
  --header 'x-lifi-api-key: YOUR_API_KEY'
```

API keys are created via the [LI.FI Partner Portal](https://li.fi/plans/). See [Authentication](/api-reference/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](https://li.fi/plans/).

If you exceed the limit, you'll receive a `429 Too Many Requests` response. See [Rate Limits](/api-reference/rate-limits) for details on rate limit headers and best practices.

***

## List Vaults

```
GET /v1/vaults
```

Returns a paginated list of vaults with optional filtering and sorting.

### Query Parameters

| Parameter             | Type      | Required | Default | Description                                                                                                        |
| --------------------- | --------- | -------- | ------- | ------------------------------------------------------------------------------------------------------------------ |
| `chainId`             | `integer` | No       | —       | Filter by EVM chain ID (e.g., `8453` for Base, `1` for Ethereum)                                                   |
| `asset`               | `string`  | No       | —       | Filter by underlying token symbol (e.g., `"USDC"`, `"ETH"`)                                                        |
| `protocol`            | `string`  | No       | —       | Filter by protocol name (e.g., `"morpho-v1"`, `"aave-v3"`)                                                         |
| `minTvlUsd`           | `number`  | No       | —       | Minimum TVL in USD (e.g., `1000000` for \$1M+)                                                                     |
| `isTransactional`     | `boolean` | No       | —       | Pass `"true"` to return only vaults that support programmatic deposits and withdrawals via Composer                |
| `isRedeemable`        | `boolean` | No       | —       | Pass `"true"` to return only vaults that currently support withdrawals                                             |
| `isComposerSupported` | `boolean` | No       | —       | Pass `"true"` to return only vaults fully supported by the LI.FI Composer for end-to-end cross-chain deposit flows |
| `sortBy`              | `string`  | No       | —       | Sort order: `"apy"` (highest first) or `"tvl"` (highest first)                                                     |
| `limit`               | `integer` | No       | `50`    | Results per page (1–100)                                                                                           |
| `cursor`              | `string`  | No       | —       | Pagination cursor from a previous response's `nextCursor`                                                          |

### Example Request

<CodeGroup>
  ```bash curl theme={"system"}
  curl -X GET 'https://earn.li.fi/v1/vaults?chainId=8453&asset=USDC&sortBy=apy&minTvlUsd=100000&limit=10'
  ```

  ```ts TypeScript theme={"system"}
  const params = new URLSearchParams({
    chainId: '8453',
    asset: 'USDC',
    sortBy: 'apy',
    minTvlUsd: '100000',
    limit: '10',
  });

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

### Response

```json theme={"system"}
{
  "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
}
```

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

### Pagination

The API uses cursor-based pagination. To fetch the next page, pass the `nextCursor` value from the response as the `cursor` query parameter:

```ts TypeScript theme={"system"}
// 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/vaults?${params}`);
  const { data, nextCursor } = await response.json();

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

***

## Get Vault by Chain and Address

```
GET /v1/vaults/:chainId/:address
```

Returns the full details for a single vault.

### Path Parameters

| Parameter | Type      | Required | Description                                             |
| --------- | --------- | -------- | ------------------------------------------------------- |
| `chainId` | `integer` | Yes      | EVM chain ID                                            |
| `address` | `string`  | Yes      | Vault contract address (0x-prefixed, 40 hex characters) |

### Example Request

<CodeGroup>
  ```bash curl theme={"system"}
  curl -X GET 'https://earn.li.fi/v1/vaults/8453/0x7BfA7C4f149E7415b73bdeDfe609237e29CBF34A'
  ```

  ```ts TypeScript theme={"system"}
  const chainId = 8453;
  const address = '0x7BfA7C4f149E7415b73bdeDfe609237e29CBF34A';

  const response = await fetch(`https://earn.li.fi/v1/vaults/${chainId}/${address}`);
  const vault = await response.json();
  ```
</CodeGroup>

### Response

Returns a single [NormalizedVault](/earn/how-it-works#the-normalizedvault-schema) object (same shape as items in the list endpoint).

### Errors

| Status | Description                        |
| ------ | ---------------------------------- |
| `400`  | Invalid chain ID or address format |
| `404`  | Vault not found                    |

***

## List Earn-Supported Chains

```
GET /v1/chains
```

Returns the list of chains that have at least one Earn vault available. Derived from current vault data.

<Note>
  **Scoped to LI.FI Earn.** This endpoint only returns chains where Earn currently has indexed vaults — it is not a general list of all chains the LI.FI platform supports. If you are integrating **Swaps or Bridges** (via the LI.FI SDK or the main API), use [`GET https://li.quest/v1/chains`](/api-reference/get-information-about-all-currently-supported-chains) instead.
</Note>

### Example Request

<CodeGroup>
  ```bash curl theme={"system"}
  curl -X GET 'https://earn.li.fi/v1/chains'
  ```

  ```ts TypeScript theme={"system"}
  const response = await fetch('https://earn.li.fi/v1/chains');
  const chains = await response.json();
  ```
</CodeGroup>

### Response

```json theme={"system"}
[
  {
    "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/protocols
```

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

### Example Request

<CodeGroup>
  ```bash curl theme={"system"}
  curl -X GET 'https://earn.li.fi/v1/protocols'
  ```

  ```ts TypeScript theme={"system"}
  const response = await fetch('https://earn.li.fi/v1/protocols');
  const protocols = await response.json();
  ```
</CodeGroup>

### Response

```json theme={"system"}
[
  {
    "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/portfolio/:userAddress/positions
```

Returns a user's DeFi positions across all supported protocols.

### Path Parameters

| Parameter     | Type     | Required | Description                                            |
| ------------- | -------- | -------- | ------------------------------------------------------ |
| `userAddress` | `string` | Yes      | User's wallet address (0x-prefixed, 40 hex characters) |

### Example Request

<CodeGroup>
  ```bash curl theme={"system"}
  curl -X GET 'https://earn.li.fi/v1/portfolio/0x1234567890abcdef1234567890abcdef12345678/positions'
  ```

  ```ts TypeScript theme={"system"}
  const userAddress = '0x1234567890abcdef1234567890abcdef12345678';

  const response = await fetch(
    `https://earn.li.fi/v1/portfolio/${userAddress}/positions`
  );
  const { positions } = await response.json();
  ```
</CodeGroup>

### Response

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

<Note>
  The `address`, `protocolName`, and `balanceUsd` fields on each position can be `null`. `address` is null when a contract address cannot be determined for the position. `protocolName` is null when the protocol cannot be identified. `balanceUsd` is null when a USD price is unavailable for the asset. Always handle these cases in your integration.
</Note>

### Errors

| Status | Description                   |
| ------ | ----------------------------- |
| `400`  | Invalid wallet address format |

***

## Error Handling

All Earn Data API endpoints return standard HTTP error responses:

| Status | Meaning                                                                |
| ------ | ---------------------------------------------------------------------- |
| `200`  | Success                                                                |
| `400`  | Bad request. Invalid parameters (check the error message for details). |
| `404`  | Resource not found (vault does not exist)                              |
| `500`  | Internal server error                                                  |

Error responses include a message describing the issue:

```json theme={"system"}
{
  "statusCode": 400,
  "message": "Invalid Ethereum address"
}
```

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Discover and Deposit Recipe" icon="book" href="/earn/recipes/discover-and-deposit">
    End-to-end recipe combining Earn discovery with Composer deposits
  </Card>

  <Card title="Composer API Guide" icon="code" href="/composer/guides/api-integration">
    Execute deposits and withdrawals via the Composer API
  </Card>
</CardGroup>
