# Análise de crédito

<https://unifokal.com/docs/modulos/credito>

## Análise de crédito

Cinco módulos consultam a situação de crédito do **CPF lido do documento**: `credito_dividas` (dívidas e negativações), `credito_scr` (SCR do Banco Central), `credito_boavista` (Boa Vista SCPC), `credito_protestos` (protestos Cenprot) e `credito_cadin` (CADIN). Exigem Verificação de Identidade, Face Match e Liveness, pela mesma razão dos cadastrais: o CPF consultado vem do documento, e o documento tem que pertencer a quem está vivo na frente da câmera.

O sexto, `credito_pgfn` (Dívida Ativa da União), é de **empresa**: ele consulta o **CNPJ lido do documento societário** e por isso exige apenas o `cnpj_ocr` no flow, sem biometria, porque empresa não tem rosto. A fonte dele não é fornecedor: é o **dado aberto oficial** que a PGFN publica e atualiza **trimestralmente**, ingerido na nossa base. Cada resposta carimba a **competência publicada** do arquivo que respondeu, para você saber a que mês ela se refere.

**Venda pausada hoje**: os **cinco** de CPF aparecem na tabela de preços e no `GET /v1/capabilities` com preço e status `coming_soon`, e não podem ser ligados num flow enquanto a fonte não for liberada na conta do fornecedor. O `credito_pgfn` saiu dessa fila em 11 de setembro de 2026 e viaja como `available`. O estado vem do catálogo vivo, e esta página acompanha.

**Os cinco de CPF pedem finalidade, relação e consulente**, como a Lei 12.414/2011 manda para dado de crédito. A **finalidade** é do flow: ao montá-lo no painel você declara `credit_purpose`, `analise_risco_credito` ou `concessao_credito` (art. 7º). A **relação** com o titular vai em cada sessão, no campo `credit_relationship` do `POST /v1/verification-sessions`: `mantem` ou `pretende_manter` (art. 15). O **consulente** é a sua empresa, e por isso a conta precisa ter o CNPJ cadastrado e verificado. A consulta só sai com a identidade aprovada, e cada uma fica registrada com a finalidade, a relação e o consulente. O `credito_pgfn` não passa por esse portão.

```
// sessão num flow com módulo de crédito
{ "flow_id": "flow_...", "reference_id": "cliente-4821", "credit_relationship": "mantem" }

// os 422 do portão, cada um com a prosa na página de erros:
//   credit_relationship_required       flow com crédito e a chamada sem credit_relationship
//   credit_relationship_not_supported  credit_relationship num flow sem módulo de crédito
//   credit_purpose_required            flow com crédito que não declara a finalidade
//   credit_consulente_unverified       a conta ainda sem CNPJ cadastrado e verificado
```

São **informacionais**: ter dívida **não reprova a identidade** (o pass/fail é 100% biometria). Os cinco de CPF são **assíncronos** na fonte: o dossiê pode chegar num `verification.completed` posterior, quando a consulta conclui. Enquanto processa, o módulo aparece como `pending` **sem a chave** `data`; concluído, o `data` traz o dossiê do pacote. Se a fonte não concluir na janela, o módulo termina como indisponível e **não é cobrado**.

O `credito_pgfn` responde da **nossa base**, na mesma verificação, e não tem esses dois tempos. Em troca ele carrega a **competência** do arquivo do governo que respondeu, em `competencia` e `atualizado_em`, mais a `cobertura` por fonte. Quando a base está vencida ou incompleta, ele sai como `pending` com o motivo e **não é cobrado**: um **nada consta** só é emitido com a base inteira dentro do prazo. Achado positivo, ao contrário, é devolvido mesmo com cobertura incompleta, porque **consta** continua verdadeiro.

**Sem dossiê, a chave `data` não vem `null`: ela não existe.** Vale enquanto a fonte processa, quando ela não responde na janela e quando o documento não é encontrado. Um leitor que testa `check.data === null` não pega nenhum desses casos: teste a **presença** da chave, e ramifique por `outcome`.

Aqui o `data` **é** o dossiê da fonte, sem envelope nenhum: não há `flagged`, não há `matched_by`, não há bloco nosso em volta. Valem as mesmas duas regras da [consulta cadastral](https://unifokal.com/docs/modulos/cadastrais#modulos-cadastrais): tiramos só `pacoteUsado`, `saldo` e `consultaID`, e **o conjunto de chaves é o do pacote**, não uma lista fechada nossa. Todo dossiê traz o bloco comum `status`, `estado`, `cpf` e `nome`, e os dois primeiros enganam: `status` é o indicador de sucesso da **chamada** (nunca a situação do titular) e `estado` é o estágio do **processamento** (`"concluido"`; a primeira chamada da fonte real pode responder `"processando"`, que tratamos como indisponibilidade temporária). Os valores em dinheiro vêm em **reais com decimais**, e não em centavos como os saldos do topo do webhook.

As duas regras do parágrafo acima valem para os **cinco** de CPF, que repassam o dossiê do fornecedor. O `credito_pgfn` é a exceção nas duas: o payload dele é nosso, então não existe o bloco comum `status`, `estado`, `cpf` e `nome`, e o dinheiro sai em **centavos inteiros**, em `valor_total_centavos`.

```
// credito_dividas: dossiê concluído (informacional, não reprova)
{ "module": "credito_dividas", "passed": true, "outcome": "approved", "score": 100,
  "data": { "score": 742, "classe": "B", "renda_presumida": 4200.5, "possui_debitos": true,
            "total_negativado": 1234.56,
            "negativacoes": [ { "credor": "BANCO EXEMPLO S.A.", "valor": 1234.56,
                                "data": "2026-03-10", "tipo": "Pendencia financeira" } ] } }

// credito_pgfn: Dívida Ativa da União do CNPJ, da NOSSA base do dado aberto da PGFN.
// Os três papéis vêm separados: corresponsável costuma ser dívida de OUTRA empresa.
// Valor em CENTAVOS aqui (só este módulo), e sem número de inscrição: a base agrega
// por documento e por papel. "competencia" é o mês do arquivo publicado pelo governo,
// e é a MAIS ANTIGA entre as fontes que responderam: o carimbo é o do elo mais velho.
{ "module": "credito_pgfn", "passed": true, "outcome": "approved", "score": 100,
  "data": { "fonte": "pgfn_dados_abertos", "documento": "cnpj",
            "fonte_oficial": "Divida Ativa da Uniao, dado aberto oficial da PGFN",
            "competencia": "202606", "atualizado_em": "2026-09-02T03:14:00.000Z",
            // uma entrada POR LIVRO da PGFN. "status" é um destes sete: "consultada",
            // "desabilitada", "nunca_ingerida", "ingestao_vencida", "competencia_vencida",
            // "vazia" (ingeriu e veio sem linha) e "ausente" (o livro nem está na base).
            // SÓ "consultada" conta como olhada: qualquer outro degrada a resposta para
            // pending, com o motivo, e a checagem não é cobrada. "ingerida_em" é quando
            // NÓS ingerimos aquele livro, e não a competência dele: os dois são diferentes
            // e confundi-los é ler frescor de ingestão como frescor de dado.
            // A cobertura vem ORDENADA POR fonte, sempre, e nao na ordem de tamanho dos livros:
            // ordem estavel e o que permite comparar duas respostas sem reordenar.
            "cobertura": [ { "fonte": "pgfn_fgts", "livro": "FGTS", "status": "consultada",
                             "competencia": "202606",
                             "ingerida_em": "2026-09-02T01:12:00.000Z", "registros": 541698 },
                           { "fonte": "pgfn_prev", "livro": "PREV", "status": "consultada",
                             "competencia": "202606",
                             "ingerida_em": "2026-09-02T01:40:00.000Z", "registros": 3606529 },
                           { "fonte": "pgfn_sida", "livro": "SIDA", "status": "consultada",
                             "competencia": "202606",
                             "ingerida_em": "2026-09-02T03:14:00.000Z", "registros": 45553971 } ],
            // "situacoes" conta a SITUACAO_INSCRICAO (INSCRITA, AJUIZADA, PARCELADA...) e
            // "tipos_situacao" conta o TIPO_SITUACAO_INSCRICAO ("Em cobranca", "Garantia",
            // "Suspenso por decisao judicial", "Em negociacao", "Beneficio Fiscal"). São
            // eixos diferentes: exigibilidade suspensa por juiz não é inadimplência, e
            // reportar as duas do mesmo jeito seria menos honesto. "livros" diz de quais
            // livros da PGFN as inscrições deste papel vieram.
            "principal": { "consta": true, "inscricoes": 4, "valor_total_centavos": 345000,
                           "ajuizadas": 1,
                           "situacoes": { "INSCRITA": 3, "AJUIZADA": 1 },
                           "tipos_situacao": { "Em cobranca": 3, "Garantia": 1 },
                           "primeira_inscricao": "2019-04-18",
                           "ultima_inscricao": "2025-11-30",
                           "ufs": ["SP"], "livros": ["PREV", "SIDA"] },
            // corresponsavel e solidario têm a MESMA forma do principal, zerados quando não
            // consta: as duas datas vêm null, nunca ausentes e nunca com data sentinela.
            "corresponsavel": { "consta": false, "inscricoes": 0, "valor_total_centavos": 0,
                                "ajuizadas": 0, "situacoes": {}, "tipos_situacao": {},
                                "primeira_inscricao": null, "ultima_inscricao": null,
                                "ufs": [], "livros": [] },
            "solidario": { "consta": false, "inscricoes": 0, "valor_total_centavos": 0,
                           "ajuizadas": 0, "situacoes": {}, "tipos_situacao": {},
                           "primeira_inscricao": null, "ultima_inscricao": null,
                           "ufs": [], "livros": [] } } }

// credito_scr: o retrato do SCR do Banco Central
{ "module": "credito_scr", "passed": true, "outcome": "approved", "score": 100,
  "data": { "status": 1, "estado": "concluido",       // sucesso da chamada / estágio do processamento
            "cpf": "12345678900", "nome": "TITULAR MOCK DA SILVA",
            "data_base": "31/07/2026",                // a competência do retrato
            "instituicoes": 3, "operacoes": 5,
            "carteira_credito_total": 18500.0,        // REAIS com decimais, não centavos
            "vencido_ate_90": 0, "prejuizo": 0 } }

// credito_protestos: protestos em cartório (Cenprot)
{ "module": "credito_protestos", "passed": true, "outcome": "approved", "score": 100,
  "data": { "status": 1, "estado": "concluido",
            "cpf": "12345678900", "nome": "TITULAR MOCK DA SILVA",
            "total_protestos": 1,
            "protestos": [ { "cartorio": "2º Tabelionato de Protesto", "uf": "SP",
                             "valor": 980.0, "data": "05/01/2026" } ] } }

// credito_cadin: inscrição no CADIN. "inscrito": false com "registros": [] é nada consta.
{ "module": "credito_cadin", "passed": true, "outcome": "approved", "score": 100,
  "data": { "status": 1, "estado": "concluido",
            "cpf": "12345678900", "nome": "TITULAR MOCK DA SILVA",
            "inscrito": false, "registros": [] } }

// credito_boavista: score e pendências da Boa Vista SCPC
{ "module": "credito_boavista", "passed": true, "outcome": "approved", "score": 100,
  "data": { "status": 1, "estado": "concluido",
            "cpf": "12345678900", "nome": "TITULAR MOCK DA SILVA",
            "score_boavista": 688, "possui_pendencias": false, "pendencias": [],
            "consultas_ultimos_90d": 2 } }

// ainda processando, ou fonte que não respondeu -> pending, e repare: NÃO existe a chave "data"
{ "module": "credito_scr", "passed": null, "outcome": "pending", "score": 0 }
```

Em sandbox o dossiê vem pronto (sem os dois tempos da fonte real): o desfecho segue o sufixo do documento, como no resto do ambiente de testes.
