Skip to main content
POST
/
rpc
/
Trails
/
GetEarnPools
GetEarnPools returns aggregated pool information from DeFi protocols (Aave, Morpho).
curl --request POST \
  --url https://trails-api.sequence.app/rpc/Trails/GetEarnPools \
  --header 'Content-Type: application/json' \
  --data '
{
  "chainIds": [
    123
  ],
  "protocols": [
    "<string>"
  ],
  "minTvl": 123,
  "maxApy": 123
}
'
import requests

url = "https://trails-api.sequence.app/rpc/Trails/GetEarnPools"

payload = {
"chainIds": [123],
"protocols": ["<string>"],
"minTvl": 123,
"maxApy": 123
}
headers = {"Content-Type": "application/json"}

response = requests.post(url, json=payload, headers=headers)

print(response.text)
const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({chainIds: [123], protocols: ['<string>'], minTvl: 123, maxApy: 123})
};

fetch('https://trails-api.sequence.app/rpc/Trails/GetEarnPools', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));
<?php

$curl = curl_init();

curl_setopt_array($curl, [
CURLOPT_URL => "https://trails-api.sequence.app/rpc/Trails/GetEarnPools",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'chainIds' => [
123
],
'protocols' => [
'<string>'
],
'minTvl' => 123,
'maxApy' => 123
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
package main

import (
"fmt"
"strings"
"net/http"
"io"
)

func main() {

url := "https://trails-api.sequence.app/rpc/Trails/GetEarnPools"

payload := strings.NewReader("{\n \"chainIds\": [\n 123\n ],\n \"protocols\": [\n \"<string>\"\n ],\n \"minTvl\": 123,\n \"maxApy\": 123\n}")

req, _ := http.NewRequest("POST", url, payload)

req.Header.Add("Content-Type", "application/json")

res, _ := http.DefaultClient.Do(req)

defer res.Body.Close()
body, _ := io.ReadAll(res.Body)

fmt.Println(string(body))

}
HttpResponse<String> response = Unirest.post("https://trails-api.sequence.app/rpc/Trails/GetEarnPools")
.header("Content-Type", "application/json")
.body("{\n \"chainIds\": [\n 123\n ],\n \"protocols\": [\n \"<string>\"\n ],\n \"minTvl\": 123,\n \"maxApy\": 123\n}")
.asString();
require 'uri'
require 'net/http'

url = URI("https://trails-api.sequence.app/rpc/Trails/GetEarnPools")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"chainIds\": [\n 123\n ],\n \"protocols\": [\n \"<string>\"\n ],\n \"minTvl\": 123,\n \"maxApy\": 123\n}"

response = http.request(request)
puts response.read_body
{
  "pools": [
    {
      "id": "<string>",
      "name": "<string>",
      "protocol": "<string>",
      "chainId": 123,
      "apy": 123,
      "tvl": 123,
      "token": {
        "symbol": "<string>",
        "name": "<string>",
        "address": "<string>",
        "decimals": 123,
        "logoUrl": "<string>"
      },
      "depositAddress": "<string>",
      "isActive": true,
      "poolUrl": "<string>",
      "protocolUrl": "<string>",
      "wrappedTokenGatewayAddress": "<string>"
    }
  ],
  "timestamp": "<string>",
  "cached": true
}
{
"error": "WebrpcEndpoint",
"code": 0,
"msg": "endpoint error",
"status": 400,
"cause": "<string>"
}
{
"error": "WebrpcBadResponse",
"code": -5,
"msg": "bad response",
"status": 500,
"cause": "<string>"
}
GetEarnPools is deprecated. Use YieldGetMarkets instead — it provides richer market data, filtering, and pagination.

Overview

The GetEarnPools endpoint returns aggregated yield-bearing pool information from supported DeFi protocols such as Aave and Morpho. Use this to display earning opportunities to users and build Earn mode integrations.

Use Cases

  • Display yield pools with APY and TVL in your UI
  • Filter pools by chain or protocol
  • Power the Trails Earn mode with live pool data
  • Show users the best yield opportunities across chains

Request Parameters

All fields are optional.
  • chainIds (number[]): Filter pools to specific chain IDs
  • protocols (string[]): Filter by protocol name (e.g. "aave", "morpho")
  • minTvl (number): Minimum total value locked (USD) filter
  • maxApy (number): Maximum APY filter

Response

  • pools (EarnPool[]): Array of yield pool objects
  • timestamp (string): ISO timestamp of when this data was fetched
  • cached (boolean): Whether the response is from cache

EarnPool Object Structure

Each pool includes:
  • id (string): Unique pool identifier
  • name (string): Human-readable pool name
  • protocol (string): Protocol name (e.g. "aave", "morpho")
  • chainId (number): Chain the pool is deployed on
  • apy (number): Current annual percentage yield
  • tvl (number): Total value locked in USD
  • token (PoolTokenInfo): Deposit token details (symbol, name, address, decimals)
  • depositAddress (string): Contract address to deposit to
  • isActive (boolean): Whether the pool is currently accepting deposits
  • poolUrl (string, optional): URL to the pool on the protocol’s UI
  • protocolUrl (string, optional): URL to the protocol’s website
  • wrappedTokenGatewayAddress (string, optional): Gateway address for native token deposits

Examples

Get All Earn Pools

const response = await fetch('https://trails-api.sequence.app/rpc/Trails/GetEarnPools', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-Access-Key': 'YOUR_ACCESS_KEY'
  },
  body: JSON.stringify({})
});

const { pools, timestamp, cached } = await response.json();

console.log(`Fetched ${pools.length} pools (cached: ${cached})`);
pools.forEach(pool => {
  console.log(`${pool.name} on chain ${pool.chainId}: ${pool.apy.toFixed(2)}% APY, $${pool.tvl.toLocaleString()} TVL`);
});

Filter by Chain and Protocol

const response = await fetch('https://trails-api.sequence.app/rpc/Trails/GetEarnPools', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-Access-Key': 'YOUR_ACCESS_KEY'
  },
  body: JSON.stringify({
    chainIds: [8453], // Base only
    protocols: ['aave'],
    minTvl: 1000000 // At least $1M TVL
  })
});

const { pools } = await response.json();

Build an Earn Pool List UI

import { useEffect, useState } from 'react';

interface EarnPool {
  id: string;
  name: string;
  protocol: string;
  chainId: number;
  apy: number;
  tvl: number;
  token: { symbol: string; address: string };
  depositAddress: string;
  isActive: boolean;
}

export const EarnPoolList = ({ chainId }: { chainId?: number }) => {
  const [pools, setPools] = useState<EarnPool[]>([]);

  useEffect(() => {
    fetch('https://trails-api.sequence.app/rpc/Trails/GetEarnPools', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'X-Access-Key': 'YOUR_ACCESS_KEY'
      },
      body: JSON.stringify({
        chainIds: chainId ? [chainId] : undefined
      })
    })
      .then(res => res.json())
      .then(({ pools }) => setPools(pools.filter((p: EarnPool) => p.isActive)));
  }, [chainId]);

  return (
    <ul>
      {pools.map(pool => (
        <li key={pool.id}>
          <strong>{pool.name}</strong>{pool.apy.toFixed(2)}% APY
          ({pool.token.symbol}, chain {pool.chainId})
        </li>
      ))}
    </ul>
  );
};

Next Steps

Earn Mode

Use earn pools in the Trails widget

GetChains

Discover supported chains for earn pools

Body

application/json
chainIds
number[]

[]uint64

protocols
string[]

[]string

minTvl
number
maxApy
number

Response

OK

pools
object[]
required

[]EarnPool

timestamp
string
required
cached
boolean
required