liquidity no resumo, a sincronização das contas no horário do perfil e
os alertas. Os títulos vêm das cargas do ERP e o ajuste por
pagamento confirmado vem da conciliação assistida.
Chaves do módulo
Todas nascem desligadas.
Sem versão de cálculo ativa (
FINANCIAL_PROFILE_CALCULATION_VERSION), nada é calculado nem avaliado.
Diagnóstico de liquidez
O diagnóstico compara o caixa próprio das contas conectadas com os títulos a pagar do ERP e as obrigações adicionais elegíveis, nos horizontes de 7, 15 e 30 dias:- Caixa próprio: a métrica
own_cash_availableda F1. - Reserva efetiva de um título: o valor em aberto do ERP menos a parte confirmada na conciliação já refletida na posição usada e ainda não absorvida pela origem. Título liquidado ou cancelado reserva zero. A reserva nunca fica negativa.
- Janela: de 00h00 do dia de referência até 00h00 do dia N seguinte, fim exclusivo, em
America/Sao_Paulo. Referência 12/10/2026 e 7 dias: de 12/10 00h00 a 19/10 00h00. Referência
25/02/2026 e 7 dias: fim em 04/03/2026 00h00.
window_startewindow_endsaem em UTC. - Vencidos: vencimento anterior ao dia de referência e reserva maior que zero. Entram em todos os
horizontes, em subtotal próprio (
overdue_reserve), sem mudar de data. - Recebíveis (
receivables,overdue_receivables) e recorrências estimadas (estimated_commitments) aparecem à parte e nunca entram no residual. - Valores são decimais exatos:
1000.0400+0.2000=1000.2400.
Estados por horizonte
Uma insuficiência já demonstrável pode aparecer com limitação. Cobertura favorável (
covered) exige
todas as condições abaixo ausentes.
Carga válida sem títulos a pagar em aberto:
agenda.empty é true e agenda.message é “Nenhum título
em aberto no recorte declarado”, com o source_as_of e a cobertura de cada carga em
agenda.imports. Isso não afirma ausência de dívida.
Bloco liquidity no resumo
GET /financial-profiles/{id}/summary traz liquidity com a chave ligada. O envelope da F1
(financial_profile_id, analysis_id, data_version, calculation_version, computed_at,
bank_position_skew, fontes) continua igual.
Exemplo do PRD: caixa de R 20.000,00 de títulos vencendo em 7 dias e R 6.000,00. R$ 8.000,00 de recebíveis no mesmo
período aparecem à parte e não viram cobertura.
liquidity no resumo (trecho)
agenda.imports[]: a carga usada, comobligation_import_id,import_id,source_system,source_as_ofesource_as_ofefetivo, cobertura, pendências de cadência e coerência com o banco.quality:favorable_allowed,reasons, posições bancárias mais antiga e mais recente,bank_position_skew_secondse os limites (7200segundos de defasagem entre contas e3600de coerência entre ERP e banco).reasonstraz os motivos que valem para todos os horizontes (caixa, posição bancária, carga, cadência, coerência, moeda, valor, sobreposição eagenda_missing), sem repetição e[]quando não há nenhum.favorable_allowedétruesó comreasonsvazio.obligations[]: cada título com a versão considerada (obligation_version_id,source_version), o valor em aberto do ERP e a reserva efetiva lado a lado, ebucket(overdue,within_horizonsouafter_horizons).payment_matches[]:payment_match_id,version,state,allocated_amount,applied_amount,reserve_effect,absorption_basis,position_referenceeposition_at.additional_obligations[]: faturas de cartão com vencimento nos próximos 30 dias. Uma fatura ligada a um título porbank_obligation_referenceconta uma vez.estimated_commitments[]econflicts[](bill_title_overlap,bill_title_amount_mismatch).
A conclusão vale por horizonte: leia
horizons[].state e horizons[].reasons. Motivos de um
horizonte só (coverage_partial, coverage_short_of_horizon, payment_review_pending) não entram em
quality.reasons, então quality.favorable_allowed igual a true não garante covered em todos os
horizontes.Liquidação na origem antes do débito (FR-037)
Quando o ERP registra a baixa antes de a posição bancária refletir o débito, o valor continua reservado. Para cada liquidação dos últimos 7 dias de um título a pagar ativo:bank_debit e método ausente seguem a mesma regra. released_without_debit não conclui que o
pagamento não ocorreu: ele pode ter saído de uma conta não conectada.
Cada alocação confirmada libera no máximo o seu valor alocado, somando todas as liquidações. Primeiro
são liberadas as liquidações que trazem o payment_match_id e cabem no saldo dele, por settled_at
e settlement_id; depois as demais, na mesma ordem, com o saldo restante das confirmações do título.
A liberação é integral ou nenhuma: sem saldo suficiente, a liquidação fica reserved até outra
confirmação ou até toda posição passar de release_after.
A reserva fica em unobserved_settlement_reserve, separada do valor em aberto do ERP, e vale em
todos os horizontes.
unobserved_settlements (trecho)
positions_used não faz parte da resposta: ele só mostra as posições de quality usadas no exemplo.
Com todas as posições às 15h05 UTC ou depois, sem débito, a liquidação passa a
released_without_debit e a reserva volta a zero.
Versão e recálculo
Odata_version inclui a impressão digital da entrada do diagnóstico: cargas ativas, cadência,
títulos, reservas, correspondências, liquidações e faturas. Uma carga nova, a confirmação de
atividade, a perda de atividade e cada decisão de conciliação pedem novo cálculo. Se a entrada mudar
durante o cálculo, o resultado é descartado e o pedido volta para a fila; na leitura, um resultado com
entrada desatualizada sai como result_outdated. O recálculo lê só o banco da Malvo: não chama
instituição nem dispara sincronização.
Sincronização por perfil (FR-036)
ComFINANCIAL_PROFILE_SYNC_SCHEDULE_ENABLED, as contas dos itens vinculados ao perfil sincronizam
nos horários do perfil, derivados do financial_profile_id. Item desvinculado volta aos horários
derivados do próprio id.
- A frequência do perfil é a maior entre os itens, limitada a 3 execuções automáticas por dia por item, somando horários e reexecuções.
- Falha transitória de um item com consentimento válido é reexecutada uma vez, 15 minutos depois,
dentro de até 60 minutos do horário do perfil, se não passar do teto diário. Não há reexecução para
429, consentimento expirado, revogado ou que precise de novo consentimento. - Cada horário abre um ciclo. O ciclo fecha quando todas as contas
BANKreceberam saldo depois do horário (close_reason: "all_accounts") ou após 90 minutos (timeout). No fechamento, a Malvo pede novo cálculo e publicafinancial_profile.bank_position_updated. - A posição de cada conta é o
updateDateTimedo saldo da API Contas. A defasagem do perfil é a posição mais recente menos a mais antiga. Acima de 2 horas, o diagnóstico não conclui cobertura. Posições às 08h00 e 10h30 dão 2h30 (9000 segundos): fora do limite. Exatamente 2 horas ainda está dentro.
GET /financial-profiles/{id}/sync-schedule (rota da F1)
passa a trazer a posição de cada conta, a defasagem atual, o último ciclo e a política de reexecução:
sync-schedule na F2 (trecho)
position_basis é update_date_time quando o provedor informa a posição, ou captured_at quando
não informa; contas assim são contadas em accounts_without_provider_position. cycle é null
antes do primeiro ciclo. Nenhum valor de saldo aparece nesta rota.
Alertas financeiros
Não há percentual padrão:
receipts_drop, recurring_expense_increase e due_concentration só
avaliam depois que a aplicação ou o perfil configura o limite. A severidade do cash_shortfall segue
o horizonte: high em 7 dias, medium em 15 e low em 30.
Ciclo de vida
- Abertura:
financial_alert.opened. Há no máximo um alerta ativo por regra e perfil. - Atualização: mudança de estado ou de evidência sai na hora (
financial_alert.updated). Mudança só de valores espera 24 horas desde a última notificação, salvomaterial_worsening_percentconfigurado e atingido. A versão nova fica consultável desde o início. - Recuperação mínima: quando a condição some com uma observação mais nova, o alerta fica aberto com
clear_sincee só é resolvido depois de 24 horas sem a condição. - Retratação: confirmação, reversão ou absorção de correspondência, reclassificação ou título
corrigido na mesma posição que invalidam o alerta geram
financial_alert.retractedcomreason: "invalidated_by_correction"eretractsapontando a versão invalidada. - Revogação da fonte: quando uma fonte usada pelo alerta perde autorização, o alerta ativo é
retratado com
reason: "source_revoked", sem severidade e sem conteúdo da fonte. Veja Fonte sem autorização. - Reconhecer não muda a condição. Silenciar adia as atualizações por até 30 dias; resolução e retratação são sempre entregues.
GET /financial-profiles/{id}/alerts?status=&rule=&page=&pageSize=
Alertas do perfil, ativos primeiro. families lista as famílias ligadas.
Alertas 200
condition.measures traz os valores como string decimal. evidence lista o que sustenta a condição
(obligation_import, obligation, payment_match, settlement, bank_position, metric_month,
recurrence, source) com a versão quando houver. basis guarda a posição bancária e o
source_as_of usados, para distinguir recuperação (dado mais novo) de retratação (correção).
source_authorization vem sempre: authorized ou unauthorized (veja
Fonte sem autorização).
GET /financial-profiles/{id}/alerts/{alertId}
O alerta, history (todas as versões, da mais antiga para a mais nova, com o evento e o event_id
de cada notificação) e actions.
Alerta com histórico 200
T-1010 para 14000.00 numa carga com o mesmo
source_as_of, e a posição bancária também não mudou. O residual vai a zero sem dado mais novo: o
alerta é retratado, não resolvido. As fontes continuam autorizadas, então a retratação mantém a
severidade e a condição avaliada. As versões do histórico foram resumidas (measures e evidence
vazios) para caber na página.
Fonte sem autorização
source_authorization diz se o conteúdo do alerta pode ser lido:
Com
unauthorized, a listagem, o detalhe e todas as versões de history saem com severity: null
e a condição bloqueada: reasons: ["source_not_authorized"], measures e evidence vazios, basis
com bank_position_at e source_as_of nulos e sem severity nem window. rule, category,
state, datas, acknowledged e actions continuam visíveis. Isso vale também para alertas já
resolvidos ou retratados antes da revogação.
Na revogação, cada alerta ativo (open, suspended ou under_review) que usa a fonte ganha uma
versão nova retracted com reason: "source_revoked", sem analysis_id na versão, e publica
financial_alert.retracted com o mesmo conteúdo bloqueado. Alertas já resolvidos ou retratados não
geram evento novo. A distribuição dos eventos antigos está em
Eventos financeiros.
Alerta com fonte revogada 200
high e insuficiência de 6000.00, mas a leitura não mostra mais esses
valores. Ao receber source_revoked, apague o que guardou das versões anteriores do alerta.
POST /financial-profiles/{id}/alerts/{alertId}/acknowledge
Reconhece a versão atual. Corpo {actor, reason?} e header Idempotency-Key. Reconhecer não muda
o estado do alerta. A resposta 200 é o alerta com histórico, no formato do GET.
Reconhecer
POST /financial-profiles/{id}/alerts/{alertId}/silence
Silencia até until, no máximo 30 dias. Corpo {actor, reason, until} e header Idempotency-Key.
As atualizações ficam adiadas; resolução e retratação continuam sendo entregues.
Silenciar
POST /financial-profiles/{id}/alerts/{alertId}/unsilence
Retira o silêncio. Corpo {actor, reason?} e header Idempotency-Key.
Retirar silêncio
409 ALERT_STATE_CONFLICT
Regras por aplicação e por perfil
Os parâmetros da aplicação valem para todos os perfis. O perfil sobrepõe campo a campo. Mudar uma regra pede a revalidação dos perfis afetados.GET /financial-profile-alert-rules
Parâmetros da aplicação de cada regra e se a família está ligada. results traz um item por regra,
nas cinco regras; os exemplos mostram só cash_shortfall. Parâmetro não configurado não aparece.
Regras da aplicação 200 (trecho)
PUT /financial-profile-alert-rules/{rule}
Grava os parâmetros da aplicação para a regra. actor é obrigatório. A resposta 200 é a regra
atualizada.
Parâmetros da aplicação
DELETE /financial-profile-alert-rules/{rule}
Volta a regra aos padrões. Responde 204 sem corpo.
GET /financial-profiles/{id}/alert-rules
Parâmetros da aplicação, do perfil e o efetivo.
Regras do perfil 200 (trecho)
PUT /financial-profiles/{id}/alert-rules/{rule}
Grava a sobreposição do perfil. A resposta 200 é a regra com o efetivo.
Parâmetros do perfil
DELETE /financial-profiles/{id}/alert-rules/{rule}
Remove a sobreposição do perfil. Responde 204 sem corpo.
409 ALERT_FAMILY_DISABLED
Eventos
Análise, qualidade, posição bancária, alertas e correspondências publicam eventos de webhook com identidade estável e versão de schema. O payload, a idempotência e a assinatura estão em Eventos financeiros.Base normativa
- API Contas do Open Finance Brasil 2.5.1
(
api_accounts_-_open_finance_brasil/2.5.1.yaml, lido em 12/10/2026):AccountBalancesData.updateDateTime(UTC, “a última vez que capturou o saldo”) como posição usada na defasagem, na reserva e na liberação;creditDebitType = DEBITOecompletedAuthorisedPaymentType = TRANSACAO_EFETIVADApara o débito correspondente;amountcom até 4 casas. - IN BCB nº 615, de 6/5/2025, art. 1º e 3º, vigência a partir de 1º/7/2025, e Manual de APIs do Open Finance Brasil v7.0, seção 5.2, item V: o sync por perfil não passa de 3 execuções automáticas por dia por item; diagnóstico, alertas e recálculos não chamam instituição.
- Contrato
obligations.v1(Títulos do ERP — contrato v1):settlement_method,payment_match_idebank_obligation_reference. - Lei nº 13.709/2018 (LGPD), art. 6º, 7º, 15, 16 e 18, e a política de retenção da Malvo aprovada em 10/10/2026.
- PRD v1.3, seções 10, 11, 14 e 17 (FR-016 a FR-023, FR-031, FR-036 e FR-037). Janela civil com fim exclusivo, tolerância de lançamento de 2 horas, defasagem máxima de 2 horas, coerência de 1 hora e repetição de alerta em 24 horas são regras de produto, sem norma externa.