Pular para o conteúdo
Sursa Developers

Paginação

As listas da API do Sursa são paginadas com um cursor: você pede até limit itens, e a resposta diz como obter a próxima página. Você nunca calcula deslocamentos, e os itens não se repetem nem somem entre as páginas quando os dados mudam nesse meio-tempo.

ParâmetroValor
limitQuantos itens por página, em geral de 1 a 200. As listas novas têm o padrão 50; a referência mostra o intervalo e o padrão de cada lista.
cursorO cursor da página anterior. Omita-o na primeira página.

Uma lista retorna o próximo cursor de uma de duas formas, conforme o formato da resposta dela. A página de cada endpoint na referência da API mostra qual delas ele usa.

Listas com envelope data

As listas acrescentadas para a API pública, como o feed de eventos, retornam um objeto com os itens em data:

curl "https://api.sursa.com/v1/webhook-events?limit=2" \
  -H "Authorization: Bearer $SURSA_API_KEY"
{
  "data": [
    {"id": "evt_8a1f…", "type": "card.published", "created_at": "2026-10-24T10:00:00Z"},
    {"id": "evt_8a20…", "type": "card.updated", "created_at": "2026-10-24T10:00:03Z"}
  ],
  "next_cursor": "eyJ2IjoxLCJrIjpbMTA0Ml19",
  "has_more": true
}

Quando has_more é true, peça a próxima página com cursor igual a next_cursor e os mesmos filtros:

curl "https://api.sursa.com/v1/webhook-events?limit=2&cursor=eyJ2IjoxLCJrIjpbMTA0Ml19" \
  -H "Authorization: Bearer $SURSA_API_KEY"

As listas que já existiam antes dos cursores e retornam um objeto mantêm o próprio envelope (por exemplo, {"items": […], "total": 120}). Elas recebem next_cursor e has_more no mesmo objeto; os itens ficam onde estavam.

Listas que retornam um array

Algumas listas retornam um array JSON simples, por exemplo GET /v1/collections. O formato da resposta delas não pode mudar, então a próxima página vem nos cabeçalhos:

curl -i "https://api.sursa.com/v1/collections?limit=50" \
  -H "Authorization: Bearer $SURSA_API_KEY"
HTTP/1.1 200 OK
Link: <https://api.example.com/v1/collections?limit=50&cursor=eyJ2IjoxLCJrIjpbNTBdfQ>; rel="next"
X-Next-Cursor: eyJ2IjoxLCJrIjpbNTBdfQ

[{"id": 1, "name": "support", …}, …]
  • Link com rel="next" é o endereço completo da próxima página; X-Next-Cursor é o mesmo cursor, sozinho.
  • Sem Link com rel="next" e sem X-Next-Cursor, esta é a última página.
  • Sem limit, essas listas retornam todos os itens em uma única resposta, como sempre fizeram. Passe limit para paginá-las; o cursor guarda o tamanho da página, então a próxima requisição pode omitir limit.
  • GET /v1/cards é a exceção: ela sempre retorna páginas, com 200 cartões por padrão e até 1000 com limit, então siga X-Next-Cursor mesmo sem limit.
// Every item of a list that returns an array.
async function* listArray(path) {
  let next = `https://api.sursa.com${path}?limit=200`;
  while (next) {
    const response = await fetch(next, { headers: { Authorization: `Bearer ${process.env.SURSA_API_KEY}` } });
    if (!response.ok) throw new Error(`HTTP ${response.status}`);
    yield* await response.json();
    const cursor = response.headers.get("X-Next-Cursor");
    next = cursor ? `https://api.sursa.com${path}?cursor=${encodeURIComponent(cursor)}` : null;
  }
}

O feed de eventos

O feed de eventos GET /v1/webhook-events é um registro, então a paginação dele é um pouco diferente:

  • Os eventos estão em ordem crescente, os mais antigos primeiro.
  • next_cursor é retornado em todas as páginas, mesmo quando has_more é false. Guarde-o e pergunte de novo mais tarde com o mesmo cursor para receber os eventos que aconteceram desde então. O feed é uma fila que você pode ler no seu próprio ritmo.
  • Um evento aparece no feed cerca de um segundo depois da alteração que ele descreve, e nunca antes de um evento que já foi lido.
  • O feed reúne os eventos da organização inteira, por isso, para lê-lo, é preciso uma chave com a função admin e o escopo webhooks:manage.

Exportar para um data warehouse mostra um loop de consulta periódica completo.

Regras dos cursores

  • Um cursor é uma string opaca de até 512 caracteres. Não o decomponha nem o monte por conta própria: o formato dele pode mudar.
  • Um cursor pertence a uma lista e a um conjunto de filtros. Um cursor danificado, vindo de outra lista ou enviado com filtros diferentes retorna 400 com o código api.cursor_invalid.
  • Cada lista tem uma ordenação fixa que termina com uma chave única, então cada item aparece em exatamente uma página.
  • As listas acrescentadas com cursores não retornam uma contagem total; as listas que já tinham total o mantêm. Conte os itens conforme avança, se precisar de um total.

Paginação por deslocamento

Algumas listas aceitavam offset antes da introdução dos cursores e continuam aceitando, para que as integrações existentes continuem funcionando. Prefira cursor em código novo. offset e cursor não podem ser combinados: enviar os dois retorna 422 com o código validation.failed.