Tema
Sincronização incremental
Para manter uma cópia atualizada das ocorrências sem varrer tudo de cada vez:
GET /occurrences/changes
GET /claims/changesDevolvem os registos que mudaram desde o ponto que indicar — criados, alterados, ou que receberam uma intervenção nova. Cada registo vem completo, com a mesma forma da leitura normal, e não apenas os campos que mudaram.
A resposta
json
{
"Items": [ ... ],
"Cursor": "MTk4NzY1NDMyMQ",
"HasMore": false,
"FullSyncRequired": false
}| Campo | O que é |
|---|---|
Items | Os registos alterados |
Cursor | Onde ficou. Guarde-o: é o que envia da próxima vez |
HasMore | true se ainda há alterações por entregar. Continue já, com o novo cursor |
FullSyncRequired | true quando tem de fazer uma leitura completa antes de continuar |
Começar
Chame sem parâmetros nenhuns:
bash
curl "https://servidor.exemplo/api/integrations/v1/acme/occurrences/changes" \
-H "ApiKey: $GC_API_KEY"json
{
"Items": [],
"Cursor": "MTk4NzY1NDMyMQ",
"HasMore": false,
"FullSyncRequired": true
}fullSyncRequired: true significa: "não sei onde ficaste, por isso não te dou nada. Lê tudo pela listagem normal e depois continua a partir deste cursor."
O cursor entregue corresponde ao estado do sistema naquele instante. Por isso a ordem correta é:
- Chamar
/changessem parâmetros e guardar o cursor - Ler tudo por
/occurrences, página a página - Daí em diante, chamar
/changes?since=<cursor guardado>
Guardar o cursor antes da leitura completa e não depois é o que garante que nada se perde: se algo mudar enquanto está a ler tudo, essa alteração vem na primeira chamada incremental. Pode vir repetida — o que é inofensivo — mas nunca em falta.
Continuar
bash
curl "https://servidor.exemplo/api/integrations/v1/acme/occurrences/changes?since=MTk4NzY1NDMyMQ&limit=200" \
-H "ApiKey: $GC_API_KEY"js
async function sync(state)
{
let cursor = state.cursor
let hasMore = true
while (hasMore)
{
const url = new URL('occurrences/changes', base)
url.searchParams.set('since', cursor)
url.searchParams.set('limit', '200')
const page = await get(url)
if (page.FullSyncRequired)
throw new FullSyncNeeded(page.Cursor)
for (const occurrence of page.Items)
await upsert(occurrence)
//saved on every page, so an interruption resumes exactly here
cursor = page.Cursor
await state.save(cursor)
hasMore = page.HasMore
}
}Guarde o cursor a cada página
Guardando só no fim, uma falha a meio faz recomeçar o ciclo todo. Guardando a cada página, retoma-se exatamente onde parou.
Por data, em alternativa
Se preferir não guardar cursor:
bash
curl "https://servidor.exemplo/api/integrations/v1/acme/occurrences/changes?changedSince=2026-09-25T00:00:00" \
-H "ApiKey: $GC_API_KEY"Devolve o que mudou a partir dessa data e hora, e traz na mesma um cursor que pode passar a usar.
O cursor é preferível. A comparação por data é inclusiva — devolve o que mudou a partir de esse instante, ele incluído. É deliberado: duas alterações no mesmo instante, com uma comparação estrita, fariam a segunda desaparecer. Nada se perde, mas em troca os registos na fronteira voltam sempre a vir na chamada seguinte.
O cursor não tem esse compromisso: é uma posição exata na sequência de alterações, não um instante, e avança sem repetir a fronteira.
Use changedSince para uma leitura pontual, ou quando não quiser guardar estado nenhum entre chamadas.
Um ou outro, nunca os dois
Enviar since e changedSince no mesmo pedido responde 400 CONFLICTING_FILTERS: não haveria como saber qual foi respeitado.
Com que frequência
Depende do que está a construir. Alguns minutos entre chamadas é adequado para quase tudo; segundos é desperdício em ocorrências de condomínio, que não mudam a esse ritmo. Tenha em conta os limites de utilização.
Quando HasMore é true, continue imediatamente — está a recuperar atraso, não a sondar.
O que esperar
Um registo pode vir repetido. Se for alterado duas vezes entre duas sincronizações, vem uma vez; mas uma alteração na fronteira de uma página pode voltar a aparecer. Trate cada entrega como "este é o estado atual deste registo" e escreva por identificador — nunca acumule.
As eliminações não são reportadas. Um registo apagado deixa de aparecer, sem que nada o assinale. Se isso for relevante para si, confirme periodicamente contra a listagem completa.
Os sinistros têm o seu próprio fluxo. /claims/changes e /occurrences/changes são conjuntos disjuntos: um sinistro não aparece nas ocorrências, nem o contrário. Se acompanha os dois, sincronize os dois, cada um com o seu cursor.
Nas empresas com as ocorrências noutro sistema
A sincronização funciona da mesma forma e com os mesmos parâmetros, mas os cursores não são intermutáveis entre sistemas. Se uma empresa mudar de sistema de ocorrências, recomece com uma leitura completa. Ver Ocorrências: GC ou GM.