Pular para o conteúdo

Paginação

Modelo 1: offset (padrão da maioria das listagens)

Seção intitulada “Modelo 1: offset (padrão da maioria das listagens)”

É o modelo do helper de paginação usado pelo grosso dos handlers.

GET /api/v1/alerts?status=OPEN&page=2&limit=50
Authorization: Bearer $SENTINEX_JWT
Param Default Máximo Notas
page 1 n/a Base 1. Valor menor que 1 é corrigido para 1
limit 20 100 Acima de 100 é truncado para 100, sem erro

O offset é calculado no servidor como (page - 1) * limit.

{
"success": true,
"data": [
{ "id": "9c2a1b3e-…", "created_at": "2026-05-18T14:32:11Z" }
],
"meta": {
"page": 2,
"limit": 50,
"total": 137
}
}

Você chegou ao fim quando page * limit >= meta.total, ou quando data volta com menos itens que limit.

Parte da superfície /vasp/* usa offset direto em vez de page, e devolve a chave pagination em vez de meta. Exemplo medido em GET /api/v1/vasp/alerts:

GET /api/v1/vasp/alerts?status=OPEN&limit=50&offset=100
X-API-Key: $SENTINEX_API_KEY
{
"success": true,
"data": [],
"pagination": {
"total": 137,
"limit": 50,
"offset": 100
}
}

Aqui o limit tem default 50 e teto 200.

Disponível em rotas de busca específicas, como a busca de clientes e a listagem de enrollments. O cursor não se chama cursor: o parâmetro é cursor_before, e o valor vem no campo next_cursor da resposta anterior.

GET /api/v1/clients?pagination=cursor&limit=100&cursor_before=<valor de next_cursor>
Authorization: Bearer $SENTINEX_JWT
Param Default Máximo Notas
pagination vazio n/a Só aceita cursor. Outro valor retorna 400
cursor_before vazio n/a Opaco. Use exatamente como veio em next_cursor
limit 50 200 Acima de 200 é truncado

next_cursor é irmão de data, e não fica dentro de um objeto pagination:

{
"success": true,
"data": [
{ "id": "9c2a1b3e-…", "external_id": "ACME-001" }
],
"next_cursor": "eyJjcmVhdGVkX2F0IjoiMjAyNi0wNS0xOFQxNDozMjoxMVoifQ"
}

Quando a lista acaba, next_cursor vem como string vazia, e não como null. Pare quando ele for falsy.

// Modelo cursor: pare quando next_cursor vier vazio
async function* paginarPorCursor(endpoint, params = {}) {
let cursorBefore = undefined;
for (;;) {
const res = await api.get(endpoint, {
params: { ...params, pagination: 'cursor', limit: 200, cursor_before: cursorBefore },
});
for (const item of res.data) yield item;
if (!res.next_cursor) return; // "" encerra
cursorBefore = res.next_cursor;
}
}
// Modelo offset: pare quando a página vier menor que o limite
async function* paginarPorPagina(endpoint, params = {}) {
const limit = 100;
for (let page = 1; ; page++) {
const res = await api.get(endpoint, { params: { ...params, page, limit } });
for (const item of res.data) yield item;
if (res.data.length < limit) return;
}
}
  • Não troque filtros entre páginas. No modelo cursor, o cursor codifica a posição no resultset filtrado; no modelo offset, mudar filtro no meio embaralha a janela. Mudou filtro, recomece do início.
  • Offset é instável sob escrita concorrente. Itens novos deslocam a janela e você pode repetir ou pular registros. Para varredura completa de dados que mudam, prefira uma janela temporal fechada (from, to) em vez de percorrer todas as páginas.
  • Não decodifique o cursor. Ele é opaco e o formato pode mudar sem aviso.
  • Não existe um código de erro INVALID_CURSOR: cursor inválido cai na validação genérica de parâmetro, com 400.