Paginación y filtros
Cursores, filtros por fecha y cómo hacer una sincronización incremental confiable.
Listas
Todos los endpoints que listan (GET /products, GET /sales, GET /events…) responden igual:
- El orden es siempre
created_atdescendente (lo más reciente primero), con elidpara desempatar. limitva de 1 a 100; por defecto, 25.- Si
has_moreestrue, pide la página siguiente pasandonext_cursortal cual enstarting_after. Cuandohas_moreesfalse,next_cursoresnully terminaste. - El cursor es opaco: no lo construyas ni lo modifiques. Uno alterado responde
400 INVALID_CURSOR.
Como el orden es por fecha de creación, un registro que se edita no cambia de posición: puedes recorrer todas las páginas mientras el negocio sigue vendiendo sin saltarte ni repetir registros.
Filtros por fecha
Las fechas van en ISO 8601 con zona horaria: 2026-09-28T00:00:00Z o 2026-09-28T00:00:00-05:00.
Una fecha sin zona horaria se rechaza con 400 VALIDATION_ERROR, porque no hay forma de saber a qué hora
te refieres. En la URL, codifica el + de una zona positiva como %2B.
GET /events no tiene updated_since: los eventos no se modifican.
Además, cada lista tiene sus propios filtros (status, customer_id, sku, q, occurred_since…): los
encuentras en la referencia. La búsqueda q es literal: % y _ se buscan como esos
caracteres, no como comodines. Un filtro que no existe (o mal escrito) se rechaza con
400 VALIDATION_ERROR; nunca se ignora en silencio, porque ignorarlo te devolvería más datos de los que
pediste.
Registros eliminados
Productos, categorías y clientes aceptan include_deleted=true en la lista y en la consulta por id. Sin él,
los eliminados no aparecen; con él, aparecen con deleted_at distinto de null. Úsalo en tu sincronización
incremental para enterarte de lo que se eliminó en las cajas.
Receta: sincronización incremental
Para mantener una copia de, por ejemplo, los productos en tu sistema:
- Carga inicial: recorre
GET /products?limit=100&include_deleted=truepágina por página hasta quehas_moreseafalse. Antes de empezar, anota la hora de inicio (T0). - Cada corrida siguiente: pide
GET /products?updated_since=<T_anterior>&limit=100&include_deleted=true, recorre todas las páginas y haz upsert porid. Sideleted_atno esnull, márcalo como eliminado en tu sistema. - Guarda como nuevo punto de partida la hora en que empezó la corrida, restándole un margen (por ejemplo, 5 minutos). Procesar dos veces un registro es inofensivo si haces upsert; saltarte uno no.
En las ventas, created_at es cuando la venta llegó al servidor; cuándo se registró en la caja lo dice
occurred_at. Una caja que trabajó sin internet sube sus ventas al reconectarse, con un created_at de ese
momento. Por eso, para la sincronización incremental, filtra por created_since/updated_since (sí te
traen esas ventas en la siguiente corrida), no por occurred_since. Usa occurred_at para tus reportes.
Lee Cómo se sincroniza con las cajas.