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âmetro | Valor |
|---|---|
limit | Quantos 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. |
cursor | O 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", …}, …]
Linkcomrel="next"é o endereço completo da próxima página;X-Next-Cursoré o mesmo cursor, sozinho.- Sem
Linkcomrel="next"e semX-Next-Cursor, esta é a última página. - Sem
limit, essas listas retornam todos os itens em uma única resposta, como sempre fizeram. Passelimitpara paginá-las; o cursor guarda o tamanho da página, então a próxima requisição pode omitirlimit. GET /v1/cardsé a exceção: ela sempre retorna páginas, com 200 cartões por padrão e até 1000 comlimit, então sigaX-Next-Cursormesmo semlimit.
// 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 quandohas_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
admine o escopowebhooks: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
400com o códigoapi.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
totalo 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.