O perfil financeiro reúne as fontes Open Finance de uma mesma PJ (identificada pelo CNPJ) e publica indicadores de caixa e de consumo com a evidência de cada número. Esta página descreve o contrato das rotas da F1. Todos os exemplos usam dados sintéticos do sandbox PJ.
O módulo fica desligado por padrão. Enquanto a chave CONSOLIDATED_INTELLIGENCE_ENABLED estiver desligada, nenhuma rota desta página existe e todas respondem 404. Sem uma versão de cálculo ativa (FINANCIAL_PROFILE_CALCULATION_VERSION), as leituras devolvem result_status: "unavailable" e o pedido de análise responde 503.

O que entra e o que fica fora da F1

Criar o perfil e vincular itens não faz parte das rotas desta fase. Console, eventos de webhook, rota de leitura do histórico de revisões e billing também ficam fora.
A F2 acrescenta carga de títulos do ERP por API e upload CSV (Títulos do ERP, guia CSV), conciliação (Conciliação assistida), diagnóstico de liquidez, sincronização por perfil e alertas (Liquidez e alertas) e eventos de webhook. Previsão de caixa continua fora.

Regras comuns

  • Autenticação: todas as rotas exigem o header X-API-KEY da aplicação. Sem token, a resposta é 403. Um perfil de outra aplicação responde 404 NOT_FOUND, como os demais recursos.
  • Valores: todo valor monetário é string decimal, no padrão da API Contas 2.5.1 (transactionAmount: até 15 dígitos inteiros e de 2 a 4 casas, como "1000.0400"). Nunca é número JSON. Some com tipo decimal: "0.10" + "0.20" = "0.30". Com float64, essa soma não fecha. Moeda segue ^[A-Z]{3}$. O consolidado é em BRL.
  • Instantes: campos como as_of, computed_at e observed_at são UTC com Z, como o transactionDateTime da API Contas.
  • Janela civil: dias e meses são civis em America/Sao_Paulo. O instante 2026-03-01T02:30:00.000Z cai no dia civil 2026-02-28. Toda janela tem início inclusivo e fim exclusivo e termina, no máximo, à meia-noite do dia de referência. O dia corrente fica de fora.
  • Realizado: só movimento com completedAuthorisedPaymentType = TRANSACAO_EFETIVADA entra nos indicadores. LANCAMENTO_FUTURO e TRANSACAO_PROCESSANDO ficam fora, com motivo. A direção vem de creditDebitType (CREDITO é entrada e DEBITO é saída), nunca do sinal do valor.
  • Duas perspectivas: caixa (contas BANK) e consumo (compras de cartão). O pagamento da fatura não entra no consumo. A transferência entre contas da própria PJ é neutralizada.
  • Sem chamada nova à instituição: o cálculo e todas as rotas leem só o banco da Malvo. Nenhuma rota pede saldo, dispara sync ou chama a instituição.
  • Erros: o corpo segue o envelope padrão (code, message, codeDescription, requestId). Veja Erros.

Consentimento diferente de AUTHORISED

Uma fonte só entra no cálculo se estiver vinculada ao perfil, com titularidade comprovada pelo CNPJ e com consentimento AUTHORISED dentro do prazo, com ACCOUNTS_READ e ACCOUNTS_BALANCES_READ. Consentimento REVOKED, EXPIRED, REJECTED, CONSUMED, AWAITING_AUTHORISATION ou vencido deixa a fonte fora, com o motivo consent_not_authorised. Nenhum resultado novo usa essa fonte:
  • Leituras (summary, metrics, evidence, recurrences): o resultado publicado antes da mudança deixa de ser servido. A resposta é 200 sem números, com o motivo e os estados.
  • Análise: se nenhuma fonte for elegível, nada é publicado e o pedido termina em failed com failure_reason: "no_eligible_source". Se o consentimento mudar no meio do cálculo, o pedido vira superseded e um pedido novo é registrado.
  • Revisão de classificação: a rota responde 403 SOURCE_NOT_AUTHORISED e não grava nada.
Leitura depois de revogar o consentimento da única fonte:
Leitura com fonte revogada
A mudança do consentimento registra um recálculo (processing: "queued"). Quando ele termina sem fonte elegível, processing passa a failed. Revisão de classificação de um movimento dessa fonte:
403 SOURCE_NOT_AUTHORISED

Envelope das leituras

summary, metrics, evidence e recurrences começam pelo mesmo envelope: Motivos de fonte excluída: consent_not_authorised, missing_account_permission, holder_under_review e unlinked. Motivos de conta fora do caixa próprio: not_bank_account, unsupported_currency, credit_limit_not_separated, balance_not_observed e invalid_amount.

Análise

POST /financial-profiles/{id}/analyses

Pede um cálculo novo. Não espera o resultado: devolve 202 com o pedido. O cálculo roda em segundo plano e lê só o banco. Existe um pedido pendente por perfil; um pedido novo enquanto outro está pendente devolve o mesmo pedido.
202 Accepted

GET /financial-profiles/{id}/analyses/{analysisId}

Estado do pedido: pending, processing, published, superseded ou failed. Quando publicado, traz data_version e calculation_id. trigger diz a origem: api, sync_finished, source_linked, source_unlinked, consent_changed, revalidation ou classification_revised. A F2 acrescenta profile_sync_cycle, obligation_import, obligation_source_activity e payment_match.
Pedido publicado
Pedido de outro perfil ou inexistente: 404 NOT_FOUND.

Resumo

GET /financial-profiles/{id}/summary

Envelope, caixa próprio disponível e a janela rolling_30d. available_windows lista as janelas que estão em metrics. O caixa próprio disponível soma o último saldo observado das contas BANK em BRL das fontes incluídas. No Open Finance, ele vem do availableAmount da API Contas 2.5.1, que pode ser negativo e não inclui cheque especial, aplicação automática nem reserva. Exemplo: "1000.0400" + "0.2000" = "1000.2400".
summary 200 OK
summary_window.metrics traz as cinco métricas da janela e available_windows lista todas as janelas. O exemplo mostra só parte delas para encurtar.

Métricas

GET /financial-profiles/{id}/metrics?window=&metric=

Envelope, caixa próprio, janelas e séries mensais. window e metric podem se repetir e filtram a resposta. Crédito tomado (OPERACAO_CREDITO) e resgate (RESGATE_APLIC_FINANCEIRA) aparecem na composição das entradas, fora de operational_receipts. Cada métrica traz id, value (string decimal ou null), unit, definition, formula, composition, exclusions (contagem por motivo), quality e evidence_ref. Valor nulo vem com unavailable_reason: insufficient_history, no_cash_source, no_card_source ou no_transactions. Nenhuma lacuna é preenchida. A série mensal tem um ponto por mês. A comparação usa só os dois últimos meses completos (difference_between_complete_months); o mês parcial nunca entra.
metrics 200 OK (trecho depois do envelope)

Evidências

GET /financial-profiles/{id}/evidence?metric=&kind=&decision=&page=&pageSize=

Envelope e a linhagem paginada do resultado publicado: uma linha por fonte (kind: source), por saldo (balance) e por movimento (movement). Filtros: metric (no formato janela.métrica, igual a evidence_ref), kind e decision (included ou excluded). pageSize padrão 20, máximo 500.
evidence 200 OK (trecho depois do envelope)

Recorrências

GET /financial-profiles/{id}/recurrences?status=&flow=&periodicity=

Envelope, parameters, recurrences e discarded. Filtros: status (suggested ou rejected), flow (expense ou receipt) e periodicity. Na v1 só monthly está ligada: mínimo de 3 ocorrências, tolerância de ±5 dias e de ±20% no valor. O grupo combina conta, produto, direção, moeda e contraparte (documento quando identificável; senão, a descrição normalizada). O nível de evidência é regra, não probabilidade: low (3 ocorrências), medium (4 ou 5, ou 6+ com valor variável ou só pela descrição) e high (6+, valor fixo e contraparte identificada). Entrada recorrente não é renda comprovada.
recurrences 200 OK (trecho depois do envelope)
Motivos de descarte: insufficient_occurrences, irregular_pattern, lapsed e no_grouping_key.

POST /financial-profiles/{id}/recurrences/{recurrenceId}/rejections

Rejeita uma recorrência sugerida, com escopo, autoria e versão. A primeira rejeição devolve 201; a mesma rejeição repetida devolve a existente com 200.
Corpo da rejeição
Rejeição 201 Created

Revisão de classificação

POST /financial-profiles/{id}/transactions/{transactionId}/classification-revisions

Troca a natureza de um movimento de conta (perspectiva caixa), com autoria, motivo e versões. A transação de origem não muda: a revisão fica num histórico só de inserção, e a cadeia de versões (0 → 1 → 2) fica inteira.
Corpo da revisão
Revisão 201 Created
Com versão de cálculo ativa, a revisão registra um pedido de recálculo (trigger: classification_revised), e o resultado anterior passa a result_outdated até o novo cálculo. Sem versão ativa, a revisão fica gravada e recalculation_request_id vem null. A revisão exige que a fonte do movimento esteja vinculada e elegível no momento do pedido, com consentimento AUTHORISED dentro do prazo que tenha também ACCOUNTS_TRANSACTIONS_READ, porque a rota lê e altera a classificação de um movimento.

Horário de sync do perfil

GET /financial-profiles/{id}/sync-schedule

Mostra o horário que cada item teria com o sync por perfil e mede quantas execuções a mais isso custaria. A rota só lê: não dispara sync, não pede saldo e não chama a instituição. O sync por perfil fica atrás da chave FINANCIAL_PROFILE_SYNC_SCHEDULE_ENABLED, desligada por padrão. Desligada, cada item segue o próprio horário de hoje (schedule_basis: "item") e o motor de sync não muda. Ligada ou não, o teto continua em três execuções por dia por item (max_daily_runs_per_item: 3). O perfil usa a maior frequência entre os seus itens, sem passar desse teto. Com três execuções por dia, cada conta faz até 93 leituras de saldo num mês de 31 dias, abaixo do piso de 420 chamadas/mês para saldos (Manual de APIs v7.0, seção 5.2, item V). Os horários (slots, no formato HH:MM) estão em UTC (timezone: "UTC"), diferente da janela civil dos indicadores. accounts traz a última posição de cada conta, com o id do saldo e o instante, nunca o valor.
sync-schedule 200 OK
schedule_basis vale item, financial_profile ou auto_sync_disabled. No exemplo, com a chave ligada, o item de frequência 1 passaria a seguir os horários do perfil, com 2 execuções a mais por dia, e o de frequência 3 não mudaria. Na F2, a mesma rota traz também position_at, position_basis e captured_at por conta, a defasagem atual (position_skew), o último ciclo do perfil (cycle) e a política de reexecução (policy). Veja Sincronização por perfil.

Base normativa

  • API Contas, Open Finance Brasil, api_accounts_-_open_finance_brasil/2.5.1.yaml, info.version 2.5.1, lida em 11/10/2026: creditDebitType, completedAuthorisedPaymentType (TRANSACAO_EFETIVADA, LANCAMENTO_FUTURO, TRANSACAO_PROCESSANDO), type, transactionAmount em string decimal, moeda ^[A-Z]{3}$, transactionDateTime em UTC, availableAmount e leitura só com consentimento AUTHORISED.
  • IN BCB nº 615, de 6 de maio de 2025, art. 1º e art. 3º (vigência em 1º de julho de 2025), e Manual de APIs v7.0, seção 5.2, item V: piso de 420 chamadas/mês para saldos. As rotas da F1 não fazem chamada nova.
  • A janela civil em America/Sao_Paulo, as duas perspectivas e a transferência própria são regra de produto da Malvo, não norma do Banco Central. O instante oficial continua o UTC da API Contas.
  • Lei nº 13.709/2018 (LGPD), art. 6º, I e III: a linhagem guarda só o que explica o número, e revisão e rejeição guardam só o identificador do operador.