O saldo que se prova | Conciliar por evento e por período até fechar com o extrato

GuiaUNIFOKAL7 min de leituraProduto e integração
Ver em Markdown

Saldo de API pré-paga que não se reconstrói pelos lançamentos é opinião. Como casar o custo de cada evento com o extrato do período, pela mesma chave, sem duplicar na reimportação.

Toda empresa que compra verificação de identidade por crédito pré-pago chega, cedo ou tarde, à mesma reunião: o financeiro tem o valor da recarga, o painel mostra um saldo, o time de produto diz quantas verificações rodaram no mês, e os três números não conversam. Ninguém está mentindo. O que falta é a ponte entre eles, a capacidade de pegar qualquer saldo e reconstruí-lo, centavo por centavo, a partir dos lançamentos que o produziram.

Saldo que não se reconstrói é opinião. Saldo que fecha com o extrato é prova. Este guia descreve as duas réguas de conciliação que uma API (interface de programação de aplicações) cobrada por uso precisa oferecer, por evento e por período, a chave que casa as duas e as diferenças que aparecem no fechamento, com o lugar onde cada uma costuma morar.

O saldo é consequência, não registro

O princípio é o do extrato bancário: saldo inicial, mais as entradas, menos as saídas, é igual ao saldo final. Um sistema que guarda só o saldo atual, sem os lançamentos que o formaram, não tem como responder "por que o saldo é esse". Um sistema que guarda cada lançamento com o saldo depois dele consegue responder qualquer pergunta sobre qualquer ponto do tempo.

A referência de mercado mostra o formato. A documentação da Stripe descreve o relatório de resumo do saldo como algo que "funciona como um extrato bancário, ajudando a reconciliar seu saldo da Stripe no final de cada mês", e a seção de resumo "mostra o saldo inicial e final da Stripe do intervalo de datas selecionado", junto com o resumo da atividade do período. A conta que o relatório entrega é exatamente a do parágrafo anterior, e ela só fecha porque cada transação está lá para ser somada.

Quando cada linha do extrato traz também o saldo depois dela, a conferência ganha uma segunda trava: além de a soma do período fechar, cada linha precisa ser o saldo da linha anterior mais o valor dela. Uma linha que quebra essa sequência aponta o lugar exato da divergência, em vez de deixar só um total errado no fim do mês.

Duas réguas: por evento e por período

A conciliação por evento acontece no momento em que o fato ocorre. A verificação termina, o webhook chega, e ele traz quanto aquela verificação custou. Quem guarda esse valor junto do próprio registro, na hora, tem o custo de cada cliente final sem precisar consultar nada depois.

A conciliação por período acontece no fechamento. O financeiro exporta o extrato do mês e precisa que ele bata com o que o sistema do cliente acumulou evento a evento. As duas réguas medem a mesma coisa por caminhos independentes, e é por isso que uma confere a outra.

O período tem armadilhas próprias, e a doc da Stripe descreve duas. A primeira é o fuso: a Stripe agrupa a atividade "por dia civil no fuso horário selecionado para o relatório", então o mesmo lançamento das 23h30 pode cair em dias diferentes conforme o fuso escolhido. A segunda é a data: o relatório distingue a data em que a transação "começa a afetar seu saldo" da data em que o valor fica disponível. Fechamento que não declara qual fuso e qual data usa produz diferença que ninguém consegue explicar depois. A regra prática é fixar as duas por escrito e usar as mesmas no seu sistema.

A chave que casa as duas réguas

As duas réguas só conversam se compartilham uma chave. O evento precisa trazer o identificador da operação que gerou o custo, e cada linha do extrato precisa trazer o mesmo identificador. Com isso, a soma das linhas do extrato com a mesma chave é o custo informado pelo evento daquela operação, com a convenção de sinal que o extrato adota.

Os lançamentos que não nascem de uma verificação, como uma recarga ou uma consulta avulsa, precisam de chave própria, senão viram resíduo inexplicável no fim do mês. E cada linha precisa de um identificador único dela, que não se repete. É esse identificador que torna a importação segura.

A RFC 9110 (Request for Comments) do IETF (Internet Engineering Task Force) considera idempotente o método de requisição em que o efeito pretendido no servidor de várias requisições idênticas com esse método "é o mesmo que o efeito de uma única" requisição. A definição é sobre métodos HTTP (protocolo de transferência de hipertexto), mas a propriedade é a que a importação do extrato precisa ter: importar o mesmo período duas vezes, ou dois períodos que se sobrepõem, tem de produzir o mesmo estado que importar uma vez. Com um identificador único por linha e uma restrição de unicidade no seu banco, a reimportação vira operação sem risco. O raciocínio completo, com a chave do lado de quem chama, está no artigo sobre idempotência em APIs.

Na UNIFOKAL, por exemplo, o evento de verificação concluída traz o custo debitado e o saldo restante, e o extrato em CSV (valores separados por vírgula) traz uma linha por lançamento, com o identificador da verificação e um identificador único por linha. O passo a passo da conciliação está na documentação de webhooks.

Onde mora a diferença quando não fecha

Quando as réguas divergem, a diferença costuma ter endereço conhecido, e vale procurar nesta ordem.

O evento que não chegou. Uma política de retentativa de webhook tem fim, então um evento perdido deixa um custo no extrato sem par no seu sistema. A correção é a rotina de reconciliação de webhook, que consulta o estado canônico das operações pendentes, e não a soma manual.

O custo que chega depois da chamada. A RFC 9110 define o status 202 como o de uma requisição "aceita para processamento, mas o processamento não foi concluído". Uma verificação assíncrona aceita às 23h59 pode gerar o débito no dia seguinte, e o fechamento que conta pela data da chamada erra o dia. O mesmo descompasso aparece no controle de gasto, e o artigo sobre teto de gasto diário em uma API de verificação trata dele do lado do limite.

O corte do período. Fuso diferente, data diferente, ou um extrato exportado antes de o dia estar completo. A própria Stripe informa que os dados completos de cada dia ficam disponíveis até as 12h do dia seguinte, no fuso escolhido, e que os relatórios do painel incluem apenas dias completos.

O sinal. No extrato, o que sai costuma ser negativo; no evento, o custo costuma vir positivo. Somar sem inverter dobra a diferença em vez de zerá-la.

Um roteiro de fechamento que se repete

O fechamento que não depende de heroísmo tem cinco passos fixos. Primeiro, exporte o extrato do período depois que o último dia estiver completo, no fuso combinado. Segundo, importe por identificador de linha, com unicidade no banco. Terceiro, confira a sequência: saldo inicial mais a soma do período igual ao saldo final, e cada linha igual à anterior mais o próprio valor. Quarto, agrupe as linhas pela chave da operação e compare com o custo que você guardou evento a evento. Quinto, classifique cada divergência por endereço, evento ausente, corte de período ou sinal, e registre a correção.

A divergência que sobra depois dos cinco passos é a que merece chamado com o fornecedor, e ela chega ao chamado já com a chave da operação, a linha do extrato e o evento do seu lado. As outras se explicam com os dados que você já tem.

Perguntas frequentes

Posso conciliar só pelo extrato, sem guardar o custo de cada evento?

Pode, mas perde a régua independente. O extrato sozinho diz quanto saiu; o custo guardado no evento diz para qual cliente final e em qual operação do seu sistema. Sem os dois, uma diferença no total não tem onde ser procurada.

Por que reimportar o extrato não pode duplicar lançamentos?

Porque o fechamento real é iterativo: exporta-se o mês, corrige-se, exporta-se de novo com o período ajustado. Se cada importação somar linhas que já estavam lá, o saldo do seu lado cresce a cada tentativa. Um identificador único por linha resolve isso na raiz.

Fontes citadas

  • IETF, RFC 9110, HTTP Semantics, seção 9.2.2 (Idempotent Methods) e seção 15.3.3 (202 Accepted), junho de 2022: rfc-editor.org
  • Stripe, Relatório resumido do saldo, documentação oficial, lida em 1º de outubro de 2026: docs.stripe.com