Esta página completa o contrato da F1 com o que a F2 acrescenta ao perfil financeiro: o bloco 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.
O diagnóstico descreve os dados vinculados ao perfil, não a solvência da empresa. A Malvo não altera o saldo bancário, não dá baixa no ERP e não soma recebíveis à cobertura. Todos os exemplos usam dados sintéticos.

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_available da 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_start e window_end saem 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 R18.000,00,R 18.000,00, R 20.000,00 de títulos vencendo em 7 dias e R4.000,00vencidosemabertoda~oinsuficie^nciaconservadoradeR 4.000,00 vencidos em aberto dão insuficiência conservadora de 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, com obligation_import_id, import_id, source_system, source_as_of e source_as_of efetivo, 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_seconds e os limites (7200 segundos de defasagem entre contas e 3600 de coerência entre ERP e banco). reasons traz os motivos que valem para todos os horizontes (caixa, posição bancária, carga, cadência, coerência, moeda, valor, sobreposição e agenda_missing), sem repetição e [] quando não há nenhum. favorable_allowed é true só com reasons vazio.
  • 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, e bucket (overdue, within_horizons ou after_horizons).
  • payment_matches[]: payment_match_id, version, state, allocated_amount, applied_amount, reserve_effect, absorption_basis, position_reference e position_at.
  • additional_obligations[]: faturas de cartão com vencimento nos próximos 30 dias. Uma fatura ligada a um título por bank_obligation_reference conta uma vez.
  • estimated_commitments[] e conflicts[] (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

O data_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)

Com FINANCIAL_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 BANK receberam saldo depois do horário (close_reason: "all_accounts") ou após 90 minutos (timeout). No fechamento, a Malvo pede novo cálculo e publica financial_profile.bank_position_updated.
  • A posição de cada conta é o updateDateTime do 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.
Sincronizar no mesmo horário não garante posições simultâneas: latência do provedor e falhas individuais continuam possíveis e aparecem na defasagem. 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, salvo material_worsening_percent configurado 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_since e 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.retracted com reason: "invalidated_by_correction" e retracts apontando 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
No exemplo, o ERP corrigiu o valor do título 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
No exemplo, o consentimento da única fonte bancária do perfil foi revogado às 14:00 (UTC). A versão 1 foi aberta com severidade 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 = DEBITO e completedAuthorisedPaymentType = TRANSACAO_EFETIVADA para o débito correspondente; amount com 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_id e bank_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.