Especificação · Fornecedores

Cadastro de Fornecedor

Quem é o fornecedor, se ele está apto a vender, e para onde o dinheiro vai. Três perguntas que o sistema de compras precisa responder — e que param exatamente onde começa o ERP financeiro.

substitui o módulo Fornecedores mínimo 9 agregados · 2 entidades de configuração alinhada a Anexo e GrydFiles · decidida por Fluxo de Aprovação v2.10 · 09/09/2026

Ponto de partida

Seis decisões que estruturam o resto

Decisão 1 · Identidade

Dois níveis: Supplier e SupplierEstablishment. Fornecedor é a entidade jurídica, chaveada pela raiz de 8 do CNPJ quando tem CNPJ — pelo CPF ou pelo identificador do país nos outros tipos; estabelecimento é o CNPJ completo de 14, matriz ou filial, e é onde vivem o endereço fiscal, a IE por UF, os termos comerciais e o padrão de pedido — por isso todo tipo de pessoa tem ao menos um, com ou sem CNPJ. Certidão federal, CNDT, regime tributário e quadro societário vivem na raiz. Situação cadastral, inscrição estadual, inscrição municipal, alvará e licença ambiental vivem no estabelecimento — e uma filial pode estar baixada com a matriz ativa.

Decisão 2 · CNPJ alfanumérico

CNPJ deve aceitar formato numérico e alfanumérico conforme a documentação da Receita Federal: 14 caracteres, 12 posições alfanuméricas e dois dígitos verificadores. Validar a biblioteca efetivamente adotada; não presumir compatibilidade pelo nome do pacote.

Decisão 3 · Prospect

Cotar não exige homologar. Dois estados de relacionamento, no modelo da Oracle: Prospect participa de RFQ e de qualificação mas não recebe pedido; SpendAuthorized transaciona. É a mudança de maior retorno sobre o modelo atual — desbloqueia cotação sem o atrito de exigir dez certidões de quem talvez nem venda.

Decisão 4 · Evidência

Documento enviado ≠ verificação feita. São duas entidades. SupplierDocument é o PDF que o fornecedor subiu; SupplierVerification é a consulta que o Nexio fez numa fonte oficial, com carimbo de data, fonte e resultado. Níveis de confiança diferentes, retenções diferentes e telas diferentes.

Decisão 5 · Banco

Dado bancário muda por proposta, nunca por edição. A alteração é escrita numa tabela de proposta e o registro vivo não muda até um segundo aprovador confirmar, vendo o diff. Mesma regra na API e na importação. É o padrão do D365 e é o único controle estrutural contra a fraude de troca de conta. Desde 04/09/2026 quem decide é o motor de aprovação — processo BANK_ACCOUNT_CHANGE —; carência, DICT e aviso no canal antigo continuam aqui.

Decisão 6 · Motor

Toda aprovação deste módulo é uma instância do motor de aprovação. Cadastro (SUPPLIER_REGISTRATION), homologação (SUPPLIER) e alteração bancária (BANK_ACCOUNT_CHANGE) não têm rota própria de aprovar: o Fornecedor submete, o motor decide — quem, em que ordem, em quanto tempo, com que alçada —, e o Fornecedor aplica o efeito. Até a v2.4 os três tinham rota própria, e a alteração bancária tinha um segundo caminho no motor (achado A8 da contra-análise). Bloquear, desbloquear e promover manualmente continuam atos de uma pessoa só, com motivo: não são aprovação. Ver Fluxo de Aprovação, princípio 7.

Fundamentos

Sete princípios

1. O Nexio é dono da identidade e da aptidão; o ERP é dono da obrigação e do pagamento

O cadastro guarda os fatos que sustentam "podemos comprar deste fornecedor, com que risco, e para onde pagamos" — e a evidência dessa decisão. Título a pagar, aging, retenção calculada, conta contábil, DARF, CNAB e escrituração são do ERP. Boa parte dos campos que Oracle, SAP e D365 carregam no fornecedor existe para servir ao módulo financeiro; copiá-los é o erro clássico de quem modela olhando ERP.

2. Certidão vence sozinha; status é derivado

A data de vencimento do documento é a fonte da verdade — o status do processo de homologação nunca a influencia. Isso é explícito na documentação do Ariba e evita o estado impossível "homologação aprovada com certidão vencida".

3. Homologação é por categoria, não global

Homologar "o fornecedor" é o antipadrão. Um fornecedor de serviço de limpeza e um de matéria-prima química exigem evidências diferentes. Ariba escopa qualificação por commodity + região; Oracle organiza áreas de qualificação em rule sets. Requalificação preserva o mesmo escopo da qualificação anterior.

4. Não existe rol legal fechado de documentos no setor privado

Diferente de licitação pública, cada comprador define seu pacote. O Nexio não pode ter lista de documentos codificada: precisa de requisitos configuráveis por tenant × categoria × faixa de risco. Lista fixa perde cliente de setor regulado por não coletar o que ele precisa, e irrita cliente de serviço leve por exigir o que não faz sentido.

5. Sanção pública alerta; não bloqueia sozinha

CEIS, CNEP e CEPIM são sanções em contratação pública. Uma empresa listada não está legalmente impedida de vender para uma empresa privada. No privado esses cadastros são sinal reputacional: geram alerta e decisão registrada. Bloqueio automático produz falso positivo, e o time de compras aprende a ignorar o alerta — que é o pior resultado possível de um controle.

6. CNAE não autoriza atividade

CNAE é classificação estatística e fiscal. Quem autoriza é alvará, licença setorial e conselho de classe. Use CNAE como triagem e como sinal de alerta quando o objeto contratado não guarda relação com nenhum CNAE do fornecedor — nunca como bloqueio duro, que reprova fornecedor legítimo e aprova o irregular que tem o CNAE certo e nenhuma licença.

7. O que o fornecedor declara e o que ele está autorizado a vender são coisas diferentes

As categorias que o fornecedor marca no portal servem para descoberta — montar a lista de convidados de um RFQ. O que ele pode de fato ter comprado é o ItemSupplier e a homologação por categoria. Fundir as duas transforma um campo preenchido pelo próprio fornecedor em controle de compliance.

Modelo

Mapa de entidades

SupplierEstablishment N por fornecedor CNPJ de 14, matriz ou filial — ou sem CNPJ, para quem não tem. Situação cadastral, IE, IM, endereço fiscal, termos comerciais, padrão de pedido.
SupplierContact N · papéis Pessoa com papéis (comercial, fiscal, financeiro, técnico, admin do portal). Opcionalmente ligado a um PortalUser.
SupplierDocument N · com vencimento O que o fornecedor enviou. Tipo configurável, vigência, arquivo, status derivado da data.
SupplierAddress N · flags de propósito Sede, entrega, cobrança, RFQ — flags independentes, não enum.
Supplier aggregate root · raiz do CNPJ Entidade jurídica. Razão social, natureza, porte, CNAE, regime tributário, grupo econômico.
SupplierVerification N · append-only O que o Nexio consultou: fonte, data, resultado, evidência. Nunca sobrescrito.
SupplierBankAccount versionado Conta e chave PIX com vigência. Alterado por BankAccountChangeProposal, nunca por update — e a proposta é decidida pelo motor (BANK_ACCOUNT_CHANGE).
SupplierQualification por categoria Escopo, questionário, resultado, validade, requalificação. A decisão por área é uma instância do motor (SUPPLIER).
ItemSupplier ponte com o Catálogo Preço, prazo, MOQ, múltiplo, unidade de compra. Detalhado em § Item × Fornecedor.
Contas a pagar fora de escopo Título, aging, retenção calculada, conta contábil, CNAB, escrituração.
SupplierCategory declarativa O que ele diz que fornece. Serve para descoberta e convite a RFQ — não autoriza compra.
PortalUser credencial · 0..1 por contato Separado do contato. Login, status da conta, escopo de acesso.

O Supplier é dono de anexo desde 09/09/2026 (ownerType = Supplier) — da evidência avulsa: ata de visita técnica, correspondência, e-mail de negociação, parecer solto. Certidão, contrato social e cartão de CNPJ continuam SupplierDocument, pela mesma regra de corte: o que tem número, órgão e vigência para digitar é entidade; o que é só prova é anexo. A BankAccountChangeProposal também é dona — o comprovante de titularidade que o controle antifraude exige antes de aprovar a troca de conta, e ele aceita APPROVAL_EVIDENCE, não só GENERAL, porque a retenção de GENERAL mataria a prova junto com a proposta que ela justifica. As onze respostas de cada descritor estão declaradas na página do Anexo, em O dono polimórfico — este módulo implementa, não redecide.

Convenção de nomes. O documento é em português; os identificadores são em inglês — entidades, atributos, valores de enum, rotas, permissões e códigos de erro. A exceção são os dados de negócio brasileiros, que ficam como são no mundo real: identificadores fiscais (cnpj, cpf, primaryCnae), nomes de regime tributário (SimplesNacional, LucroReal), siglas de unidade (UN, CX, KG), tipos de certidão e os exemplos de taxonomia — esses são conteúdo, não código.

A decisão central

Fornecedor e estabelecimento

A Oracle separa Supplier (entidade legal global) de Supplier Site (unidade que transaciona, com condição de pagamento, moeda e tolerâncias próprias). Esse modelo não mapeia direto para o Brasil: no Oracle o CNPJ mora no fornecedor e o site não tem identificação fiscal própria — mas aqui cada filial que emite nota tem CNPJ próprio e situação cadastral própria.

Vive na raiz (Supplier)Vive no estabelecimento
Razão social, natureza jurídica, porte, data de aberturaCNPJ completo (14), matriz ou filial
CNAE principal e secundáriosSituação cadastral e data — uma filial pode estar baixada com a matriz ativa
Regime tributário, opção pelo Simples, opção pelo regime regular de IBS/CBSInscrição estadual (por UF) e inscrição municipal
Quadro societárioEndereço fiscal
CND federal, CRF do FGTS, CNDTCertidão estadual e municipal, alvará, licença ambiental, licenças setoriais
Grupo econômico, DUNS, LEICapacidade de entrega, contatos operacionais

Grupo econômico é derivado, não digitado

A raiz de 8 dígitos do CNPJ identifica a entidade jurídica — matriz e filiais a compartilham. Isso dá ao Nexio um recurso que nenhum produto global tem: ao cadastrar um CNPJ cuja raiz já existe na base, sugerir o vínculo automaticamente em vez de deixar nascer um fornecedor duplicado. Para grupos com raízes distintas, existe parentSupplierId autorreferente, no modelo da Oracle e da Coupa.

O que o Nexio não vai construir agora: o "site" comercial

SAP e NetSuite particionam o fornecedor por unidade do comprador (company code, purchasing org, subsidiary). Num SaaS multi-tenant o tenant já é o comprador — replicar isso dentro do tenant só se paga com clientes que tenham várias filiais compradoras de fato. A evidência de que precisa vem quando o ItemSupplier precisar variar por local de entrega, que é o eixo ship-to organization da ASL da Oracle — e ela já veio: a UF de destino entrou na chave em 02/09/2026 e a condição comercial negociada ganhou eixo de empresa compradora — as duas na chave do ItemSupplierPrice, não na da relação. Condição de pagamento, moeda e incoterm continuam no estabelecimento porque nunca variaram por comprador; o preço, que varia, saiu de lá.

O tipo de pessoa muda o formulário inteiro

Company | MEI | Individual | RuralProducer | Foreign não é um campo com metade dos outros opcionais: é o seletor que decide quais campos existem, quais certidões são exigidas e quais alertas aparecem. Fornecedor estrangeiro não tem CNPJ, IE, IM, CND, FGTS, CNDT, CNAE nem Simples — forçar esses campos como obrigatórios é o bug mais comum de cadastro multi-país.

Domínio

Campos

Legenda: obrig · cond conforme tipo de pessoa · opc · gerado preenchido por consulta ou cálculo.

Fornecedor — identificação

CampoTipoRegra
entityTypeenumobrigCompany | MEI | Individual | RuralProducer | Foreign. Governa a obrigatoriedade de todo o resto.
cnpjRootchar(8)?condDerivado do CNPJ do estabelecimento principal, só para Company e MEI; nulo para Individual, RuralProducer e Foreign, que se identificam na raiz. Indexado onde não nulo — é a chave de agrupamento de grupo econômico.
legalNamestring(200)obrigPreenchido automaticamente pela consulta ao CNPJ quando disponível.
tradeNamestring(200)opcÉ por ele que o comprador busca. Indexado na busca full-text.
cpfchar(11)condObrigatório para Individual e RuralProducer, e é a identidade deles: único por tenant onde não nulo. Dado pessoal — ver LGPD.
foreignTaxId / taxIdCountrystring(40) / char(2)condObrigatórios para Foreign, e são a identidade dele: o par é único por tenant onde não nulo. Sem DV nacional — validação por formato do país. ISO 3166.
legalNatureCodestring(4)opcCódigo da tabela da Receita. Vem da consulta.
companySizeenumopcNotInformed | ME | EPP | Other. Notoriamente desatualizado na base da Receita — indicativo, nunca verdade contratual.
foundedOndateopcEmpresa aberta há poucos meses é sinal de triagem, não de reprovação.
primaryCnae / secondaryCnaeschar(7) / char(7)[]opcSubclasse CNAE de 7 dígitos. Triagem e sugestão de categoria — nunca habilitação.
duns / leiCodechar(9) / char(20)opcIdentificadores globais, relevantes em fornecedor estrangeiro.
parentSupplierIdGuid?opcAutorreferência. Grupo econômico com raízes distintas.
isOneTimeSupplierboolopcCompra pontual sem homologação plena. Evita poluir a base com fornecedor de uma compra só.

Identidade por tipo de pessoa

entityTypeIdentidadeOnde viveUnicidade
Company · MEIcnpjSupplierEstablishment, um por CNPJ de 14; cnpjRoot derivado na raizúnico por tenant, entre os estabelecimentos
Individual · RuralProducercpfSupplierúnico por tenant, entre as raízes
ForeigntaxIdCountry + foreignTaxIdSuppliero par, único por tenant, entre as raízes

Três identidades, cada uma com o seu índice único parcial por tenant — onde a coluna não é nula. Índice parcial depende do banco; a verificação vale na aplicação, inclusive contra rascunhos e cadastros pendentes (ver Antiduplicidade). cnpjRoot, cnpj, establishmentType e registrationStatus são nulos fora de Company e MEI; cpf só existe em Individual e RuralProducer; taxIdCountry + foreignTaxId só em Foreign. O estabelecimento continua obrigatório para todo tipo — ver RN-FOR-02. Fechado em 04/09/2026 pelo achado A7 da contra-análise.

Fornecedor — tributário

CampoTipoRegra
taxRegimeenumopcSimplesNacional | MEI | LucroPresumido | LucroReal | TaxExempt | NotApplicable. Obtido dos dados abertos da Receita (tabela do Simples traz opção e datas).
optsForRegularIbsCbsRegimebool?condicionalRegistra opção conhecida, fonte e data, sem inferir crédito líquido automaticamente. Na aquisição de optante do Simples com IBS/CBS no DAS, o adquirente no regime regular pode ter crédito limitado ao montante devido no Simples e informado, observadas as condições legais; opção pelo regime regular segue suas regras de apropriação, não crédito integral incondicional. LC 214, art. 47, § 9º.
regularRegimeOptedOndate?condObrigatória quando o anterior é verdadeiro — a opção tem data e afeta comparativos retroativos.

Estabelecimento

CampoTipoRegra
cnpjvarchar(14)?condObrigatório para Company e MEI; nulo para Individual, RuralProducer e Foreign, cuja identidade vive na raiz. Nunca numérico. Regex ^[A-Z0-9]{12}[0-9]{2}$, gravado sem máscara e em caixa alta. DV por módulo 11 com valor do caractere = ASCII − 48 (assim A–Z valem 17–42). Caso de teste canônico da Receita: 12ABC34501DE → DV 35. Índice único por tenant onde não nulo — parcial, depende do banco.
establishmentTypeenum?condicionalHeadquarters ou Branch conforme indicador cadastral da fonte oficial, com fonte/data; não derivar apenas da ordem 0001 do CNPJ. Nulo para entidade sem CNPJ. isPrimary é preferência operacional distinta. Receita Federal, FAQ CNPJ.
registrationStatus / registrationStatusOnenum? / date?geradoRegistrationStatus = 01 Null | 02 Active | 03 Suspended | 04 Unfit | 08 ClosedDown, os códigos da Receita — o mesmo enum do Establishment comprador, alinhado em 04/09/2026. Só Active deveria homologar. É por estabelecimento, não por raiz; nulo para quem não tem CNPJ — não existe situação cadastral sem cadastro.
stateRegistrationStatus / stateRegistrationNumber / stateRegistrationUfenum / string(20) / char(2)condstateRegistrationStatus ∈ {HasRegistration, Exempt, NotApplicable, NotInformed}. É 1:N — o mesmo fornecedor pode ter IE em várias UFs. O erro clássico é uma coluna de texto que recebe "ISENTO" digitado de sete jeitos.
municipalRegistration / municipalRegistrationCityCodestring(20) / código IBGEopcNecessária para prestador de serviço emitir NFS-e.
isPrimaryboolobrigExatamente um por fornecedor, de qualquer tipo de pessoa. É o padrão em pedidos quando nenhum outro é escolhido.
paymentTerms / currency / defaultIncotermstring(40) / char(3) / char(3)opcTermos comerciais negociados. O prazo é do Nexio; o cálculo do vencimento e dos encargos é do ERP.
receiptToleranceobjopcPercentuais de over e under delivery, e dias de antecipação e atraso aceitos. Detalhado no documento de Unidade de Medida.

Armadilha de importação: o Excel converte 3E5… em notação científica e come zeros à esquerda. O importador precisa forçar a coluna de CNPJ como texto. E a API deve expor CNPJ como string desde o dia 1, mesmo enquanto for numérico — trocar tipo em API pública depois é caro.

Domínio

Endereços e contatos

Propósito de endereço é flag, não enum

A Oracle usa AddressPurposeOrderingFlag, AddressPurposeRemitToFlag e AddressPurposeRFQOrBiddingFlag — booleanos independentes. Um endereço pode ser simultaneamente de pedido e de cobrança; um enum "tipo de endereço" obrigaria a cadastrar o mesmo endereço duas vezes. O Nexio usa as mesmas flags mais purposeShipping e fiscal.

Contato tem papel; a Oracle não tem e faz falta

O modelo da Oracle só traz AdministrativeContactFlag e deixa o papel funcional emergir da associação contato×endereço. O Nexio precisa de roles[] — Commercial, Tax, Finance, Technical, Quality, PortalAdmin — porque precisa saber para quem enviar o RFQ e para quem enviar o pedido, que raramente são a mesma pessoa. Exatamente um contato tem isPortalAdmin.

Contato e credencial são entidades separadas

SupplierContact pode existir sem acesso. PortalUser nasce do convite e guarda estado e vínculo de acesso; suspender contato ou conta deve seguir revogação explícita. A v1 não chama confirmação no mesmo canal de MFA.

EntidadeCampos
SupplierAddresslabel, street, number, complement, district, cityCode (IBGE), state, postalCode, country, landmark, phone, email, purposeHeadquarters, purposeOrdering, purposeShipping, purposeRemitTo, purposeRfq, purposeTax, supplierEstablishmentId?, status, inactiveOn
SupplierContactfirstName, lastName, jobTitle, email, phone, mobile, roles[], addressIds[], supplierEstablishmentId?, isPortalAdmin, status, inactiveOn
PortalUsercontactId, login, accountStatus, dataAccessScope, submissionConfirmationRequired, lastAccessOn

Domínio · FornecedorDocumento

Documentos

Tipo de documento é catálogo configurável por tenant, não enum de código. Campo fixo por tipo (fgtsCertificateUrl, fgtsExpiresOn) não escala e obriga migração para cada novo tipo.

CampoRegra
documentTypeIdCatálogo do tenant. Cada tipo declara: nível (raiz ou estabelecimento), se tem vencimento, validade padrão, se é exigido por categoria, e a política de vencimento.
scopeSupplier ou Establishment — herdado do tipo.
supplierEstablishmentIdcond Obrigatório quando scope = Establishment, proibido quando scope = Supplier (400 SUPPLIER_DOCUMENT_ESTABLISHMENT_REQUIRED). É o que distingue o alvará da filial da Bahia do alvará da filial de Minas — sem ele, três alvarás de três filiais são três linhas iguais, e o pacote exigido não sabe qual falta. Ver RN-FOR-25.
number, issuer, issuedOn, expiresOnVencimento nulo = documento sem validade (contrato social).
storedFileId→ GrydFiles, perfil nexio.supplier-document. Hash, antivírus, retenção e URL pré-assinada são do módulo de arquivo; o SupplierDocument cria a sua FileReference com ownerScope = "nexio.supplier-document" e a libera quando o documento é substituído. Não é Attachment: tem número, órgão, vigência e status derivado da data — a regra de corte da spec de Anexo.
statusgerado Valid | Expiring | Expired | Waived — derivado da data, com janela de "a vencer" configurável. Nunca gravado à mão.
confirmedBy / confirmedOnQuem, do lado do comprador, conferiu o documento. Diferente de quem subiu.
waivedBy / waiverReasonDispensa é decisão registrada, não campo em branco.

Catálogo-semente de tipos, com o nível certo

DocumentoEmissorValidadeNível
Contrato / estatuto socialJunta comercialsem validaderaiz
CND / CPEN federalRFB + PGFN (conjunta)180 diasraiz
CRF do FGTSCaixa Econômica Federal30 dias — a mais curta do pacote, porque o recolhimento é mensalraiz
CNDTJustiça do Trabalho / TST180 diasraiz
Certidão estadualSEFAZ / PGE da UF30 a 180 dias, variaestabelecimento
Certidão municipalPrefeitura30 a 90 dias, variaestabelecimento
Falência / recuperação judicialCartório distribuidor da comarca30 a 180 dias · pagaestabelecimento
Alvará de funcionamentoPrefeiturageralmente anualestabelecimento
Licença ambiental (LP/LI/LO)Órgão estadual ou IBAMAanos, por licençaestabelecimento
Licenças setoriais (ANVISA AFE, MAPA, ANTT, ANP)Órgão setorialvariaestabelecimento · por categoria
ISO 9001 / 14001 / 45001Organismo acreditadociclo de 3 anosestabelecimento
Apólices (RC geral, RC profissional, performance bond)Seguradoravigência da apóliceraiz · por categoria
Código de conduta assinadoo próprio tenantconfigurávelraiz

Cinco tipos-semente são por estabelecimento — certidão estadual, certidão municipal, falência/recuperação, alvará e licença ambiental —, e as licenças setoriais somam o eixo de categoria. É por isso que supplierEstablishmentId existe na linha: o pacote exigido é resolvido por estabelecimento ativo, e GET /suppliers/{id}/document-requirements devolve o que falta com o alvo, não uma lista plana. As três certidões federais de vigilância contínua — CND/CPEN, CRF do FGTS e CNDT — não têm consulta automatizada na v1 e são entrada manual com vigência (RN-FOR-26); a automação é pendência nomeada, no fim desta página.

Documento vencido não deve apagar o fornecedor do mapa. Nenhum dos produtos pesquisados bloqueia automaticamente o cadastro ao vencer um documento — o padrão real é sinalizar e rotear para decisão humana. No Nexio, a política é por tipo de documento e graduada: avisar, exigir justificativa na aprovação do pedido, ou bloquear a emissão de novo pedido. Bloqueio silencioso trava a operação e gera o workaround clássico — o comprador cadastra um fornecedor duplicado para contornar, o que alimenta o problema da antiduplicidade.

Domínio · FornecedorVerificacao

Verificações em fonte oficial

Entidade append-only: cada consulta gera um registro novo, com fonte, data, resultado e evidência. Sem a data da consulta, a flag é inauditável — o par flag + fonte + data é o que a Oracle faz com OnOFACListFlag e OFACSources.

FonteO que devolveAutomatizávelUso
Receita — CNPJRazão social, fantasia, endereço, CNAEs, porte, situação, sóciosSimAutopreenchimento no cadastro e revalidação periódica da situação
Receita — Simples/MEIOpção e datasSim (dados abertos)Regime tributário
Portal da Transparência — CEIS, CNEP, CEPIM, acordos de leniênciaSanções por CPF/CNPJSim — API pública e gratuita, com token; limites de 400 req/min das 06h às 24h e 700 req/min das 00h às 06hAlerta reputacional. Não bloqueia — ver princípio 5
Lista suja do trabalho escravo (MTE)Empregadores autuadosSim — publicação semestral (abril e outubro), por downloadAlerta bloqueante por política do tenant
OFAC / SDNSanções dos EUASim — arquivos para downloadRelevante em fornecedor estrangeiro
SINTEGRA / SEFAZ estadualSituação da inscrição estadualParcial — 27 portais, cobertura por API comercialValidação de IE
DICT (via PSP) / consulta de boletoTitular da chave PIX ou do boletoSim, por parceiroValidação de titularidade bancária — ver § bancário
CND / CPEN federal (RFB + PGFN)Regularidade fiscal federalNão na v1 — emissão por formulário com CAPTCHA, sem API públicaentrada manual SupplierDocument com número, emissão e vencimento; validade 180 dias
CRF do FGTS (Caixa)Regularidade do FGTSNão na v1 — sem API públicaentrada manual A mais curta do pacote: 30 dias. É a que mais vence, e a que mais precisa do aviso antecipado
CNDT (TST)Débitos trabalhistasNão na v1 — sem API públicaentrada manual Validade 180 dias

Base própria para buscar, consulta oficial para decidir

Quase todas as APIs gratuitas de CNPJ são derivadas do mesmo dump de dados abertos da Receita e herdam a latência dele — semanas. Para autopreenchimento e busca, isso é ótimo e barato: espelhe os dados abertos. Para uma decisão de homologação com efeito jurídico ("este fornecedor está ativo hoje"), dado defasado é risco: faça consulta pontual no momento da homologação e da revalidação, e grave fonte e carimbo de tempo.

O autopreenchimento é a maior alavanca de conversão do onboarding

Razão social, fantasia, endereço, CNAEs, porte, situação, sócios e Simples estão todos disponíveis a partir do CNPJ. Isso reduz um formulário de trinta campos para cerca de oito digitados. É, na prática, o principal diferencial dos SRMs brasileiros de homologação, e é replicável.

A varredura roda em lote, não só na homologação

Com uma API pública, gratuita e com limite generoso cobrindo quatro cadastros de integridade, não há razão para consultar apenas no onboarding. Um job periódico varre a base inteira e abre alerta quando algo muda — é o melhor custo-benefício de todo o pacote de compliance. A varredura cobre situação cadastral e sanção, não certidão.

Três das certidões que o produto promete vigiar não têm fonte, e isso está escrito

CND/CPEN, CRF do FGTS e CNDT são emitidas por formulário, com CAPTCHA, sem API pública. Na v1 elas são documento de entrada manual com vigência — o status continua derivado da data, o upload continua indo ao arquivo, e o que muda é que ninguém as consulta sozinho. O aviso passa a ser antecipado: 30, 15 e 5 dias antes do vencimento, e não só depois — que é o comportamento de hoje e é inútil, porque a essa altura a política de documento vencido já travou o pedido. A automação é pendência com dono declarado, no fim da página. Prometer varredura que não existe é pior do que não prometer: o comprador confia e o vencimento passa.

Processo

Homologação

CampoRegra
supplierIdHomologação é da entidade jurídica; documentos de estabelecimento são conferidos dentro dela.
scopeCategoryIdsNós da árvore de categorias. Um fornecedor pode estar homologado em Serviços de Limpeza e não em Produtos Químicos.
questionnaireId / answersQuestionário modular reutilizável entre processos, não template por projeto.
riskTierLow | Medium | High | Critical. Define o pacote de documentos exigido e a periodicidade da revalidação.
outcomeApproved | ApprovedWithFindings | Rejected. A opção do meio é o que o mercado brasileiro efetivamente usa e o que evita reprovar por um documento faltante.
findings[]Cada ressalva com descrição, prazo e responsável. Ressalva sem prazo é ressalva esquecida.
validTo / nextReviewOnCríticos tipicamente anual; demais, bienal.
approvalRequestId · approvals[]A instância do motor no processo SUPPLIER, e a leitura das tarefas dela — área (o rótulo do alvo), aprovador, decisão, data. Em paralelo — jurídico, financeiro, técnico e qualidade revisam ao mesmo tempo, não em cadeia: é o nível Panel do motor, um aprovador de cada alvo. A política padrão semeada é um nível só (PermissionHolder(manage:supplier-qualifications)); o tenant troca pelo painel de quatro áreas quando quiser. approvals[] não é gravado aqui — é projeção da instância.

Requalificação preserva o escopo da qualificação anterior — mesmas categorias, mesma faixa de risco. Recomeçar do zero com escopo diferente é como uma homologação vencida vira um fornecedor que ninguém sabe se pode usar.

Quem decide e quem executa. Submeter a qualificação abre a instância SUPPLIER com scopeCategoryIds e riskTier como critérios — "risco Critical exige jurídico" é política, não código. Quando a instância termina em Approved, o Fornecedor grava outcome (com ApprovedWithFindings quando alguma tarefa aprovou com ressalva), findings[], validTo, e promove o fornecedor a SpendAuthorized (RN-FOR-04). Rejeição grava Rejected com a quádrupla de motivo, uso SupplierReject. Quem conduz a qualificação — questionário, documentos — não decide: a RN-AP-08 o remove das tarefas.

Segurança

Dados bancários

A fraude não precisa que você pague — precisa que você armazene o dado que alguém a jusante vai usar. Se não houver necessidade real, não guarde. Se guardar, esta seção inteira é requisito, não sugestão. No Brasil a jurisprudência tende a não responsabilizar o banco quando o boleto foi emitido fora da plataforma bancária: a perda fica com quem pagou.

Campos

CampoRegra
accountKindDomestic | International. Discrimina o bloco de campos — doméstico usa ISPB, agência, conta e chave PIX; internacional usa IBAN, SWIFT/BIC, país e banco intermediário. Campo do bloco errado responde 400 SUPPLIER_FIELD_NOT_APPLICABLE nomeando campo e bloco. Ver RN-FOR-27.
ispb / compeCodebloco doméstico Guardar o ISPB de 8 dígitos como chave — é o identificador moderno no SFN. O COMPE de 3 dígitos fica como conveniência de exibição.
branchNumber / branchCheckDigit / accountNumber / accountCheckDigitFormatos variam por banco; não existe validação universal.
accountTypeChecking | Savings | Payment. Conta de pagamento cobre fintechs.
holderName / holderTaxIdA comparação é por tipo de pessoa, e a raiz do CNPJ só serve a Company — onde permite que a filial receba na conta da matriz. Em MEI, Individual e RuralProducer compara-se o documento inteiro (CNPJ do MEI ou CPF do titular, ambos esperados); em Foreign não há documento brasileiro a comparar e o veredito é de nome, gravado, nunca flag automática. A flag "titular ≠ fornecedor" nasce só quando a comparação aplicável falha — a política do motor decide quem a mais aprova, e a justificativa vai no comentário da tarefa. Ver RN-FOR-13.
pixKeyType / pixKeyCNPJ | CPF | Email | Phone | Random. Ver a tabela de risco abaixo.
validFrom / validToVersionamento. Nunca UPDATE na linha — sempre nova versão, com autor e justificativa.
holderVerificationResultado da consulta ao DICT ou ao boleto: documento retornado, comparação com o do fornecedor, veredito e carimbo de tempo.
usableFromcarência Data e hora a partir das quais a conta é destino de pagamento legítimo. Gravada pelo contrato de desfecho quando a instância BANK_ACCOUNT_CHANGE termina em Approved: decidedAt + bankChangeGraceHours (configuração do tenant, 24 a 72 h, padrão 48). Conta com usableFrom no futuro não entra no pacote enviado ao ERP e responde 409 BANK_ACCOUNT_NOT_USABLE_YET_CONFLICT a quem a pedir como destino. Nunca é editada por PUT, nunca anda para trás, e não existe rota de antecipação — a carência é o controle. Ver RN-FOR-22.
iban / swiftBic / bankCountryCode / bankNamebloco internacional Obrigatórios quando accountKind = International. iban validado por formato e dígito ISO 13616 quando o país usa IBAN; swiftBic em 8 ou 11 caracteres, ISO 9362; bankCountryCode em ISO 3166-1 alfa-2. Onde não há IBAN (EUA, Canadá), accountNumber e o código de compensação local voltam a valer dentro deste bloco, com routingCodeType = ABA | TransitNumber | SortCode | Other.
intermediaryBankSwiftBic / intermediaryBankNameopc Banco intermediário, quando o correspondente exige. Ausência não é erro; presença sem accountKind = International é.

Chave PIX e risco

TipoCarrega identidade?Leitura
CNPJSim, diretamentemenor risco Auto-verificável contra o cadastro. É a chave a preferir e a sugerir ao fornecedor.
CPFSimalerta Para fornecedor pessoa jurídica, chave CPF é sinal de alerta.
Email / PhoneNãoalerta Exige resolução no DICT para saber de quem é.
Aleatória (EVP)Não carrega nenhuma informaçãomaior risco É impossível saber o titular olhando. Aceitar sem resolver no DICT é aceitar um destino de pagamento anônimo.

O mecanismo: proposta de alteração

ControleComo funciona
Proposta, não ediçãoA alteração vai para BankAccountChangeProposal. O registro vivo não muda até a aprovação. O aprovador vê atual vs. proposto lado a lado — não se aprova um registro, aprova-se uma mudança.
Campos protegidos configuráveisBanco, agência, conta, chave PIX, IBAN, SWIFT/BIC, titular, razão social — e o e-mail e o telefone do contato com papel Finance, que são o canal do aviso. O admin marca quais exigem aprovação; a tela os rotula como tal. Proteger o destino do dinheiro sem proteger o canal do aviso não protege nada: quem reescreve os contatos plantando o próprio endereço recebe, ele mesmo, o aviso da troca que vai propor em seguida. Ver RN-FOR-21.
Mudança de canal também é propostaAlterar e-mail ou telefone de contato Finance — por tela, por PUT /suppliers/{id}/contacts ou por importação — responde 409 SUPPLIER_CONTACT_PROTECTED_FIELD_CONFLICT e exige POST /suppliers/{id}/contacts/change-proposals. A proposta é a mesma entidade, com changeKind = NoticeContact, e abre a mesma instância BANK_ACCOUNT_CHANGE: mesmo motor, mesma separação entre quem propõe e quem aprova, mesmo aviso — que sai no canal anterior, e não no proposto.
Quem decideA proposta abre uma instância do motor, processo BANK_ACCOUNT_CHANGE, com valor avaliado e as flags "titular ≠ fornecedor" e "chave PIX não verificada". A política semeada tem um degrau incondicional de Quorum(2), que não consulta valor nenhum, mais os degraus por faixa acima dele — o alvo continua sendo PermissionHolder(approve:supplier-banks), e a recomendação de um nível de controladoria sempre que a flag de titular estiver presente segue de pé. Quando a instância termina em Approved, o Fornecedor aplica a proposta ao registro vivo e grava usableFrom.
O valor avaliado é gancho nomeado, e "indisponível" não é zeroQuem calcula: o gancho supplier-spend-12m, implementado pelo módulo de Pedido quando ele existir — não pelo Fornecedor. Sobre qual documento: PurchaseOrder aprovado nos últimos doze meses, somado sobre todas as empresas do tenant, dividido por doze. Em que moeda: na moeda funcional da empresa compradora; havendo mais de uma, cada parcela é convertida para a moeda do limite da política pela regra de conversão da alçada, e a taxa e a data usadas ficam no evento da instância. Enquanto o módulo não existir, o gancho devolve Unavailable, nunca zero, e valor indisponível nunca reduz a exigência: a instância cai no degrau incondicional. Sem isso o controle nasceria funcionando com uma assinatura só durante todo o MVP, que é o pior modo de falha possível.
Aprovador ≠ solicitanteObrigatório, sem exceção de urgência — garantido pela RN-AP-08 do motor, que remove o solicitante de toda tarefa da própria instância. Idealmente o aprovador não é de quem fez a compra.
Mesma regra na API e no importTrês modos, no padrão do D365: aceitar sem aprovação, recusar a alteração, ou criar proposta. O default é criar proposta. É aqui que a maioria das implementações vaza.
Verificação de titularidadeResolver a chave PIX no DICT ou consultar o beneficiário do boleto, comparar com o CNPJ do fornecedor e gravar o veredito. Este controle não existe nos concorrentes globais no Brasil.
Carência antes do primeiro usoÉ o campo usableFrom, não uma frase: 24 a 72 h entre a decisão e a liberação para pagamento, com a invariante "conta em carência não sai no pacote do ERP" escrita na RN-FOR-22. Sem campo, a carência não existe — o que existe é a intenção de tê-la.
Janela mínima entre o aviso e a primeira decisãoNenhuma tarefa da instância é ativada antes de noticeSentAt + minNoticeHours (configuração do tenant, mínimo 12 h, padrão 24). Decisão tentada antes responde 409 BANK_CHANGE_NOTICE_WINDOW_NOT_ELAPSED_CONFLICT. Aviso disparado e proposta aprovada no mesmo minuto é aviso decorativo: o fornecedor legítimo precisa de tempo de reagir antes de a conta trocar, não depois. Ver RN-FOR-23.
Notificação nos canais anterioresAvisar o contato Finance antes da mudança, por dois canais: e-mail e telefone. O resolvedor Previous lê o contato vigente antes da alteração proposta — o que vale tanto para a proposta bancária quanto para a proposta de canal, e é o que fecha o ataque em dois passos. O aviso não pode deixar de sair da empresa: na falta de contato Finance, a cadeia cai para PortalAdmin, depois Commercial, depois o contato do estabelecimento principal — e, se nenhum canal fora do tenant existir, a proposta não abre (422 BANK_CHANGE_NO_EXTERNAL_NOTICE_CHANNEL_UNPROCESSABLE). O administrador do tenant recebe cópia; ele nunca é o destinatário no lugar do fornecedor.
Alertas de padrãoMesma conta em dois fornecedores diferentes; conta em UF descolada do domicílio; mudança pouco antes de um pagamento grande.
Trilha imutávelValor anterior, novo, quem, quando, de qual IP e por qual canal. Em fraude consumada, é isso que determina responsabilidade.

Domínio · FornecedorCategoria

Categorias fornecidas

Relação N:N com CategoryNode, com entidade associativa própria — o mesmo desenho do Products and Services da Oracle. Duas semânticas que precisam ficar separadas:

Declarativa

SupplierCategory. O que o fornecedor diz — ou foi aprovado — a fornecer. Origem: autodeclaração no portal durante o registro, mais aprovação. Uso: descoberta — montar a lista de convidados de um RFQ, busca, segmentação. Não bloqueia nada. Guarda a origem (autodeclarado ou homologado) e quem informou.

Autorizativa

SupplierQualification.scopeCategoryIds vigente. O que ele pode de fato ter comprado é o resultado de uma consulta — supplierId × categoryNode, casando por prefixo de path e respeitando validTo —, não de um estado do relacionamento. É o papel da Approved Supplier List da Oracle. ItemSupplier.status continua sendo trava por item onde a relação existe, e nunca é o gate: item sem ItemSupplier ficaria sem nenhum. Ver RN-FOR-24.

Fundir as duas transforma um campo que o próprio fornecedor edita em controle de compliance. A documentação da Oracle é explícita: Products and Services serve para identificar quem convidar para negociações — quem restringe a compra é a ASL.

Ponte com o Catálogo

Item × Fornecedor

Especificado em Cadastro de Item; aqui ficam a chave e as decisões que dependem do fornecedor. A parte de unidade de compra, fator de conversão e preço por quantidade está detalhada no documento de Unidade de Medida.

A relação e o preço são duas entidades, e a UF é dimensão de preço

O análogo exato é a ASL da Oracle, chaveada em item ou categoria × organização de entrega × fornecedor × site, com atributos que são quase os mesmos do ItemSupplier: unidade de compra, país de origem, quantidade mínima e múltiplo de lote. No Nexio o par é ItemSupplier — a relação de fornecimento, chaveada em três partes (itemId + supplierId + supplierEstablishmentId?) e dona de status, isPreferred/priority, tolerâncias, reviewByDate e contractId — mais ItemSupplierPrice, a versão de preço, filha e append-only, chaveada por itemSupplierId + validFrom + shipToStateCode? + companyId? + incoterm. A vigência e a UF de destino saíram da chave da relação e foram para a do preço, que é o movimento inteiro. A UF fica no preço porque não é dimensão de relacionamento: com ela na relação, um fornecedor com preço nacional mais uma exceção de SP viraria duas relações para um único relacionamento, sem resposta para qual delas carrega o status — e mudar o endereço de entrega de uma requisição mudaria de relacionamento de fornecimento, porque a FK da linha aponta para a relação. Mudar onde se recebe muda o preço, nunca o fornecedor. Estabelecimento nulo significa "vale para todos os estabelecimentos" — dá o comportamento da Oracle sem obrigar todo cliente a modelar filiais. É o info record × condition record do SAP e o ASL × price break do Oracle: reajustar preço deixa de duplicar a relação, "máximo dez preferidos por item" volta a contar relações, e o DELETE "só se nunca usado" volta a ser decidível. Esta página descreve a chave; quem a define é o Cadastro de Item, spec dona do agregado.

Status é política executável, não rótulo

New | UnderQualification | Approved | Blocked, cada um carregando allowsQuotation e allowsOrder. Na Oracle, o status da ASL determina se o fornecedor pode ser origem do item e se o pedido pode ser aprovado — Debarred impede a aprovação. É controle, não etiqueta.

O eixo de destino existe, e é a UF

Preço e prazo de um mesmo item e fornecedor variam por destino. A ASL da Oracle já tem esse eixo, e o Nexio passou a ter em 02/09/2026 — não como o gancho desligado shipToLocationId que esta página anunciava, mas como shipToStateCode ligado e dentro da chave do ItemSupplierPrice, ao lado de companyId? — as duas são dimensão de preço sem serem também dimensão de status. Destino muda frete e tributação; comprador muda condição negociada; nenhum dos dois muda quem é o fornecedor homologado. É onde a variação tributária mora no condition record do SAP e no price break do Oracle, e o que aqueles dois levam na chave da relação é a organização compradora — no Nexio, o companyId, que já está no preço. A dimensão é a UF, não o ponto de entrega: o que muda preço é frete e tributação, e dois pontos na mesma cidade não têm preço diferente — chavear pelo ponto faria o catálogo crescer sem teto. A busca usa o deliveryStateCode já congelado na linha, então resolver preço não consulta o cadastro do ponto. Preço por sítio específico é negociação, e mora no Contract. Ver o Cadastro de Item.

Governança

Estados e bloqueios

O status atual do módulo (Approved / UnderReview / Suspended / Blocked) mistura quatro coisas distintas. Oracle e Ariba as separam, e a separação resolve problemas reais.

EixoValoresResponde
RelacionamentoProspect | SpendAuthorizedAté onde este fornecedor pode ir
Processo de cadastroDraft | AwaitingSupplier | UnderReview | Approved | RejectedOnde está o cadastro. UnderReview é a instância SUPPLIER_REGISTRATION aberta no motor; Approved e Rejected são o efeito dela
VigênciaActive | Inactive + inactiveOnSe o registro está em uso
Bloqueiobloqueado + motivo + blockedBy + blockedOnImpedimento operacional pontual

O que cada estado libera

A tabela cruza dois eixos, não um. Ler só o relacionamento é o que deixava o cadastro Rejected convivendo com Prospect convidável — recusado por sanção numa coluna e convidável na outra.

EstadoConvidar para RFQReceber pedidoQualificar
Prospectpermitidobloqueadopermitido
SpendAuthorizedpermitidopermitidopermitido
SpendAuthorized, documento vencidopermitidoconforme política do tipopermitido
SpendAuthorized, bloqueadoavisobloqueadopermitido
Inactivebloqueadobloqueadobloqueado
Cadastro Draft ou AwaitingSupplierbloqueadobloqueadobloqueado
Cadastro UnderReviewpermitido, com avisobloqueadopermitido
Cadastro Rejectedbloqueadobloqueadobloqueado
SpendAuthorized, sem qualificação vigente na categoria da linhapermitidobloqueado SUPPLIER_NOT_QUALIFIED_FOR_CATEGORY_CONFLICTpermitido

Cadastro Rejected só sai de Rejected por novo submit, que reabre a instância SUPPLIER_REGISTRATION e volta o processo a UnderReview. Não há caminho que devolva um recusado ao convite sem passar por análise — e a promoção manual (POST /suppliers/{id}/promote) mexe no eixo de relacionamento, nunca no de processo, então também não é essa porta. E receber pedido não é uma linha desta tabela sozinha: a quarta condição é a qualificação vigente que cubra a categoria de cada linha do documento (RN-FOR-24).

Pedidos em aberto sobrevivem ao bloqueio e à inativação — bloquear o recebimento de um pedido legítimo já colocado transforma uma decisão de cadastro num problema operacional. E Status + inactiveOn existem em cada nível — fornecedor, estabelecimento, endereço, contato — no padrão consistente da Oracle. Não é um status global.

Qualidade de dados

Antiduplicidade

O Nexio tem uma vantagem estrutural sobre os produtos globais: o CNPJ tem dígito verificador e formato fixo. Isso resolve, de graça, o caso difícil que a Oracle ataca normalizando o taxpayer ID para caracteres alfanuméricos.

#RegraAção
1CNPJ normalizado — 14 caracteres, caixa alta, sem máscara — índice único por tenant onde não nulo (Company, MEI)bloqueia
2CPF normalizado — índice único por tenant onde não nulo (Individual, RuralProducer)bloqueia
3taxIdCountry + foreignTaxId normalizados — índice único por tenant onde não nulos (Foreign)bloqueia
4Raiz do CNPJ já existente na basealerta — oferece vincular ao grupo econômico em vez de duplicar
5Similaridade de razão social e nome fantasia (trigram) + domínio de e-mail coincidentealerta com candidatos
6Conta bancária ou chave PIX idêntica entre fornecedores distintosalerta de segurança — é sinal de fraude, não só de duplicidade
7Re-execução na aprovação do cadastroalerta ao aprovador

Verifique também contra rascunhos e cadastros pendentes

É o achado mais subestimado da documentação da Oracle: a checagem considera fornecedores existentes e também solicitações de registro pendentes de aprovação ou salvas para completar depois. Sem isso, dois cadastros do mesmo CNPJ passam juntos pela fila.

Aplique em todos os caminhos de entrada

Tela, importação, API e autocadastro. A Oracle é explícita nisso, e é exatamente onde a maioria das implementações vaza — a validação existe na tela e não existe no POST.

Não revele a colisão ao fornecedor

No autocadastro, a mensagem não nomeia qual fornecedor colidiu. A Oracle expõe o nome do fornecedor existente apenas a usuários internos. É controle de vazamento de informação, e é fácil de esquecer.

Contrato vigente · revisão consolidada

Desempenho com denominador e origem verificáveis

O Nexio pode calcular desempenho a partir dos fatos que registra e dos recebimentos importados, com origem, cobertura e data de atualização. Recebimento também existe em soluções como SAP Ariba e Coupa; não é exclusividade competitiva demonstrada.

MétricaDefinição mínimaLimitação visível
OTIFEntregas programadas vencidas cuja quantidade integral aceita chegou até a data prometida mais tolerância, divididas por todas as entregas programadas vencidas elegíveis. Entregas vencidas abertas entram no denominador e falham.Definir grão por programação/linha, janela, unidade e tolerâncias; nunca usar apenas recebimentos concluídos. Cancelamento documentado antes do vencimento pode ser excluído, com contagem separada.
AtrasoDias de atraso de entregas concluídas e idade das vencidas abertas, em indicadores separados.Mostrar promessa original e promessa renegociada, com autor/motivo; adiar promessa não apaga falha histórica.
Integralidade e qualidadeQuantidade aceita acumulada contra a programação; rejeições e devoluções vinculadas aos lotes/recebimentos.Entrega parcial pontual não é In Full; qualidade e devolução têm métricas separadas e janela explícita.
Aderência de preço / custo totalPedido versus nota e custos efetivos por linha, na mesma moeda e base.Separar variação cambial, tributos, frete e mudança de quantidade. Crédito fiscal depende de confirmação.
Resposta à cotaçãoConvite entregue, primeira resposta, proposta válida, revisão e ausência de resposta.Fornecedor que nunca respondeu permanece na coorte; falha de entrega do convite é categoria separada.

Projeções são reconstruíveis, versionadas pela definição da métrica e publicam cobertura, período e atualidade. Amostra pequena ou histórico incompleto limita a recomendação; não transforma ausência de falha observada em confiabilidade alta. Comparativos antes de existir volume suficiente são hipóteses de produto.

Rastreabilidade

Regras de negócio

RN-FOR-01

CNPJ é texto de 14 caracteres, validado por regex e DV

^[A-Z0-9]{12}[0-9]{2}$ mais módulo 11 com valor do caractere igual a ASCII − 48. Gravado sem máscara e em caixa alta; a entrada normaliza minúsculas. Aceitar os dois formatos, numérico e alfanumérico — a Receita continua emitindo CNPJs só numéricos, então "CNPJ novo" não implica "tem letra".

RN-FOR-02

Todo fornecedor tem exatamente um estabelecimento principal

Criado junto com o fornecedor, para todo entityType — é no estabelecimento que vivem a IE por UF (produtor rural tem IE), o endereço fiscal, paymentTerms / currency / defaultIncoterm, receiptTolerance e o padrão de pedido por isPrimary. Para Company e MEI, o principal é a matriz quando ela existe na base. Para Individual, RuralProducer e Foreign, o principal é o estabelecimento único criado com o cadastro — sem cnpj, sem establishmentType e sem situação cadastral; a identidade fica na raiz. A alternativa "estabelecimento só para quem tem CNPJ" foi recusada em 04/09/2026: deixaria produtor rural sem IE e estrangeiro sem moeda e incoterm.

RN-FOR-03

Tipo de pessoa governa a obrigatoriedade

Campo obrigatório para um tipo e inaplicável a outro responde 400 SUPPLIER_FIELD_NOT_APPLICABLE nomeando campo e tipo. Estrangeiro não tem CNPJ, IE, IM, CNAE nem regime tributário brasileiro. A identidade segue o tipo — cnpj no estabelecimento para Company e MEI, cpf na raiz para Individual e RuralProducer, taxIdCountry + foreignTaxId na raiz para Foreign —, cada uma com o seu índice único parcial por tenant, que depende do banco e é verificado na aplicação.

RN-FOR-04

Prospect cota, homologado transaciona

Prospect pode ser convidado a RFQ e qualificado; pedido responde 409 SUPPLIER_NOT_SPEND_AUTHORIZED_CONFLICT. A promoção acontece por homologação aprovada (instância SUPPLIER terminada em Approved) ou manualmente com justificativa — e por mais nada. Vitória em cotação não promove: ela abre uma qualificação para as categorias do que foi cotado, que percorre o mesmo caminho de todas as outras. Promover por vitória tornaria o convite a uma RFQ o atalho mais barato para contornar a homologação — sem instância, sem motivo codificado, sem certidão e sem varredura de sanção. E promover não basta: quem paga a conta do gasto é a RN-FOR-24.

RN-FOR-05

Situação cadastral diferente de Ativa impede homologar

Suspensa, inapta, baixada ou nula bloqueiam a aprovação da homologação e são reavaliadas na revalidação periódica. Fornecedor que fica inapto depois de homologado gera alerta, não bloqueio automático de pedidos em aberto. Quem não tem CNPJ não tem situação cadastral, e esta regra não se aplica — a diligência de pessoa física e de estrangeiro é a dos documentos do tipo.

RN-FOR-06

Status de documento é sempre derivado da data

Nunca gravado à mão. A janela de "a vencer" é configurável por tipo. O status da homologação não influencia o vencimento do documento — a relação é só nessa direção.

RN-FOR-07

A política de documento vencido é por tipo e graduada

Warn | RequireJustification | BlockNewOrder. Nenhuma política bloqueia recebimento de pedido já colocado.

RN-FOR-08

Requisitos de documento são configuráveis por categoria e faixa de risco

Não existe lista fixa. O motor resolve: dado o fornecedor, suas categorias homologadas e a faixa de risco, quais tipos são exigidos, quais opcionais e quais dispensados.

RN-FOR-09

Homologação é escopada por categoria e a requalificação preserva o escopo

Homologação sem escopo é recusada. Requalificação herda categorias e faixa de risco da anterior.

RN-FOR-10

Sanção pública gera alerta, nunca bloqueio automático

CEIS, CNEP, CEPIM e leniência abrem pendência com decisão registrada. O tenant pode elevar um tipo de sanção a bloqueante por configuração, mas não é o default.

RN-FOR-11

Verificação é append-only

Cada consulta grava fonte, data, resultado e evidência. Nunca sobrescreve a anterior — a série histórica é o que torna a decisão auditável.

RN-FOR-12

Dado bancário nunca é alterado por update

Toda mudança em campo protegido cria BankAccountChangeProposal, que abre uma instância do motor no processo BANK_ACCOUNT_CHANGE. O registro vivo permanece intacto até a instância terminar em Approved; "aprovador distinto do solicitante" é a RN-AP-08 do motor, não uma checagem deste módulo. Vale para tela, API e importação.

RN-FOR-13

Titular da conta deve bater com o fornecedor, e a comparação segue o tipo de pessoa

Só Company compara pela raiz do CNPJ, que é o que permite a filial receber na conta da matriz. MEI compara o documento inteiro e aceita tanto o CNPJ quanto o CPF do titular — a conta de MEI é conta de pessoa física no mundo real, e tratá-la como divergência produziria flag em cem por cento dos MEIs. Individual e RuralProducer comparam o CPF da raiz. Foreign não tem documento brasileiro a comparar: o veredito é de nome contra o titular informado, gravado com fonte e data como qualquer verificação, e nunca vira flag automática. A flag "titular ≠ fornecedor" nasce só quando a comparação aplicável ao tipo falha — a política do motor decide quem a mais aprova, e a justificativa fica no comentário da tarefa. Não existe exceção fora do motor. Falso positivo crônico é o modo de morte de um controle: um alerta que dispara sempre é um alerta que ninguém lê.

RN-FOR-14

Chave PIX aleatória exige resolução de titularidade

Sem verificação bem-sucedida no DICT, a chave fica em estado não verificado e não é oferecida como destino de pagamento.

RN-FOR-15

CNPJ é único por tenant, verificado contra pendentes

A checagem cobre ativos, rascunhos e cadastros pendentes de aprovação, em todos os caminhos de entrada.

RN-FOR-16

Fornecedor não é excluído

Havendo RFQ, pedido, recebimento ou nota, apenas inativação. O DELETE existe só para cadastro em rascunho nunca submetido.

RN-FOR-17

Bloqueio exige motivo e registra autor

motivo, blockedBy e blockedOn são obrigatórios. Desbloqueio idem. Sem isso, ninguém sabe por que aquele fornecedor está parado há seis meses.

RN-FOR-18

Categoria declarada não autoriza compra

Serve a convite de RFQ e busca. A autorização vem da consulta às qualificações vigentes (RN-FOR-24); ItemSupplier.status é trava adicional por item, quando a relação existe — nunca o gate, porque item sem ItemSupplier não teria gate nenhum.

RN-FOR-19

Concorrência otimista em todo update

expectedVersion obrigatório no corpo do PUT, checado antes de tocar o agregado.

RN-FOR-20Auditar acesso proporcional ao dado

IAuditableEntity registra alterações; leitura e exportação de CPF e dados bancários têm autorização específica, máscara e trilha mínima de acesso. Retenção e base legal são definidas por finalidade, conforme a seção LGPD.

RN-FOR-21

O canal do aviso é campo protegido, como o destino do dinheiro

E-mail e telefone de contato com papel Finance só mudam por proposta, pela mesma entidade e pela mesma instância BANK_ACCOUNT_CHANGE, com changeKind = NoticeContact. Tentativa por PUT, por tela ou por importação responde 409 SUPPLIER_CONTACT_PROTECTED_FIELD_CONFLICT. O resolvedor Previous lê o contato vigente antes da alteração proposta, e o telefone é segundo canal, não alternativa. Não havendo contato Finance, a cadeia cai para PortalAdmin, Commercial e contato do estabelecimento principal — nesta ordem; se nenhum canal fora do tenant existir, a proposta não abre (422 BANK_CHANGE_NO_EXTERNAL_NOTICE_CHANNEL_UNPROCESSABLE). O administrador do tenant recebe cópia e nunca substitui o fornecedor como destinatário: aviso que não sai da empresa não avisa ninguém. Por quê: sem esta regra o ataque cabe numa sessão — reescrever os contatos, abrir a proposta bancária, receber o próprio aviso.

RN-FOR-22

Conta aprovada só é destino de pagamento a partir de usableFrom

O contrato de desfecho grava usableFrom = decidedAt + bankChangeGraceHours ao aplicar a proposta. Conta com usableFrom no futuro não entra no pacote enviado ao ERP — a seleção do destino de pagamento filtra por usableFrom <= agora, e pedi-la explicitamente responde 409 BANK_ACCOUNT_NOT_USABLE_YET_CONFLICT. A data não anda para trás, não é editável por PUT e não tem rota de antecipação: uma carência que se pode encurtar sob pressão é a carência que não existe justamente no dia em que ela importa. A conta anterior continua vigente e pagável durante a janela.

RN-FOR-23

Entre o aviso e a primeira decisão há janela mínima

A proposta grava noticeSentAt quando o aviso sai. Nenhuma tarefa da instância é ativada antes de noticeSentAt + minNoticeHours (configuração do tenant, mínimo 12 h, padrão 24), e decisão tentada antes responde 409 BANK_CHANGE_NOTICE_WINDOW_NOT_ELAPSED_CONFLICT. O aviso existe para dar ao fornecedor legítimo a chance de dizer "não fui eu" antes da troca; disparado e aprovado no mesmo minuto, ele só documenta a fraude. A guarda vive no motor, que é quem ativa tarefa — o Fornecedor fornece noticeSentAt e a configuração.

RN-FOR-24Revalidar autorização ao emitir

Emitir novo pedido exige SpendAuthorized, cadastro Approved, fornecedor não bloqueado e qualificação vigente cobrindo cada categoria na data de efetivação. Validar também na submissão como prévia. ItemSupplier é trava adicional. Vencimento posterior não impede registrar entrega de pedido vigente; novo compromisso exige regularização.

RN-FOR-25

Documento de escopo de estabelecimento declara qual estabelecimento

SupplierDocument.supplierEstablishmentId é obrigatório quando scope = Establishment e proibido quando scope = Supplier — descumprir responde 400 SUPPLIER_DOCUMENT_ESTABLISHMENT_REQUIRED. Cinco dos treze tipos-semente são por estabelecimento; sem a coluna, três alvarás de três filiais são três linhas indistinguíveis e o pacote exigido não sabe dizer que falta o da Bahia. O requisito é resolvido por estabelecimento ativo, e a promessa "filial baixada com a matriz ativa" passa a valer também para a documentação: estabelecimento inativo sai do pacote.

RN-FOR-26

Certidão sem fonte automatizada é entrada manual com vigência, e o aviso vem antes

CND/CPEN federal, CRF do FGTS e CNDT não têm consulta automatizada na v1 — as fontes existem, o acesso programático não. Elas são SupplierDocument com número, órgão, emissão e vencimento digitados ou lidos do PDF enviado, e o status continua derivado da data (RN-FOR-06). O aviso dispara antes do vencimento — 30, 15 e 5 dias —, nunca só depois: certidão avisada no dia seguinte ao vencimento é pedido travado sem aviso prévio. A automação é pendência nomeada com dono, na seção de pendências; enquanto não existir, a página diz que não existe, em vez de prometer varredura que ninguém escreveu.

RN-FOR-27

O bloco bancário segue o tipo de pessoa

accountKind = Domestic exige ISPB, agência e conta e aceita chave PIX; International exige IBAN ou conta mais código de compensação local, SWIFT/BIC e país, e aceita banco intermediário. Foreign aceita os dois blocos — há fornecedor estrangeiro com conta no Brasil. Company, MEI, Individual e RuralProducer aceitam apenas Domestic na v1. Campo do bloco errado responde 400 SUPPLIER_FIELD_NOT_APPLICABLE, nomeando campo e bloco. Por quê: o produto sustenta Foreign com moeda, incoterm e um módulo de câmbio inteiro — havia onde comprar e não havia onde pagar.

Camada API

Endpoints

Prefixo api/v{version}/nexio, [Authorize] e uma permissão explícita por endpoint. Sucesso 200, inclusive nos POST.

RotaPermissãoObservação
GET /suppliersread:suppliersPaged. Filtros: search, relacionamento, statusProcesso, bloqueado, categoryNodeId, comDocumentoVencido, faixaRisco, uf.
GET /suppliers/{id}read:suppliersCompleto, com estabelecimentos, endereços, contatos, documentos e homologações.
POST /supplierscreate:suppliersNasce em Draft / Prospect.
PUT /suppliers/{id}update:suppliersCampos bancários rejeitados aqui — usam o fluxo de proposta.
POST /suppliers/lookup-cnpjread:suppliersConsulta o CNPJ e devolve os dados para autopreenchimento sem gravar, junto com o resultado da checagem de duplicidade.
POST /suppliers/{id}/submitcreate:suppliersEnvia para análise: abre a instância SUPPLIER_REGISTRATION no motor e põe o cadastro em UnderReview.
sem rota própria—Aprovar e recusar o cadastro é decisão do motor, na tarefa da instância (POST /approvals/{id}/assignments/{aid}/approve · /reject). Ao terminar, o Fornecedor grava Approved ou Rejected com a quádrupla de motivo — uso SupplierReject, ver Motivo. Até a v2.4 existia POST /suppliers/{id}/approve · /reject.
POST /suppliers/{id}/promoteapprove:suppliersProspect → SpendAuthorized. Motivo codificado obrigatório na promoção manual — uso SupplierManualPromotion. Vinte por mês é o processo de homologação sendo contornado, e agora aparece no relatório.
POST /suppliers/{id}/block · /unblockblock:suppliersMotivo codificado obrigatório nos dois sentidos — SupplierBlock e SupplierUnblock. O desbloqueio é o ato silencioso, e é o primeiro que uma auditoria de compras procura.
GET /suppliers/{id}/establishments POST PUTupdate:suppliersCNPJ validado e único.
PUT /suppliers/{id}/addresses · /contactsupdate:suppliersReescrevem o conjunto. E-mail e telefone de contato Finance são rejeitados aqui — usam o fluxo de proposta (409 SUPPLIER_CONTACT_PROTECTED_FIELD_CONFLICT). Criar, inativar ou trocar o papel de um contato Finance cai na mesma regra: é troca de canal por outro caminho.
POST /suppliers/{id}/contacts/change-proposalspropose:supplier-banksNovo. Proposta de alteração do canal de aviso — changeKind = NoticeContact na mesma entidade da proposta bancária, mesma instância BANK_ACCOUNT_CHANGE, mesmo aviso no canal anterior. A permissão é a bancária de propósito: quem propõe canal está mexendo no controle de fraude, não no cadastro.
POST /suppliers/{id}/documentsupdate:suppliersMultipart. Tipo, número, emissão e vencimento conforme o tipo exige. supplierEstablishmentId obrigatório quando o tipo é de escopo Establishment.
GET /suppliers/{id}/document-requirementsread:suppliersResolve o pacote exigido dado categorias e faixa de risco, com o que está pendente, vencido e dispensado — por alvo: a raiz e cada estabelecimento ativo, cada um com a sua lista. Aceita ?supplierEstablishmentId= para pedir um alvo só.
POST /suppliers/{id}/verificationsverify:suppliersDispara consulta às fontes escolhidas e grava o resultado.
GET /suppliers/{id}/verificationsread:suppliersHistórico append-only.
GET /suppliers/{id}/bank-accountsread:supplier-banksPermissão própria. Números mascarados salvo permissão elevada. Devolve accountKind e usableFrom; conta em carência vem marcada como tal.
POST /suppliers/{id}/bank-accounts/change-proposalspropose:supplier-banksCria a proposta. Nunca altera o registro vivo.
sem rota própria—A proposta é decidida na instância BANK_ACCOUNT_CHANGE do motor; ao terminar em Approved, o Fornecedor aplica ao registro vivo e inicia a carência. Até a v2.4 existia POST /bank-change-proposals/{id}/approve · /reject.
GET /suppliers/{id}/qualifications POSTmanage:supplier-qualificationsHomologação por categoria. Submeter abre a instância SUPPLIER; a decisão por área é do motor. O GET aceita ?categoryNodeId= e ?onDate= e é a consulta de autorização de gasto da RN-FOR-24 — quem emite pedido chama isto, não lê estado.
PUT /suppliers/{id}/categoriesupdate:suppliersCategorias declaradas.
GET /suppliers/{id}/performanceread:suppliersAgregados de OTIF, atraso, divergência e aderência de preço.
POST /suppliers/invitecreate:suppliersConvite de autocadastro por e-mail, com escopo de categorias sugerido.
GET /suppliers/{id}/auditread:supplier-auditDiff de campos e log de acesso a dado pessoal.

Contrato

Códigos de erro

CódigoHTTPQuando
SUPPLIER_NOT_FOUND404Fornecedor inexistente no tenant
SUPPLIER_CNPJ_INVALID400Formato ou dígito verificador inválido
SUPPLIER_CPF_INVALID400CPF inválido em fornecedor pessoa física
SUPPLIER_FIELD_NOT_APPLICABLE400Campo preenchido que o tipo de pessoa não usa
SUPPLIER_IE_STATE_REQUIRED400Inscrição estadual informada sem UF
SUPPLIER_PRIMARY_ESTABLISHMENT_REQUIRED400Nenhum ou mais de um estabelecimento principal
SUPPLIER_DUPLICATE_CONFLICT409CNPJ, CPF ou taxIdCountry + foreignTaxId já cadastrado, inclusive em rascunho ou pendente. Nome do existente exposto só a usuário interno
SUPPLIER_VERSION_CONFLICT409Versão defasada no PUT
SUPPLIER_NOT_SPEND_AUTHORIZED_CONFLICT409Pedido para fornecedor em Prospect
SUPPLIER_BLOCKED_CONFLICT409Operação em fornecedor bloqueado — mensagem traz o motivo
SUPPLIER_STATE_TRANSITION_CONFLICT409Transição de processo inválida
SUPPLIER_HAS_DOCUMENTS_CONFLICT409Exclusão de fornecedor com RFQ, pedido ou nota
SUPPLIER_REQUIRED_DOCUMENTS_MISSING_UNPROCESSABLE422Homologação sem os documentos exigidos — lista os tipos faltantes
SUPPLIER_DOCUMENT_EXPIRED_CONFLICT409Novo pedido com documento vencido de política bloqueante
SUPPLIER_REGISTRATION_STATUS_NOT_ACTIVE_UNPROCESSABLE422Homologação de fornecedor com situação cadastral diferente de Ativa
QUALIFICATION_SCOPE_REQUIRED400Homologação sem categorias no escopo
BANK_CHANGE_REQUIRES_PROPOSAL_CONFLICT409Tentativa de alterar campo bancário protegido por PUT direto
BANK_CHANGE_APPROVER_IS_REQUESTER_CONFLICT409Aprovador igual ao solicitante
BANK_HOLDER_MISMATCH_CONFLICT409Documento do titular não confere com o do fornecedor
BANK_PIX_KEY_UNVERIFIED_UNPROCESSABLE422Chave aleatória sem resolução de titularidade
SUPPLIER_NOT_QUALIFIED_FOR_CATEGORY_CONFLICT409Linha de documento cuja categoria não é coberta por qualificação vigente — nomeia o nó pedido
SUPPLIER_CONTACT_PROTECTED_FIELD_CONFLICT409Alteração de e-mail ou telefone de contato Finance fora do fluxo de proposta
SUPPLIER_DOCUMENT_ESTABLISHMENT_REQUIRED400Documento de escopo Establishment sem supplierEstablishmentId, ou de escopo Supplier com ele
BANK_ACCOUNT_NOT_USABLE_YET_CONFLICT409Conta pedida como destino de pagamento antes de usableFrom
BANK_CHANGE_NOTICE_WINDOW_NOT_ELAPSED_CONFLICT409Decisão tentada antes de noticeSentAt + minNoticeHours
BANK_CHANGE_NO_EXTERNAL_NOTICE_CHANNEL_UNPROCESSABLE422Proposta bancária ou de canal sem nenhum contato do fornecedor com e-mail ou telefone

Autorização

Permissões

PermissãoCobre
read:suppliers · create:suppliers · update:suppliers · delete:suppliersCRUD do cadastro
approve:suppliersPromover manualmente a homologado; e é o alvo da política padrão de SUPPLIER_REGISTRATION — quem a tem recebe as tarefas de aprovação do cadastro no motor
block:suppliersBloquear e desbloquear
verify:suppliersDisparar consultas a fontes oficiais
manage:supplier-qualificationsHomologação, questionários e requisitos de documento; alvo da política padrão de SUPPLIER
read:supplier-banksVer dados bancários — números mascarados por padrão
propose:supplier-banksSolicitar alteração bancária e alteração do canal de aviso (e-mail e telefone do contato Finance) — os dois são o mesmo controle
approve:supplier-banksAlvo da política semeada de BANK_ACCOUNT_CHANGE, nos dois changeKind — quem a tem recebe as tarefas no motor, e o degrau incondicional exige duas delas. Não deve estar no mesmo perfil de propose; e update:suppliers sozinho não muda canal de aviso, que é o buraco que a RN-FOR-21 fecha
read:supplier-auditHistórico e log de acesso a dado pessoal

Grupos sugeridos: Nexio - Fornecedores (read/create/update), Nexio - Homologação (+ approve, verify, qualification), Nexio - Tesouraria (read:supplier-banks + approve:supplier-banks, sem propose) e Nexio - Consulta (read). A separação entre quem propõe e quem aprova mudança bancária é a razão de existirem duas permissões.

Contrato vigente · revisão consolidada

Dados pessoais e base legal

CPF, contatos e dados bancários de pessoas naturais exigem finalidade, minimização, controle de acesso e política de retenção por categoria. A execução de contrato ou procedimentos preliminares a pedido do titular está no art. 7º, V da LGPD; o inciso VI trata do exercício regular de direitos em processo. Não presumir uma única base legal para todos os tratamentos. Lei 13.709, art. 7º.

Registrar a finalidade e a base aplicável, mascarar dados em consulta geral e auditar acesso aos dados sensíveis para a operação, inclusive exportações. Retenção segue necessidade, obrigações legais aplicáveis e legal hold; não adotar prazo único para todo cadastro ou impedir indefinidamente direitos do titular por referência genérica à auditoria.

Exclusão lógica preserva integridade comercial, mas não substitui procedimento de anonimização, atendimento ao titular e expurgo permitido. Logs, anexos, backups e integrações devem constar do inventário de dados. A documentação define o requisito; a adequação operacional precisa ser comprovada antes do primeiro cliente.

Limites

Fora de escopo e pendências

É do ERP financeiro
  • Título a pagar, aging, provisão, saldo em aberto. O Nexio pode exibir por integração; não é fonte da verdade.
  • Cálculo de retenções (IRRF, INSS, ISS, CSRF), códigos de DARF, alíquotas. O Nexio carrega os insumos — regime tributário, IE, IM, natureza do serviço; quem calcula é o ERP fiscal. Resista ao pedido de incluir "só o campo de retenção": ele nunca vem sozinho.
  • Conta contábil do fornecedor, plano de contas, conta de reconciliação.
  • Calendário de vencimento, juros, multa e desconto. O prazo negociado é do Nexio; o cálculo é financeiro.
  • Escrituração: EFD-Reinf, DCTFWeb, SPED, comprovantes de retenção.
  • Remessa e retorno CNAB, conciliação bancária, arquivo de pagamento.
  • Limite de crédito e campos de 1099 e afins, herdados de produtos americanos.
Fora agora, previsto no modelo
  • Site comercial do fornecedor — condição de pagamento e moeda por unidade de relacionamento. Hoje ficam no estabelecimento.
  • Ponto de entrega específico no ItemSupplier — o eixo ship-to da ASL na granularidade do site. A UF de destino já está na chave do preço desde 02/09/2026; o que continua fora é o preço por ponto, que é negociação e mora no Contract.
  • Portal do fornecedor — autocadastro, upload de documento e resposta a RFQ pelo próprio fornecedor. PortalUser existe no modelo; o portal é projeto próprio.
  • Scorecard com avaliação humana — as métricas calculadas vêm primeiro.
  • Integração cXML / punchout — projeto próprio, não campo de cadastro.
  • Consulta automatizada a CND/CPEN, CRF do FGTS e CNDT — nenhuma das três tem API pública; todas são cobertas por serviços comerciais. Na v1 são entrada manual com vigência (RN-FOR-26). Dono: a decisão (a) do quadro abaixo — quem fornecer a consulta de CNPJ é quem fornecerá as certidões, e é uma escolha só, não duas.

Pendências para decidir. (a) Qual fonte de consulta ao CNPJ: base própria a partir dos dados abertos, ou serviço comercial com SLA — a primeira dá soberania e custo previsível, a segunda dá atualidade. (b) O Nexio guarda dados bancários, ou só referencia o que está no ERP? A resposta muda o peso de toda a seção de segurança. (c) Base compartilhada de fornecedores entre tenants — decisão jurídica antes de produto. (d) Contatos e sócios: o quadro societário vem da Receita e é dado pessoal; entra no MVP ou fica para quando houver due diligence formal?

Contrato vigente · revisão consolidada

Identidade comercial e verificações

Oferta e preço seguem ItemSupplierOffer e ItemSupplierPrice. Cadastro oficial, opção fiscal, sanções e verificação bancária guardam provedor, data, resultado e evidência; consulta ausente ou vencida não equivale a resultado favorável.

Aviso de mudança bancária é durável e usa o contato anterior protegido. noticeSentAt significa entrega aceita pelo provedor do canal, com identidade de mensagem e resultado persistidos, não apenas intenção em memória. Repetição não reinicia a carência. A identidade convidada pelo e-mail não prova a pessoa física autora; a trilha registra o meio efetivamente verificado.