Documentation Index
Fetch the complete documentation index at: https://docs.pan.tech/llms.txt
Use this file to discover all available pages before exploring further.
Limites por Plan
| Plan | Requests/minuto | Wallets | Creditos/mes |
|---|
| Free | 100 | 100 | 100 |
| Pro | 1,000 | 10,000 | 10,000 |
| Enterprise | Custom | Ilimitadas | Custom |
Cada respuesta incluye headers informativos:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1642248000
| Header | Descripción |
|---|
X-RateLimit-Limit | Máximo requests por minuto |
X-RateLimit-Remaining | Requests restantes en ventana actual |
X-RateLimit-Reset | Timestamp Unix cuando se reinicia |
Respuesta 429
Cuando excedes el limite:
{
"error": "RATE_LIMITED",
"message": "Too many requests",
"details": {
"limit": 100,
"window": "1 minute",
"retryAfter": 45
}
}
Headers adicionales:
Manejo Recomendado
Backoff Exponencial
async function requestConBackoff(fn, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await fn();
} catch (error) {
if (error.status !== 429) throw error;
const wait = Math.pow(2, i) * 1000; // 1s, 2s, 4s
console.log(`Rate limited. Esperando ${wait}ms...`);
await new Promise(r => setTimeout(r, wait));
}
}
throw new Error('Max retries exceeded');
}
Usar Retry-After
async function request(url, options) {
const response = await fetch(url, options);
if (response.status === 429) {
const retryAfter = response.headers.get('Retry-After');
const wait = parseInt(retryAfter) * 1000;
console.log(`Rate limited. Retry after ${retryAfter}s`);
await new Promise(r => setTimeout(r, wait));
return request(url, options);
}
return response;
}
Rate Limiter Local
class RateLimiter {
constructor(maxRequests, windowMs) {
this.maxRequests = maxRequests;
this.windowMs = windowMs;
this.requests = [];
}
async acquire() {
const now = Date.now();
// Limpiar requests viejos
this.requests = this.requests.filter(
t => now - t < this.windowMs
);
// Verificar limite
if (this.requests.length >= this.maxRequests) {
const oldestRequest = this.requests[0];
const waitTime = this.windowMs - (now - oldestRequest);
await new Promise(r => setTimeout(r, waitTime));
return this.acquire();
}
this.requests.push(now);
}
}
// Uso
const limiter = new RateLimiter(100, 60000); // 100/min
async function makeRequest() {
await limiter.acquire();
return fetch('https://api.pan.tech/v1/yields', { ... });
}
Créditos
Ademas del rate limit, cada request consume creditos:
| Endpoint | Créditos |
|---|
| POST /wallets | 1 |
| GET /wallets/:id | 1 |
| GET /balances/:id | 1 |
| GET /yields | 1 |
| POST /intents | 5 |
| GET /intents/:id | 1 |
Verificar Creditos
curl https://api.pan.tech/dashboard/credits \
-H "Authorization: Bearer $PAN_API_KEY"
{
"balance": 8750,
"totalPurchased": 10000,
"totalUsed": 1250,
"plan": "pro"
}
Optimizar Uso
- Cache respuestas de yields - APYs no cambian cada segundo
- Batch requests - Agrupa operaciones cuando sea posible
- Polling inteligente - Usa 5-10 segundos, no menos
- Almacena walletIds - No consultes si ya los tienes
// Cache de yields
let yieldsCache = null;
let yieldsCacheTime = 0;
async function getYields() {
const now = Date.now();
if (yieldsCache && now - yieldsCacheTime < 60000) {
return yieldsCache;
}
yieldsCache = await pan.yields.getAll();
yieldsCacheTime = now;
return yieldsCache;
}