Pular para o conteúdo

Paginação, filtros e ordenação

Todo endpoint de listagem da Ligga API aceita os mesmos parâmetros de query string e devolve o mesmo envelope. Esta página é a referência dessas convenções. Quais campos cada recurso aceita em sort e em filter está na página do recurso.

Uma listagem devolve três chaves no primeiro nível: data com os itens, pagination com o estado da paginação e meta com o identificador da requisição.

{
"data": [{}, {}],
"pagination": {
"next_cursor": "eyJpZCI6ImMwNmQ4NzA1LWYwOTEtNDZlMS04MWJiLTRhMmNlYzY1NjY5NCIsInYiOiIyMDI2LTA1LTE4VDEyOjM0OjU2WiJ9",
"has_more": true,
"limit": 50
},
"meta": { "request_id": "req_9f2c1a7b4d8e4f0a91c3b5d7e2f40a68" }
}
CampoTipoDescrição
pagination.next_cursorstring | nullCursor da próxima página. null na última
pagination.has_morebooleantrue enquanto houver página seguinte
pagination.limitintegerTamanho de página efetivamente aplicado
meta.request_idstringMesmo valor do cabeçalho X-Request-Id

A API pagina por cursor, e não por número de página. Com ?page=2 a lista escorrega quando um registro novo entra entre duas chamadas; com cursor, cada página continua exatamente de onde a anterior parou.

ParâmetroPadrãoDescrição
limit20Itens por página, de 1 a 100. Valor fora da faixa é ajustado para o extremo mais próximo
cursorCursor opaco copiado de pagination.next_cursor

A primeira chamada não leva cursor:

Terminal window
curl "$LIGGA_BASE/v1/customers?limit=50" \
-H "Authorization: Bearer $LIGGA_API_KEY"

As seguintes repetem a mesma query string e acrescentam o cursor devolvido pela anterior:

Terminal window
curl "$LIGGA_BASE/v1/customers?limit=50&cursor=eyJpZCI6ImMwNmQ4NzA1LWYwOTEtNDZlMS04MWJiLTRhMmNlYzY1NjY5NCIsInYiOiIyMDI2LTA1LTE4VDEyOjM0OjU2WiJ9" \
-H "Authorization: Bearer $LIGGA_API_KEY"

Repita enquanto has_more for true:

listar-todos.mjs
const base = process.env.LIGGA_BASE;
const key = process.env.LIGGA_API_KEY;
let cursor = null;
const todos = [];
do {
const qs = new URLSearchParams({ limit: '100', sort: '-created_at' });
if (cursor) qs.set('cursor', cursor);
const res = await fetch(`${base}/v1/customers?${qs}`, {
headers: { Authorization: `Bearer ${key}` },
});
const page = await res.json();
todos.push(...page.data);
cursor = page.pagination.next_cursor;
} while (cursor);

Mantenha sort, filter e fields idênticos entre as páginas. O cursor carrega o valor do campo de ordenação; trocar a ordenação no meio do percurso produz uma sequência sem sentido.

O cursor é opaco: você o copia da resposta e nunca o constrói. A estrutura está documentada só para auditoria.

cursor = base64url( JSON({ id: "<uuid do último item>", v: "<valor do campo de sort>" }) )

O par id + v desempata registros com o mesmo created_at, que é o caso comum em importações em lote.

?sort=-created_at
?sort=full_name
  • Prefixo - ordena de forma decrescente. Sem prefixo, ou com +, é crescente.
  • Apenas um campo por requisição. Não há ordenação composta.
  • O padrão é -created_at em todos os recursos.
  • created_at e updated_at valem em qualquer recurso. Os demais campos ordenáveis estão na página de cada recurso.

Um campo fora da lista devolve 422 com type validation.

O formato é sempre o mesmo:

?filter[<campo>][<operador>]=<valor>
?filter[full_name][ilike]=Ana%
&filter[is_active][eq]=true
&filter[total_amount][gte]=100
&filter[status][in]=paid,pending
OperadorSignificado
eqigual
neqdiferente
gtmaior
gtemaior ou igual
ltmenor
ltemenor ou igual
inestá na lista, separada por vírgula
ninnão está na lista, separada por vírgula
ilikecomparação de texto que ignora maiúsculas, com % como curinga
is_nulltrue traz os nulos; false traz os não nulos

Vários filtros na mesma requisição são combinados com AND. Não há OR, e não há como aninhar condições.

Cada recurso declara quais campos aceitam filtro. Um campo fora dessa lista devolve 422 com type validation em vez de ser ignorado.

Use fields para trazer só o que você vai usar:

?fields=id,full_name,email

Apenas os campos listados voltam no objeto. id entra sempre, mesmo se você não pedir, porque a paginação depende dele.

Alguns recursos expõem relações em include, na leitura de um item:

EndpointValores aceitos
GET /v1/sales/{id}items, status_history
GET /v1/expenses/{id}recurring
Terminal window
curl "$LIGGA_BASE/v1/sales/c06d8705-f091-46e1-81bb-4a2cec656694?include=items,status_history" \
-H "Authorization: Bearer $LIGGA_API_KEY"

Valor de include que o recurso não conhece é ignorado, sem erro. Confira a grafia se a relação não aparecer na resposta.

Terminal window
curl -G "$LIGGA_BASE/v1/customers" \
-H "Authorization: Bearer $LIGGA_API_KEY" \
--data-urlencode "limit=20" \
--data-urlencode "sort=full_name" \
--data-urlencode "filter[full_name][ilike]=Ana%" \
--data-urlencode "filter[is_active][eq]=true" \
--data-urlencode "fields=id,full_name,email,phone"

-G com --data-urlencode evita escapar % e [ na mão, e é a forma mais segura de montar filtros no cURL.

Cursor corrompido, campo de ordenação desconhecido, campo de filtro não permitido e operador inexistente caem todos na mesma resposta: 422 com type validation e um detail que aponta o parâmetro recusado. Nenhum deles chega ao banco.