Paginación
Cómo funcionan limit y offset en GET /v1/external/tournaments, qué contiene el sobre meta, y por qué los demás endpoints de listado devuelven todo de una vez.
Exactamente un endpoint pagina: GET /v1/external/tournaments. Toma limit y
offset, devuelve sus filas bajo data y reporta la ventana bajo meta. Los
otros dos endpoints de listado — categorías y equipos — devuelven un arreglo JSON
pelón con todas las filas de ese torneo, porque ambos están acotados por cuántas
categorías e inscripciones cabe en un solo torneo.
El sobre
{
"data": [
{
"idx": "3c9b7f52-6d41-4a8e-b1f0-2e7d5c9a4b18",
"name": "Torneo Apertura 2026"
},
{ "idx": "a41e08d7-33b2-4c96-8f5a-6b0d2e1c7934", "name": "Liga Otoño 2026" }
],
"meta": { "limit": 2, "offset": 0, "total": 37 }
}| Campo | Significado |
|---|---|
data | Las filas de esta ventana |
meta.limit | El tamaño de página que se aplicó realmente |
meta.offset | El offset que se aplicó realmente |
meta.total | Total de filas que cumplen los filtros, ignorando limit y offset |
Parámetros
| Parámetro | Tipo | Por defecto | Rango |
|---|---|---|---|
limit | entero | 25 | 1–100 |
offset | entero | 0 | 0 o mayor |
Los valores fuera de rango son un 400, no un ajuste automático: limit=0,
limit=101 y offset=-1 fallan la validación. Los no enteros también fallan.
Orden
Los torneos regresan ordenados por startDate descendente — la temporada más
reciente primero. El orden es estable entre páginas para un conjunto de datos
fijo.
Recorrer todas las páginas
Detente cuando hayas juntado meta.total filas, o cuando una página regrese
corta.
async function listAllTournaments(token, params = {}) {
const BASE = 'https://api.setto.io/v1';
const limit = 100;
const all = [];
let offset = 0;
let total = Infinity;
while (offset < total) {
const query = new URLSearchParams({
...params,
limit: String(limit),
offset: String(offset),
});
const res = await fetch(`${BASE}/external/tournaments?${query}`, {
headers: { Authorization: `Bearer ${token}` },
});
if (!res.ok) throw new Error(`SETTO API ${res.status}`);
const { data, meta } = await res.json();
all.push(...data);
total = meta.total;
offset += limit;
if (data.length === 0) break; // defensivo: nunca dar vueltas para siempre
}
return all;
}def list_all_tournaments(token, **params):
BASE = "https://api.setto.io/v1"
headers = {"Authorization": f"Bearer {token}"}
limit, offset, total, out = 100, 0, None, []
while total is None or offset < total:
res = requests.get(
f"{BASE}/external/tournaments",
headers=headers,
params={**params, "limit": limit, "offset": offset},
timeout=10,
)
res.raise_for_status()
body = res.json()
if not body["data"]:
break
out.extend(body["data"])
total = body["meta"]["total"]
offset += limit
return outFiltra antes de paginar
status y sport se aplican antes de la ventana, así que meta.total refleja
el conjunto ya filtrado. Acotar con status=IN_PROGRESS casi siempre sale más
barato que paginar por un archivo histórico.
Deriva del offset
La paginación por offset lee una lista en movimiento. Si se crea un torneo, o se
edita su startDate, mientras estás entre páginas, una fila puede cruzar el
límite de página y devolverse dos veces o saltarse.
Para una exportación larga:
- pagina con
limit=100para cruzar menos fronteras; - elimina duplicados por
idxconforme acumulas; - o fija la ventana con un filtro que no cambie bajo tus pies, como
status=COMPLETED.
No trates offset como un cursor que puedas persistir entre ejecuciones —
vuelve a correr el recorrido desde offset=0 cada vez.
Los otros listados
GET /v1/external/tournaments/{idx}/divisions y
GET /v1/external/tournaments/{idx}/teams no toman limit ni offset y
devuelven un arreglo JSON directo — sin sobre data/meta:
[
{
"idx": "7b2f4d16-9c83-4e50-a7d1-3f6c8b204e59",
"name": "Cuarta Fuerza Varonil",
"number": 1
},
{
"idx": "c58a1e93-0b74-42df-96e8-5a3d7f1b28c0",
"name": "Segunda Fuerza Femenil",
"number": 2
}
]Las categorías vienen ordenadas por number ascendente. Los equipos vienen
ordenados por seed ascendente con los no sembrados al final, y luego por
name.
Si un torneo muy grande vuelve incómodos esos payloads, acota la llamada de
equipos con el filtro division — ?division={divisionIdx} — en lugar de pedir
un tamaño de página que no existe.
Populate
Cómo el parámetro de consulta populate incrusta relaciones, la lista blanca exacta por endpoint, los valores por defecto de cada endpoint y las reglas para las rutas anidadas.
Errores
La forma del cuerpo de error, todos los códigos que devuelve la API externa de SETTO, qué significa cada uno y si reintentar sirve de algo.