Paginación
Los listados se paginan con cursor: estables aunque se creen registros mientras recorres las páginas y sin saltos ni duplicados.
Cómo funciona
- Parámetro
limit: tamaño de página, de 1 a 100 (por defecto 50). - La respuesta es
{"results": [...], "next_cursor": "..."}. - Si
next_cursorno esnull, pide la página siguiente con?cursor=<next_cursor>(y los mismos filtros). Cuando esnullhas terminado. - El cursor es opaco: no lo construyas ni lo modifiques. Un cursor manipulado o de otro
listado responde
400 invalid_cursor.
Orden: áreas, vacaciones y tramos de horas, del más reciente al más antiguo; empleados,
en el orden del panel (número de empleado), y al pasar cursor se mantiene el
limit de la primera petición.
Recorrer todos los empleados
Python
import os
import requests
BASE_URL = "https://api.xyago.com/v1"
session = requests.Session()
session.headers["Authorization"] = f"Bearer {os.environ['XYAGO_API_KEY']}"
def all_employees():
params = {"limit": 100}
while True:
response = session.get(f"{BASE_URL}/employees", params=params, timeout=30)
response.raise_for_status()
page = response.json()
yield from page["results"]
if not page["next_cursor"]:
return
params = {"cursor": page["next_cursor"]}
for employee in all_employees():
print(employee["external_id"], employee["first_name"], employee["status"])
JavaScript
const BASE_URL = "https://api.xyago.com/v1";
const headers = { Authorization: `Bearer ${process.env.XYAGO_API_KEY}` };
async function* allEmployees() {
let url = `${BASE_URL}/employees?limit=100`;
while (url) {
const response = await fetch(url, { headers });
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const page = await response.json();
yield* page.results;
url = page.next_cursor
? `${BASE_URL}/employees?cursor=${encodeURIComponent(page.next_cursor)}`
: null;
}
}
for await (const employee of allEmployees()) {
console.log(employee.external_id, employee.first_name, employee.status);
}
C#
using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Text.Json;
using var http = new HttpClient { BaseAddress = new Uri("https://api.xyago.com/v1/") };
http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
"Bearer", Environment.GetEnvironmentVariable("XYAGO_API_KEY"));
string? cursor = null;
do
{
var url = cursor is null ? "employees?limit=100" : $"employees?cursor={Uri.EscapeDataString(cursor)}";
var page = await http.GetFromJsonAsync<JsonElement>(url);
foreach (var employee in page.GetProperty("results").EnumerateArray())
{
Console.WriteLine($"{employee.GetProperty("external_id")} {employee.GetProperty("first_name")}");
}
var next = page.GetProperty("next_cursor");
cursor = next.ValueKind == JsonValueKind.Null ? null : next.GetString();
} while (cursor is not null);
curl
curl "https://api.xyago.com/v1/employees?limit=100" -H "Authorization: Bearer $XYAGO_API_KEY"
# ...y con el next_cursor de la respuesta:
curl "https://api.xyago.com/v1/employees?cursor=eyJwIjogMiwgInMiOiAxMDB9" -H "Authorization: Bearer $XYAGO_API_KEY"
Consejos
- Para saber si un empleado ya existe no recorras la lista: usa
GET /employees?external_id=...(devuelve 0 o 1 resultado). - Cada página cuenta para el límite de peticiones: usa
limit=100en sincronizaciones completas. - Para enterarte de cambios, mejor webhooks que releer listados completos cada pocos minutos.