Conceitos
Paginação
Como percorrer uma listagem por páginas: o cursor, o tamanho e o ciclo certo.
As listagens devolvem uma página de cada vez, por cursor: em vez de «página 3», a resposta diz a partir de onde continuar. Isto mantém a listagem estável mesmo que apareçam registos novos enquanto a percorre.
| Parâmetro | Sentido |
|---|---|
tamanho | Quantos itens por página, de 1 a 200 (por omissão 50). Fora do intervalo: 400 PEDIDO_INVALIDO. |
cursor | O proximoCursor da página anterior. Omita-o para a primeira página. É opaco: não o construa nem o altere (um cursor inventado dá 400). |
Uma página de 2 clientes
curl 'https://<endereço-da-API>/api/clientes?tamanho=2' \
-H 'X-Api-Key: assw_v1_<chave>'
const resposta = await fetch('https://<endereço-da-API>/api/clientes?tamanho=2', {
method: 'GET',
headers: {
"X-Api-Key": "assw_v1_<chave>"
},
})
const dados = await resposta.json()
import requests
resposta = requests.get(
'https://<endereço-da-API>/api/clientes?tamanho=2',
headers={
'X-Api-Key': 'assw_v1_<chave>'
},
)
dados = resposta.json()
using var cliente = new HttpClient { BaseAddress = new Uri("https://<endereço-da-API>") };
using var pedido = new HttpRequestMessage(HttpMethod.Get, "/api/clientes?tamanho=2");
pedido.Headers.Add("X-Api-Key", "assw_v1_<chave>");
using var resposta = await cliente.SendAsync(pedido);
var texto = await resposta.Content.ReadAsStringAsync();
200 OK Resposta
content-type: application/json; charset=utf-8
x-mucanda-api-version: 1
{
"itens": [
{
"id": "01a12201-fa2a-7eec-8bcb-2f0b5e02bb8e",
"nome": "Ana Beatriz Kiala",
"numeroContribuinte": "004512987LA041",
"telefone": "925112233",
"especial": false,
"saldoAtual": 0,
"isProtegido": false
},
{
"id": "01a12201-fa49-7e89-af00-dde77cab4010",
"nome": "Cantina do Mercado Velho",
"numeroContribuinte": "5417220318",
"telefone": "928667788",
"especial": false,
"saldoAtual": 0,
"isProtegido": false
}
],
"proximoCursor": "Q2FudGluYSBkbyBNZXJjYWRvIFZlbGhvIDAxYTEyMjAxLWZhNDktN2U4OS1hZjAwLWRkZTc3Y2FiNDAxMA=="
}
A resposta tem sempre itens e proximoCursor. Continue enquanto proximoCursor não for null. Uma página que vem cheia traz sempre cursor, mesmo que não haja mais registos: a página seguinte pode vir vazia. Por isso o ciclo termina quando o cursor é null ou a página vem vazia.
async function todosOsClientes() {
const clientes = []
let cursor = null
do {
const url = new URL('https://<endereço-da-API>/api/clientes')
url.searchParams.set('tamanho', '200')
if (cursor) url.searchParams.set('cursor', cursor)
const resposta = await fetch(url, { headers: { 'X-Api-Key': process.env.MUCANDA_API_KEY } })
if (!resposta.ok) throw new Error(`Erro ${resposta.status}`)
const pagina = await resposta.json()
clientes.push(...pagina.itens)
cursor = pagina.itens.length === 0 ? null : pagina.proximoCursor
} while (cursor)
return clientes
}
import os
import requests
def todos_os_clientes():
clientes, cursor = [], None
while True:
params = {'tamanho': 200}
if cursor:
params['cursor'] = cursor
r = requests.get('https://<endereço-da-API>/api/clientes',
params=params, headers={'X-Api-Key': os.environ['MUCANDA_API_KEY']})
r.raise_for_status()
pagina = r.json()
clientes += pagina['itens']
cursor = pagina['proximoCursor'] if pagina['itens'] else None
if not cursor:
return clientes
#Boas práticas
- Use páginas grandes (200) para sincronizações e pequenas para ecrãs.
- Respeite o limite de pedidos: numa importação grande, espere
Retry-Afterquando receber429. - Não guarde cursores durante muito tempo: servem para a listagem em curso, não como marcadores permanentes.
- Para «o que mudou desde ontem», filtre por período nos documentos (
dataInicioedataFim) ou usealteradoDesdenos clientes, fornecedores e artigos (ver Sincronização incremental), em vez de repetir a listagem inteira.