Skip to content

Sincronização incremental ​

Para manter uma cópia atualizada das ocorrências sem varrer tudo de cada vez:

GET /occurrences/changes
GET /claims/changes

Devolvem 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
}
CampoO que é
ItemsOs registos alterados
CursorOnde ficou. Guarde-o: é o que envia da próxima vez
HasMoretrue se ainda há alterações por entregar. Continue já, com o novo cursor
FullSyncRequiredtrue 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 é:

  1. Chamar /changes sem parâmetros e guardar o cursor
  2. Ler tudo por /occurrences, página a página
  3. 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.

API de Integração GC