Eventos de garantia (Escrituração e repasse)

Visão geral

Esta é a documentação de integração da API de eventos de garantia do crédito
consignado CLT: as escriturações (o desconto reconhecido na folha de pagamento) e os
repasses (o dinheiro que o empregador efetivamente transfere). É por ela que o seu
sistema acompanha, mês a mês, se a garantia de cada CCB está se comportando.

O ciclo do consignado CLT

  1. Averbação — o contrato é registrado no empregador, que passa a descontar a parcela
    da folha do trabalhador. É o que transforma o empréstimo em consignado.
  2. Escrituração (BOOKKEEPING) — a folha reconhece o desconto de uma competência. É
    a promessa: o valor foi retido, o empregador deve repassá-lo.
  3. Repasse (TRANSFER) — o dinheiro chega. É o caixa.
  4. Alteração de averbação (ALTER_ANNOTATION) — mudança no vínculo (inclusive o
    encerramento, quando a garantia deixa de existir).

Escriturado não é recebido. Essa é a distinção que a API existe para expor: uma
competência escriturada e não repassada é dinheiro retido do trabalhador que não chegou
ao credor. Toda a conciliação da seção 7 gira em torno disso.

Duas formas de consumir

ModoComo funcionaQuando usar
Consulta (pull)Você chama GET /banking/originator/guarantee-events por CCBConciliação, telas sob demanda, fechamento mensal
Webhook (push)Você expõe uma URL e recebe os eventosReagir na hora (alerta de vínculo encerrado, baixa automática)

Os dois entregam o mesmo evento. A consulta é a fonte de verdade e nunca deve ser
dispensada: webhook perdido acontece (rede, deploy, indisponibilidade do seu listener), e
só a consulta reconcilia o que ficou para trás.

Antes de começar

Credenciais

Você recebe um par client_id / client_secret do seu originador. Ele dá acesso ao
escopo /banking/originator — ou seja, aos dados do seu originador apenas. Consultar
uma CCB de outro originador com a sua credencial não retorna erro: retorna lista vazia.
Não confunda isso com "contrato sem eventos".

Guarde o client_secret como segredo de produção. Ele não é recuperável: se for
perdido, uma nova credencial precisa ser emitida — e a anterior pode ser invalidada.

Ambientes

Ambienteauth_hostapi_host
Homologaçãohttps://sandbox.auth.flowfinance.com.brhttps://sandbox.platform.flowfinance.com.br
Produçãohttps://auth.flowfinance.com.brhttps://platform.flowfinance.com.br

As credenciais não são intercambiáveis entre ambientes.

Ao longo do documento, {auth_host} e {api_host} referem-se à linha correspondente ao
seu ambiente.

Autenticação

OAuth 2.0, fluxo client credentials. O client_id e o client_secret vão no header
Authorization como Basic (base64 de client_id:client_secret), e o corpo carrega apenas
o grant_type.

Requisição:

POST /oauth2/token HTTP/1.1
Host: platform.flowfinance.com.br
Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials

Em curl:

curl -X POST "{auth_host}/oauth2/token" \
  -u "$CLIENT_ID:$CLIENT_SECRET" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials"

Resposta (200):

{
  "access_token": "eyJ4NXQiOiJOVGRtWmpNNFpEazNOalkwWXpjNU...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "api.banking/originator"
}

O access_token vai em todas as chamadas seguintes:

Authorization: Bearer eyJ4NXQiOiJOVGRtWmpNNFpEazNOalkwWXpjNU...

Reaproveite o token até perto do vencimento (expires_in, em segundos) em vez de
autenticar a cada requisição. Uma rotina de conciliação que pede um token por CCB
multiplica a carga sem necessidade.

Consultar eventos de garantia

GET /banking/originator/guarantee-events?contract_number=3911954&page=0&size=25
Authorization: Bearer {access_token}

Parâmetros:

ParâmetroObrigatórioDescrição
contract_numbersimNúmero do contrato (CCB). É o sequential_id da operação
pagenãoPágina, começando em 0
sizenãoTamanho da página. Veja o item 4 da seção 6 — o valor pedido não é honrado

Resposta (200):

{
  "content": [
    {
      "id": "3f2a1c88-5b41-4f0e-9a77-1d0f4e6b2c33",
      "event_type": "BOOKKEEPING",
      "annotation_id": "a7c9e1b4-2f60-4d3a-8e15-90b7c2d41f88",
      "created_at": "2026-07-05T12:00:00Z",
      "payload": {
        "contract_number": "3911954",
        "payload": {
          "contract_number": "3911954",
          "amount": 45.50,
          "consignee_id": "8b2e40d1-77aa-4c19-93de-6f1a08c5b742",
          "agency_id": "0001",
          "created_at": 1751716800,
          "metadata": {
            "period": "202607",
            "loan": { "installment_amount": 93.00 },
            "analytic": {
              "exists_employee_booked": true,
              "exists_contract_number_booked": true,
              "corresponding_data": true,
              "correct_link": true,
              "correct_agency": true,
              "correct_installment_amount": false
            },
            "document": "12345678901",
            "employee_code": "0004512",
            "employer_registration": "0001",
            "employer_number": "12345678000190"
          }
        }
      }
    },
    {
      "id": "9d51b7e0-33c2-4a6f-b8d9-77e4a1c05e26",
      "event_type": "TRANSFER",
      "annotation_id": "a7c9e1b4-2f60-4d3a-8e15-90b7c2d41f88",
      "created_at": "2026-07-20T12:00:00Z",
      "payload": {
        "contract_number": "3911954",
        "payload": {
          "contract_number": "3911954",
          "amount": 93.00,
          "created_at": 1753012800,
          "metadata": { "competence": 202607 }
        }
      }
    }
  ],
  "page": 0,
  "size": 25,
  "total_pages": 3,
  "has_next": true
}

Os três eventos

Todos chegam no mesmo envelope:

Campo do envelopeTipoDescrição
idstringIdentificador único do evento. Use-o para deduplicar
event_typestringBOOKKEEPING, TRANSFER ou ALTER_ANNOTATION
annotation_idstringAverbação a que o evento pertence
created_atstring ISO 8601Quando o evento foi gerado
payloadobjetoConteúdo, com formato próprio por tipo (abaixo)

BOOKKEEPING — escrituração

A folha reconheceu o desconto de uma competência.

{
  "id": "3f2a1c88-5b41-4f0e-9a77-1d0f4e6b2c33",
  "event_type": "BOOKKEEPING",
  "annotation_id": "a7c9e1b4-2f60-4d3a-8e15-90b7c2d41f88",
  "created_at": "2026-07-05T12:00:00Z",
  "payload": {
    "contract_number": "3911954",
    "payload": {
      "contract_number": "3911954",
      "amount": 45.50,
      "consignee_id": "8b2e40d1-77aa-4c19-93de-6f1a08c5b742",
      "agency_id": "0001",
      "created_at": 1751716800,
      "metadata": {
        "period": "202607",
        "loan": { "installment_amount": 93.00 },
        "analytic": { "correct_installment_amount": false, "correct_link": true }
      }
    }
  }
}
CampoCaminhoDescrição
Competênciapayload.payload.metadata.periodString "AAAAMM"
Valor escrituradopayload.payload.amountPode ser uma fatia da parcela (item 5 da seção 6)
Parcela cheiapayload.payload.metadata.loan.installment_amountO valor contratual da parcela
Batimentopayload.payload.metadata.analyticFlags de conferência averbado × folha
Consignatáriopayload.payload.consignee_idTambém pode vir em metadata.consignee_id
Agênciapayload.payload.agency_idIdem

Flags de analytic:

FlagSignifica
exists_employee_bookedO trabalhador foi localizado na folha
exists_contract_number_bookedO contrato foi localizado na folha
corresponding_dataOs dados cadastrais conferem
correct_linkO vínculo empregatício confere
correct_agencyA agência/estabelecimento confere
correct_installment_amountO valor deste evento é a parcela cheia

TRANSFER — repasse

O dinheiro da competência foi transferido.

{
  "id": "9d51b7e0-33c2-4a6f-b8d9-77e4a1c05e26",
  "event_type": "TRANSFER",
  "annotation_id": "a7c9e1b4-2f60-4d3a-8e15-90b7c2d41f88",
  "created_at": "2026-07-20T12:00:00Z",
  "payload": {
    "contract_number": "3911954",
    "payload": {
      "contract_number": "3911954",
      "amount": 93.00,
      "created_at": 1753012800,
      "metadata": { "competence": 202607 }
    }
  }
}
CampoCaminhoDescrição
Competênciapayload.payload.metadata.competenceInteiro 202607 — não é period
Valor repassadopayload.payload.amountPode vir ausente; a presença do evento é o que prova o repasse

ALTER_ANNOTATION — alteração da averbação

Mudança no vínculo. É aqui que aparece o encerramento, o evento mais importante do
ponto de vista de risco.

{
  "id": "c4e08a76-1b93-4d52-a0f7-2e6c9b1d3548",
  "event_type": "ALTER_ANNOTATION",
  "annotation_id": "a7c9e1b4-2f60-4d3a-8e15-90b7c2d41f88",
  "created_at": "2026-07-02T09:00:00Z",
  "payload": {
    "status_contract": "DEACTIVATED_TERMINATED_LINK",
    "metadata": {
      "employer_name": "EMPRESA EXEMPLO LTDA",
      "employee_name": "NOME DO TRABALHADOR",
      "registration": "0004512"
    },
    "contract": { "number": "3911954" }
  }
}
CampoCaminhoDescrição
Situaçãopayload.status_contractPrefixo DEACTIVATED = vínculo encerrado
Empregadorpayload.metadata.employer_nameRazão social
CCBpayload.contract.numberVer item 1 da seção 6

Oito detalhes do formato que derrubam a integração

Esta seção existe porque cada item abaixo custou uma investigação. São comportamentos
verificados contra a API real — vários deles contrariam o que a leitura ingênua do
payload sugere.

1. O número da CCB não está no envelope. Não existe contract_number na raiz do
evento. Ele vive em payload.contract_number e se repete em
payload.payload.contract_number. No ALTER_ANNOTATION pode estar apenas em
payload.contract.number — e esse campo às vezes vale literalmente "N/A". Resolva
tentando, nesta ordem: payload.contract_numberpayload.payload.contract_number
payload.contract.number.

2. BOOKKEEPING e TRANSFER vêm com aninhamento duplo. O conteúdo útil está em
payload.payload; a camada de fora só repete o envelope. O ALTER_ANNOTATION não tem
esse aninhamento — o conteúdo está direto em payload. Um leitor que assume um formato só
perde metade dos eventos.

3. A competência tem nome e tipo diferentes por evento. BOOKKEEPING usa
metadata.period, string ("202607"). TRANSFER usa metadata.competence,
inteiro (202607). Sem normalizar os dois para o mesmo tipo, o repasse nunca casa
com a escrituração — em Python, {"202607": ...} e {202607: ...} são chaves distintas, e
em JavaScript a comparação === falha do mesmo jeito.

4. O size pedido é ignorado. Peça 25, 50 ou 100: a resposta volta sempre com
size: 25. A consequência prática é a armadilha: len(content) < size é sempre
verdadeiro
, então quem pagina por esse teste lê só a primeira página e acha que terminou.
Pagine por has_next.

5. A escrituração de uma competência chega fatiada. Um mesmo mês costuma render vários
BOOKKEEPING, cada um com um pedaço do valor, que somados dão a parcela. Portanto:
compare a soma das fatias com installment_amount, nunca um evento isolado. E arredonde
para centavos antes de comparar — somar floats de oito fatias produz coisas como
392.00000000000006, e a igualdade exata falha.

6. As flags de analytic são por evento, não por competência. Como cada fatia é menor
que a parcela, correct_installment_amount vem false em todas as fatias mesmo quando
a soma fecha exatamente. Se você tratar essa flag como "há divergência", vai gerar alarme
falso em toda competência fatiada. Conclua pela soma; use as flags como pista, não como
veredito.

7. created_at muda de formato conforme o nível. No envelope é ISO 8601
("2026-07-05T12:00:00Z"); dentro do payload é epoch (1751716800), às vezes em
milissegundos. Aceite os três casos ao converter.

8. O metadata carrega dado pessoal. CPF (document), nome (employee_name),
matrícula (registration/employee_code) e identificadores do empregador vêm no evento
cru. Não replique isso em log, em tela de suporte ou em armazenamento sem necessidade
guarde o que a sua conciliação usa e descarte o resto. É LGPD aplicada ao caso mais banal:
um logger.info(payload) num serviço de conciliação.

#

EstadoRegraLeitura
PagaExiste TRANSFER e o repassado ≥ o esperadoO dinheiro chegou
Paga parcialmenteExiste TRANSFER, mas repassado < esperadoChegou menos que a parcela
Aguardando repasseEscriturada, sem TRANSFER, e é a competência escriturada mais recenteNormal. O repasse é defasado
Não repassadaEscriturada, sem TRANSFER, e não é a mais recenteDesconto retido que não chegou
Não escrituradaSem nenhum evento, dentro da janela de descontoO buraco: a folha rodou ao redor e pulou esta
A vencerSem evento, depois da última competência escrituradaAinda não chegou a vez
Sem garantiaSem evento, depois da última escriturada, com o vínculo encerradoNão será descontada: exposição migrou

Erros

StatusSignificadoO que fazer
400Parâmetro inválidoConfira contract_number, page, size
401Token ausente, inválido ou expiradoRenove o token e repita uma vez
403Credencial sem escopo para o recursoA CCB não é do seu originador
404Recurso não encontradoNuma consulta de eventos, prefira interpretar lista vazia como "sem eventos"
429Excesso de requisiçõesBackoff exponencial
5xxFalha do lado da plataformaRetentativa com backoff; não trate como "sem eventos"

Checklist de homologação

Antes de subir a produção, confirme que a sua integração:

  1. Autentica e reaproveita o token até o vencimento.
  2. Pagina por has_next — e foi testada com uma CCB de mais de 25 eventos.
  3. Lê a competência dos dois formatos (period string e competence inteiro).
  4. Resolve o contract_number nos três caminhos possíveis.
  5. Deduplica por id.
  6. Soma as fatias de BOOKKEEPING antes de comparar com a parcela, arredondando para
    centavos.
  7. Não gera alerta a partir de analytic isolado.
  8. Cruza com o cronograma da CCB, não só com os eventos.
  9. Trata DEACTIVATED* por prefixo.
  10. Não registra CPF, nome ou matrícula em log.
  11. Distingue falha do upstream de ausência de eventos.

Glossário

TermoSignificado
AverbaçãoRegistro do contrato junto ao empregador, que autoriza o desconto em folha
CCBCédula de Crédito Bancário — o título do empréstimo
CompetênciaMês de referência da folha, no formato AAAAMM
ConsignatárioInstituição que concede o crédito e recebe o repasse
CronogramaLista de parcelas contratadas, com vencimento e valor
EscrituraçãoReconhecimento, na folha, do desconto de uma competência
Margem consignávelParcela da remuneração que pode ser comprometida com consignado
RepasseTransferência do valor descontado ao consignatário
VínculoRelação de emprego que sustenta a garantia. Encerrado, a garantia deixa de existir