Paginación
Paginación
Cómo recorrer listados largos sin perder ni repetir registros.
La API tiene tres estilos de paginación conviviendo —y varias formas distintas de respuesta entre ellos—. No es una decisión de diseño: es historia. Antes de recorrer un listado, mirá en la API Reference qué parámetros acepta ese endpoint y qué esquema devuelve. Abajo está la tabla de cuál usa cada uno.
Estilo 1 — limit y offset
Es el que usan los endpoints más nuevos, entre ellos los de la sección
organizations y los de usuarios.
La respuesta trae el total de registros y la página pedida:
Para avanzar, sumás limit al offset: offset=50, offset=100, y así.
Terminás cuando results trae menos elementos que el limit pedido.
Estos endpoints no devuelven la envoltura de message / code / data:
total y results están en la raíz de la respuesta. Es la diferencia que más
sorprende al escribir el primer cliente, porque el mismo código no sirve para
leer un listado y para leer una operación de escritura.
El techo de limit no es el mismo en todos los endpoints, y pedir más
devuelve 422. Los de organizations y los de timeoff cortan en 50, los de
usuarios y los reportes de learning en 100, y el reporte general v2 y los cuatro
de Asistencia admiten hasta 500. El valor por defecto tampoco es único: en
varios es 10 y en los reportes es 100. Cada operación dice su techo y su valor
por omisión en la API Reference; si no querés mirarlo, mandá limit explícito y
quedate abajo de 50.
Este estilo es sensible a los cambios durante el recorrido. Si mientras paginás se da de alta un usuario, los registros se corren y podés ver uno repetido o saltearte otro. Para exportaciones grandes conviene hacerlas en una ventana de poca actividad.
Estilo 2 — cursor y first
Es el que usan los endpoints construidos sobre conexiones, entre ellos los deprecados de estructura organizacional y los grupos de permisos.
La respuesta trae los campos que necesitás para seguir:
Mientras has_next_page sea true, repetís la llamada pasando
cursor=<next_cursor>. Este estilo no se corre si los datos cambian a mitad
de camino: el cursor apunta a una posición estable.
La variante del catálogo
Los endpoints del catálogo de contenidos también se paginan con first y
cursor, pero la respuesta viene con otra forma: la conexión sin aplanar.
Los registros están en edges, cada uno dentro de un node, y los datos para
seguir están en page_info:
El recorrido es el mismo, con los campos en otro lugar: mientras
page_info.has_next_page sea true, repetís pasando
cursor=<page_info.end_cursor>. Y para leer un registro hay que bajar un nivel
más, a edges[].node.
Estilo 3 — limit y cursor (reportes de Asistencia)
Los reportes de Recepción de marcas y Gestión diaria de marcas paginan
con un cursor, pero la respuesta conserva la misma forma que el resto de los
reportes: total y results en la raíz, más dos campos para seguir.
Mientras has_next_page sea true, repetís la misma llamada agregando
cursor=<next_cursor>. El cursor es opaco: mandalo tal cual vino, sin
decodificarlo ni construirlo vos.
Los otros dos reportes de Asistencia —Creación de turnos y Programación de
turnos— siguen con limit y offset, como el resto de los reportes. Son
catálogos de cientos de filas, no de millones.
Por qué estos dos son distintos
Marcas y jornadas crecen con colaboradores × días: en una organización grande
son millones de filas. Con offset, cada página obliga a la base a producir y
descartar todas las filas anteriores, así que bajar el reporte completo se
vuelve cada vez más lento a medida que avanzás. El cursor apunta a la última
fila entregada, de modo que la página siguiente arranca ahí y cuesta lo mismo
sea la primera o la número doscientos.
Estos dos endpoints no aceptan offset. Si lo mandás, la respuesta es
400. No se ignora en silencio a propósito: si lo hiciera, recibirías siempre
la primera página creyendo que estás avanzando.
La paginación es solo hacia adelante. No hay cursor previo ni
has_previous_page: no se puede retroceder ni saltar a una página arbitraria.
Si necesitás una porción puntual del reporte, acotá from_date y to_date en
vez de paginar hasta ahí.
El recorrido completo
El cursor está atado a la consulta que lo generó. Si cambiás from_date,
to_date, limit o el filtro por colaborador, empezá de nuevo desde la
primera página: un cursor de otra consulta devuelve 400.
Cuál usa cada endpoint
En vez de memorizarlo, miralo en la API Reference: los parámetros de query están listados en cada operación, y el esquema de la respuesta dice cuál forma devuelve. Como regla aproximada:
Recomendaciones
- No asumas un tamaño de página por defecto. Pedí siempre
limitofirstde forma explícita. - Frená por la respuesta, no por un contador. Usá
has_next_page, o que la página venga incompleta. Calcular la cantidad de páginas a partir detotal_countfalla si los datos cambian. - Guardá el cursor, no el número de página. En los estilos 2 y 3 el cursor es lo único que garantiza continuidad.
- No construyas ni interpretes un cursor. Es opaco y su formato puede cambiar sin aviso: reenviá exactamente el que te devolvió la respuesta.
