Pular para o conteúdo

Paginação

Percorra listas longas com cursor: estável mesmo que registros sejam criados enquanto você pagina.

O que pagina como

Endpoint Cursor Offset Ordem meta
GET /api/v1/cotizaciones Sim Sim O mais recente primeiro limit, offset, total, next_cursor
GET /api/v1/clientes Sim Sim Por empresa (de A a Z) limit, offset, total, next_cursor
GET /api/v1/productos Sim Sim Ativos primeiro, depois por nombre limit, offset, total, next_cursor
GET /api/v1/facturas Sim Não A mais recente primeiro next_cursor
GET /api/v1/events Sim Não O mais recente primeiro next_cursor
GET /api/v1/webhooks Não Não O mais recente primeiro Sem meta: devolve todos os endpoints da chave.
GET /api/v1/cobranza Não Não — Sem meta: devolve a carteira completa de recebíveis.

Em todas as listas paginadas, limit vai de 1 a 200 e vale 50 se você não o enviar.

Use o cursor

Peça a primeira página sem cursor. Se meta.next_cursor trouxer um valor, repita a mesma requisição, com os mesmos filtros, acrescentando cursor=<next_cursor>. Quando chegar null, não há mais nada.

curl "https://cordhq.app/api/v1/clientes?limit=2" \
  -H "Authorization: Bearer sk_test_..."
{
  "data": [
    { "id": "0e6f2b8a-91c4-4d7e-b3a5-6c2d8f1e4a90", "empresa": "Aceros Monterrey", "email": "compras@acerosmty.mx" },
    { "id": "7a2d4c19-5e8b-4f3a-a1d6-9c0e2b4f6d81", "empresa": "Bodega Central", "email": "" }
  ],
  "meta": {
    "limit": 2,
    "offset": 0,
    "total": 142,
    "next_cursor": "WyJCb2RlZ2EgQ2VudHJhbCIsIjdhMmQ0YzE5LTVlOGItNGYzYS1hMWQ2LTljMGUyYjRmNmQ4MSJd"
  }
}
curl "https://cordhq.app/api/v1/clientes?limit=2&cursor=WyJCb2RlZ2EgQ2VudHJhbCIsIjdhMmQ0YzE5LTVlOGItNGYzYS1hMWQ2LTljMGUyYjRmNmQ4MSJd" \
  -H "Authorization: Bearer sk_test_..."

O exemplo reduz cada cliente a três campos; a resposta real traz o objeto completo.

O cursor é um token opaco: não o interprete, não o construa e não o guarde para outra lista. Reenvie-o como está, codificado para URL (os exemplos abaixo fazem isso por você). Com cursor, o offset é ignorado e meta.offset chega como null.

Por que cursor e não offset

Com offset, um orçamento criado enquanto você percorre a lista desloca tudo em uma posição: a página seguinte repete um registro e, se um for excluído, você pula outro sem perceber. O cursor aponta para a última linha que você viu, então a próxima página começa exatamente depois dela, haja ou não escritas.

offset continua funcionando em orçamentos, clientes e produtos por compatibilidade. meta.total conta todos os registros do filtro: serve para mostrar “142 clientes”, não para decidir quando parar. Para isso, use next_cursor.

Percorrer uma lista completa

#!/usr/bin/env bash
# Exige jq. Imprime o id e a empresa de todos os clientes.
set -euo pipefail
args=(-sSG "https://cordhq.app/api/v1/clientes" -d limit=200 -H "Authorization: Bearer $CORD_API_KEY")
cursor=""
while :; do
  if [ -n "$cursor" ]; then
    page=$(curl "${args[@]}" --data-urlencode "cursor=$cursor")
  else
    page=$(curl "${args[@]}")
  fi
  echo "$page" | jq -r '.data[] | [.id, .empresa] | @tsv'
  cursor=$(echo "$page" | jq -r '.meta.next_cursor // empty')
  [ -z "$cursor" ] && break
done

listAll() existe em quotes, clients, products, invoices e events, e sempre pagina por cursor desde a versão 1.1.0 do SDK. Veja SDK de Node.

Erros

Situação Resposta
Um cursor que não é de orçamentos, clientes ou produtos 400, code: "invalid_cursor", error: "El cursor no es válido. Usa el next_cursor de la respuesta anterior."
Um cursor que não é de eventos 400, code: "invalid_request", error: "cursor inválido"
limit fora do intervalo Não é erro: é ajustado para 1 ou 200.
{
  "error": "El cursor no es válido. Usa el next_cursor de la respuesta anterior.",
  "code": "invalid_cursor",
  "request_id": "req_5d2b8f1a4c7e0b3d6a9f2c5e",
  "doc_url": "https://docs.cordhq.app/docs/desarrolladores/esenciales/errores#invalid_cursor"
}

Um cursor não serve entre listas nem entre filtros: se você mudar status, type ou qualquer outro filtro, comece de novo sem cursor.