OJO
El límite es por llave y por minuto, y depende del plan del servidor: 60 con Plus, 300 con Premium y 1200 con Business. Cada llave tiene su propio cupo.
Cada respuesta lleva X-RateLimit-Limit (el cupo) y X-RateLimit-Remaining (lo que queda en este minuto).
Al pasarte: 429 rate_limited con Retry-After (los segundos que hay que esperar) y X-RateLimit-Reset (la hora unix en que se vacía la ventana). Espera eso antes de reintentar.
Aparte, 30 fallos de autenticación en un minuto desde una IP dan 429 a esa IP.
OJO
Las listas devuelven meta.next_cursor. Para la página siguiente, pásalo como ?cursor=. En la última página vale null.
limit va de 1 a 100 (por defecto, 25).
order es desc (lo más nuevo primero, por defecto) o asc. Mientras sigues un cursor, no cambies ni order ni los filtros.
Un cursor solo vale con las llaves de su servidor: si no, 400 invalid_cursor.
const API = 'https://api.blixye.com/v1';
const headers = { Authorization: 'Bearer ' + process.env.BLIXYE_API_KEY };
let cursor = null;
for (;;) {
const url = new URL(API + '/characters');
url.searchParams.set('limit', '100');
if (cursor) url.searchParams.set('cursor', cursor);
const res = await fetch(url, { headers });
if (res.status === 429) {
const wait = Number(res.headers.get('Retry-After') || '1');
await new Promise((r) => setTimeout(r, wait * 1000));
continue;
}
if (!res.ok) throw new Error((await res.json()).error.code);
const { data, meta } = await res.json();
for (const character of data) console.log(character.id, character.name);
if (!meta.next_cursor) break;
cursor = meta.next_cursor;
}
const API = 'https://api.blixye.com/v1';
const headers = { Authorization: 'Bearer ' + process.env.BLIXYE_API_KEY };
let cursor = null;
for (;;) {
const url = new URL(API + '/characters');
url.searchParams.set('limit', '100');
if (cursor) url.searchParams.set('cursor', cursor);
const res = await fetch(url, { headers });
if (res.status === 429) {
const wait = Number(res.headers.get('Retry-After') || '1');
await new Promise((r) => setTimeout(r, wait * 1000));
continue;
}
if (!res.ok) throw new Error((await res.json()).error.code);
const { data, meta } = await res.json();
for (const character of data) console.log(character.id, character.name);
if (!meta.next_cursor) break;
cursor = meta.next_cursor;
}
OJO
const API = 'https://api.blixye.com/v1';
const headers = { Authorization: 'Bearer ' + process.env.BLIXYE_API_KEY };
let cursor = null;
for (;;) {
const url = new URL(API + '/characters');
url.searchParams.set('limit', '100');
if (cursor) url.searchParams.set('cursor', cursor);
const res = await fetch(url, { headers });
if (res.status === 429) {
const wait = Number(res.headers.get('Retry-After') || '1');
await new Promise((r) => setTimeout(r, wait * 1000));
continue;
}
if (!res.ok) throw new Error((await res.json()).error.code);
const { data, meta } = await res.json();
for (const character of data) console.log(character.id, character.name);
if (!meta.next_cursor) break;
cursor = meta.next_cursor;
}
GET /v1/events va al revés: de lo más viejo a lo más nuevo, y next_cursor viene siempre. Guárdalo y pásalo en el siguiente sondeo. Sin cursor, empieza 30 días atrás (API v1: eventos).
GET /v1/events va al revés: de lo más viejo a lo más nuevo, y next_cursor viene siempre. Guárdalo y pásalo en el siguiente sondeo. Sin cursor, empieza 30 días atrás (API v1: eventos).
OJO
GET /v1/events va al revés: de lo más viejo a lo más nuevo, y next_cursor viene siempre. Guárdalo y pásalo en el siguiente sondeo. Sin cursor, empieza 30 días atrás (API v1: eventos).