Reconciliação de documentos e eventos CT-e

Os endpoints de documentos (/inbound/documentos) e eventos (/inbound/eventos) operam de forma independente. O client consome cada um em seu próprio loop de…

How-to Guide — Este documento orienta o integrador na construção da lógica de reconciliação entre documentos e eventos CT-e inbound consumidos via API REST.


1. Introdução

Os endpoints de documentos (/inbound/documentos) e eventos (/inbound/eventos) operam de forma independente. O client consome cada um em seu próprio loop de polling, com tokens e filtros separados. No entanto, documentos e eventos estão relacionados: um evento de cancelamento, por exemplo, só faz sentido quando associado ao CT-e que ele cancela.

A reconciliação é a lógica no lado do client que conecta esses dois fluxos. Como a ordem de chegada é imprevisível — um evento pode chegar antes do documento correspondente, e vice-versa — o client precisa lidar com ambos os cenários de forma resiliente.


2. Pré-requisitos


3. Visão geral do modelo

O client mantém dois loops de polling independentes, cada um com seu próprio nextToken e filtros. Ambos os loops gravam os registros recebidos na base local. A reconciliação acontece após cada gravação, usando a chave de acesso como elo de ligação.

┌──────────────────────┐       ┌──────────────────────┐
│  Loop de Documentos  │       │   Loop de Eventos    │
│  /inbound/documentos │       │  /inbound/eventos    │
└────────┬─────────────┘       └────────┬─────────────┘
         │                              │
         ▼                              ▼
   Salva documento              Salva evento
   na base local                na base local
         │                              │
         ▼                              ▼
   Busca eventos pendentes      Busca documento
   pela chave de acesso         pela chave de acesso
         │                              │
         ▼                              ▼
   Encontrou?                   Encontrou?
   ├─ Não → fim                 ├─ Não → fim
   └─ Sim → reconcilia         └─ Sim → reconcilia

Chave de acesso

A chave de acesso é o identificador que conecta um documento ao(s) seu(s) evento(s):

OrigemCampo
Documento (/inbound/documentos)metadata.chCte (também exposto na raiz do item como chCte)
Evento (/inbound/eventos)metadata.chCTe

Os dois campos têm exatamente o mesmo valor e formato (44 posições, sem prefixo) — diferente da NFS-e, onde o id do documento carrega um prefixo ("NFS...") que não bate literalmente com o infEvento.id do evento (lá, a correlação correta é id do documento vs infPedReg.chNFSe do evento, ambos sem prefixo).

Multiplicidade por empresa: tanto o documento quanto os eventos de um mesmo CT-e podem aparecer mais de uma vez — uma linha por (companyId, chCte) — quando várias empresas do tenant são partes do transporte (tomador, destinatário, etc.). Reconcilie por (companyId, chCte), não apenas por chCte, para não cruzar o evento de uma empresa com o documento de outra.

O client deve indexar sua base local por (companyId, chCte) para permitir buscas eficientes durante a reconciliação.


4. Ao receber um documento

Quando o loop de documentos retorna um novo item:

  1. Salvar o documento na base local, independentemente de já existirem eventos associados.
  2. Buscar na base local todos os eventos cujo (companyId, chCTe) corresponda ao (companyId, chCte) do documento recém-salvo.
  3. Se nenhum evento for encontrado, encerrar o processamento deste item. Os eventos podem ainda não ter chegado — serão reconciliados quando o loop de eventos os consumir.
  4. Se um ou mais eventos forem encontrados, associar cada evento ao documento e executar a ação correspondente ao tipo de evento (tpEvento). Por exemplo, se um evento de cancelamento for encontrado, marcar o documento como cancelado na base local.

5. Ao receber um evento

Quando o loop de eventos retorna um novo item:

  1. Salvar o evento na base local, independentemente de o documento associado já existir.
  2. Buscar na base local o documento cujo (companyId, chCte) corresponda ao (companyId, chCTe) do evento recém-salvo.
  3. Se o documento não for encontrado, encerrar o processamento deste item. O documento pode ainda não ter chegado — será reconciliado quando o loop de documentos o consumir.
  4. Se o documento for encontrado, associar o evento ao documento e executar a ação correspondente ao tipo de evento. Por exemplo, se for um evento de cancelamento, marcar o documento como cancelado na base local.

6. Considerações

Ordem de chegada imprevisível

Não há garantia de que o documento chegará antes dos seus eventos, nem o contrário. O client deve tratar ambos os cenários com a mesma lógica: salvar primeiro, reconciliar depois.

Idempotência

A lógica de reconciliação deve ser idempotente. Se o mesmo par documento-evento for reconciliado mais de uma vez (por exemplo, após uma reinicialização do client), o resultado final deve ser o mesmo. Isso significa que marcar um documento como cancelado duas vezes não deve gerar efeitos colaterais indesejados.

Múltiplos eventos por documento

Um CT-e pode acumular vários eventos ao longo do tempo (ex.: carta de correção seguida de cancelamento, ou comprovante de entrega seguido de sua própria cancelamento). Use nSeqEvento e tpEvento para ordenar e desduplicar eventos do mesmo tipo, em vez de assumir que o documento só recebe um evento.

Eventos sem documento

É possível que um evento permaneça sem documento associado por um período prolongado — por exemplo, se o documento ainda não foi processado pela API ou se o client iniciou o consumo de eventos com um createdFrom anterior ao dos documentos. O client deve tratar eventos não reconciliados como estado normal, não como erro.

Documentos sem evento

Nem todo documento terá eventos associados. Um CT-e que nunca foi cancelado, corrigido ou sofreu qualquer ação posterior simplesmente não terá eventos. A ausência de eventos para um documento é o cenário padrão.

Nesta página