Paginação + idempotência
Paginação por cursor em cada endpoint de listagem; Idempotency-Key em cada endpoint que altera estado. Dois padrões a interiorizar uma vez; cada endpoint segue-os.
Paginação por cursor
Todos os endpoints de listagem (GET /api/v1/public/sessions, /evidence, /whiteboards, etc.) devolvem um envelope:
{
"data": [
{ /* resource */ },
{ /* resource */ }
],
"has_more": true,
"next_cursor": "eyJjcmVhdGVkX2F0IjoiMjAyNi0wNS0yMVQxNDoyMSswMDowMCJ9"
} Como paginar
- Emita o primeiro request sem o param
cursor. - Se
has_morefortrue, passenext_cursortal como está como query paramcursorno request seguinte. - Repita até
has_moreserfalse.
curl "https://app.nexbasira.com/api/v1/public/sessions?limit=25" \
-H "Authorization: Bearer nb_sec_..."
# response includes next_cursor: "eyJjcmVhdGVkX2F0Ijo..."
curl "https://app.nexbasira.com/api/v1/public/sessions?limit=25&cursor=eyJjcmVhdGVkX2F0Ijo..." \
-H "Authorization: Bearer nb_sec_..." Limites
| Param | Por defeito | Máx. |
|---|---|---|
limit | 25 | 100 |
Valores mais altos de limit reduzem o número de idas e voltas mas aumentam o tamanho do payload por resposta + o tempo de serialização. O valor por defeito 25 é adequado para uso em UI; os trabalhos em lote noturnos passam tipicamente 100.
Forma do cursor
O cursor é opaco para os clientes — é um blob JSON codificado em base64 que codifica a posição no queryset subjacente. Não faça o parse nem construa cursores; passe-os apenas tal como estão. A forma não é estável entre versões da API.
Ordenação
A ordenação por defeito é created_at DESC (mais recente primeiro) para cada endpoint de listagem. É também a ordem em que o cursor avança — vai percorrer do mais recente ao mais antigo à medida que pagina.
Helpers do SDK
Ambos os SDKs incluem um async-iterator transparente que pagina por si:
// @nexbasira/node
for await (const session of nb.sessions.list({ limit: 100 })) {
// ...
}
// nexbasira (Python)
for session in nb.sessions.iter(limit=100):
... Idempotência
Cada endpoint que altera estado aceita um cabeçalho Idempotency-Key. Passe uma chave única (tipicamente um UUID) por operação lógica; uma retentativa com a mesma chave devolve a resposta em cache sem recriar o recurso.
curl -X POST https://app.nexbasira.com/api/v1/public/sessions \
-H "Authorization: Bearer nb_sec_..." \
-H "Idempotency-Key: 01HGAB7T8X3PVT3HKEXAMPLE" \
-H "Content-Type: application/json" \
-d '{"notes": "Vehicle damage CL-2026-0042"}' Janela de cache
As respostas em cache vivem durante 24 horas. Um replay após 24h com a mesma chave cria um novo recurso — trate a chave como válida apenas durante o seu ciclo de retentativas.
Scoping
As chaves têm scope em (credential, endpoint, method):
- Uma retentativa da mesma credencial para o mesmo endpoint com a mesma chave devolve a resposta em cache.
- Uma credencial diferente a usar a mesma chave cria um novo recurso (trata-a como uma chamada nova).
- A mesma chave num endpoint diferente cria um novo recurso (slot de cache separado).
O que é colocado em cache
Apenas respostas bem-sucedidas (2xx). Um request falhado não envenena a cache — a sua próxima retentativa com a mesma chave obtém uma tentativa nova.
Eco de cabeçalho
As respostas idempotentes bem-sucedidas devolvem a chave no cabeçalho de resposta Idempotency-Key — útil para logging / correlação.
Gerar chaves
Use qualquer coisa que seja globalmente única por operação lógica:
crypto.randomUUID()no Node 19+uuid.uuid4()em Python- O id do seu processo de negócio (ex.: número de sinistro + timestamp) se quiser traces legíveis por humanos nos logs
Helpers do SDK
// @nexbasira/node — pass via second arg
await nb.sessions.create(
{ notes: "..." },
{ idempotencyKey: crypto.randomUUID() },
);
// nexbasira (Python)
nb.sessions.create(notes="...", idempotency_key=str(uuid.uuid4())) O que vem a seguir
- Erros + limites de taxa — o que acontece quando a paginação ou os ciclos de retentativa correm mal
- API de Sessões — o primeiro endpoint a que aplicar ambos os padrões