Guides
Building with the API
TypeScript and Python code examples for fetching vaults, filtering by risk tier, and building dashboards with the Philidor API.
TypeScript: Fetch and Filter Vaults
interface Vault {
id: string;
name: string;
total_score: string | number | null;
risk_tier: string;
apr_net: number | null;
tvl_usd: number;
chain_name: string;
protocol_name: string;
}
async function getPrimeVaults(asset: string): Promise<Vault[]> {
const res = await fetch(
`https://api.philidor.io/v1/vaults?riskTier=prime&asset=${asset}&sortBy=apr_net&sortOrder=desc`
);
const { data } = await res.json();
return data;
}
const vaults = await getPrimeVaults('USDC');
for (const v of vaults) {
console.log(`${v.name}: score=${v.total_score}, APR=${((v.apr_net ?? 0) * 100).toFixed(2)}%`);
}Python: Daily Risk Monitor
import requests
import json
from datetime import datetime
API = "https://api.philidor.io/v1"
def check_portfolio(address: str):
res = requests.get(f"{API}/address/{address}/positions")
data = res.json()["data"]
print(f"Portfolio: {address}")
print(f"Total value: USD {float(data['aggregates']['total_value_usd']):,.0f}")
print(f"Weighted risk: {data['aggregates']['weighted_risk_score']:.1f}")
print()
for pos in data["positions"]:
score = pos.get("risk_score")
tier = pos.get("risk_tier", "Unrated")
flag = " monitor" if score is not None and score < 5 else ""
score_label = f"{score:.1f}" if score is not None else "unrated"
print(f" {pos['vault_name']}: {score_label} ({tier}){flag}")
check_portfolio("0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045")Error Handling
async function fetchVault(network: string, address: string) {
const res = await fetch(`https://api.philidor.io/v1/vault/${network}/${address}`);
if (res.status === 404) {
throw new Error(`Vault not found: ${network}/${address}`);
}
if (res.status === 429) {
const retryAfter = res.headers.get('Retry-After');
throw new Error(`Rate limited. Retry after ${retryAfter}s`);
}
if (!res.ok) {
const body = await res.json();
throw new Error(body.error?.message || `HTTP ${res.status}`);
}
const { data } = await res.json();
return data;
}Rate Limit Considerations
- Public endpoints allow 30 requests per minute per IP without an API key
- Use pagination (
page+limit) instead of fetching all vaults at once - Cache responses where possible because vault data updates on hourly sync cycles and incident-triggered rescoring can arrive sooner
- The API returns
X-RateLimit-LimitandX-RateLimit-Windowheaders
Extended API Access
The public read API is available without authentication. Public /v1 read endpoints support evaluation, research, and development out of the box.
For production integrations that need higher rate limits, dedicated API keys, webhooks, or agreement-defined service commitments, contact Philidor to discuss your use case. See API Access and Plans for plan details.
Contact @zdeadex on Telegram or contact@philidor.io
Pagination
async function getAllVaults(): Promise<Vault[]> {
const all: Vault[] = [];
let page = 1;
while (true) {
const res = await fetch(`https://api.philidor.io/v1/vaults?page=${page}&limit=50`);
const { data, meta } = await res.json();
all.push(...data);
if (page >= meta.totalPages) break;
page++;
}
return all;
}