API Documentation

Backend-for-Frontend (BFF) API for LendPilot - Lending market rates analytics

Overview

This API provides aggregated data from multiple sources (AaveKit GraphQL, The Graph Subgraph, Ethereum RPC) with caching, retry logic, and rate limiting. All endpoints return JSON responses unless otherwise specified.

Base URL: /api/v1

Rate Limits: 100 req/min (live data), 20 req/min (historical data)

Cache TTL: 30-60s (live), 6-24h (historical)

Markets

GET /markets

Returns list of all configured markets.

Response: {
  "markets": [
    {
      "marketKey": "ethereum-v3",
      "displayName": "Ethereum V3",
      "poolAddress": "0x...",
      "subgraphId": "...",
      "chainId": 1
    }
  ]
}

GET /market/{marketKey}

Returns current state of all assets in a market with totals.

Response: {
  "reserves": [
    {
      "underlyingAsset": "0x...",
      "symbol": "USDC",
      "name": "USD Coin",
      "decimals": 6,
      "imageUrl": "...",
      "currentState": {
        "supplyAPR": 0.05,
        "borrowAPR": 0.08,
        "totalSuppliedUSD": 1000000,
        "totalBorrowedUSD": 500000,
        "utilizationRate": 0.5
      }
    }
  ],
  "totals": {
    "totalSupply": 1000000000,
    "supply": 500000000,
    "borrowing": 500000000,
    "assetCount": 60
  }
}

GET /market/{marketKey}/timeseries?window=30d|6m|1y

Returns market totals time series data for the specified time window.

Response: {
  "marketKey": "ethereum-v3",
  "data": [
    {
      "date": "2025-01-01",
      "timestamp": 1735689600,
      "totalSuppliedUSD": 1000000000,
      "totalBorrowedUSD": 500000000,
      "availableLiquidityUSD": 500000000
    }
  ],
  "assetChanges": [...],
  "totals": {...}
}

Reserves

GET /reserve/{marketKey}/{underlying}

Returns current state and metadata for a specific asset.

GET /reserve/{marketKey}/{underlying}/snapshots/daily

Returns daily snapshots for the last 90 days.

GET /reserve/{marketKey}/{underlying}/snapshots/monthly

Returns monthly aggregated snapshots for the last 24 months.

GET /reserve/{marketKey}/{underlying}/snapshots/daily/csv

Returns daily snapshots as CSV file. Format: comma separator, UTF-8 encoding, ISO dates (YYYY-MM-DD).

GET /reserve/{marketKey}/{underlying}/liquidity-impact

Returns calculated liquidity impact scenarios for different transaction sizes.

Stablecoins

GET /stablecoins

Returns aggregated stablecoin data across all markets.

Calculation Formulas

APR Calculation (Index-Based)

Historical APR is calculated from liquidity and borrow indices using compound interest formula:

dailyGrowth = (indexEnd / indexStart)^(1/days)
APR = (dailyGrowth - 1) * 365

Where:
- indexStart: Index value at start of period
- indexEnd: Index value at end of period
- days: Number of days in period
- Indices are stored as Ray (1e27) values

This formula provides accurate historical APR based on actual index growth, not current rates.

Market Totals Calculation

Market-level totals are calculated by aggregating all reserves:

Total Supply = Σ(totalSuppliedUSD for all reserves)
Total Borrowing = Σ(totalBorrowedUSD for all reserves)
Available Supply = Total Supply - Total Borrowing

Where:
- totalSuppliedUSD = (totalATokenSupply / 10^decimals) * priceUSD
- totalBorrowedUSD = (totalCurrentVariableDebt / 10^decimals) * priceUSD
- priceUSD = usdExchangeRate * 1e8 (converted from AaveKit format)

Utilization Rate

Utilization rate indicates how much of available liquidity is borrowed:

utilizationRate = borrowed / (borrowed + availableLiquidity)

Where:
- borrowed: Total current variable debt
- availableLiquidity: Available liquidity for borrowing

Data Formats

Addresses

All addresses are normalized to lowercase and validated as Ethereum addresses (0x + 40 hex characters).

Dates

All dates are in ISO format (YYYY-MM-DD). Timestamps are Unix seconds (number).

Numbers

Large numbers (onchain values) are stored as strings to avoid precision loss. USD values are numbers with 2 decimal precision. APR values are numbers (0-1 range, e.g., 0.05 = 5%).

CSV Export

CSV files use comma separator, UTF-8 encoding, ISO date format (YYYY-MM-DD). USD values have 2 decimals, APR values have 4 decimals.

Error Responses

Standard Error Format

{
  "error": {
    "code": "ERROR_CODE",
    "message": "Human-readable error message",
    "details": "Optional additional details"
  }
}

Error Codes

  • INVALID_MARKET - Invalid market key
  • INVALID_ADDRESS - Invalid asset address
  • MARKET_NOT_FOUND - Market not found
  • RESERVE_NOT_FOUND - Asset not found in market
  • UPSTREAM_ERROR - External API error
  • RATE_LIMIT_EXCEEDED - Too many requests (429)
  • INTERNAL_ERROR - Server error (500)

Usage Examples

Fetch Market Data

fetch('/api/v1/market/ethereum-v3')
  .then(res => res.json())
  .then(data => {
    console.log('Total Supply:', data.totals.totalSupply);
    console.log('Reserves:', data.reserves);
  });

Fetch Asset Snapshots

const address = '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48';
fetch(`/api/v1/reserve/ethereum-v3/${address}/snapshots/daily`)
  .then(res => res.json())
  .then(snapshots => {
    console.log('Daily snapshots:', snapshots);
  });

Download CSV

// Trigger CSV download
window.location.href = 
  '/api/v1/reserve/ethereum-v3/0x.../snapshots/daily/csv';

Additional Resources