Conversando toda semana com CTOs e fundadores de Software Houses que estão migrando da Nuvem Fiscal API, do PlugNotas (TecnoSpeed) ou da Focus NFe para a Notaas, percebo que o gatilho da mudança quase sempre começa na planilha financeira do SaaS, mas termina na arquitetura de engenharia.
Quando uma startup ou ERP vertical está no início, qualquer API funciona. Porém, assim que a carteira passa de 15, 50 ou 200 CNPJs emitentes, duas dores batem à porta simultaneamente: primeiro, a conta mensal da API fiscal explode porque a maioria dos provedores tradicionais cobra adicional por CNPJ cadastrado (mesmo quando aquele cliente do seu ERP emite apenas 5 notas por mês ou ainda está em fase de implantação) ou exige mensalidades mínimas de R$ 250 a R$ 600+/mês logo na largada. Segundo, a manutenção de múltiplos endpoints heterogêneos, o atraso na geração de PDF do DANFSe Nacional e a parametrização manual da Reforma Tributária (IBS/CBS) drenam horas preciosas do time de produto.
Mesmo assim, muitos Tech Leads adiam a troca de provedor por um medo legítimo: "Se eu mexer no motor fiscal hoje, vou ter colisão de numeração de RPS/NF-e nos meus clientes e correr o risco de parar o faturamento na virada do mês."
Escrevi este guia de engenharia exatamente para eliminar esse risco. Vamos analisar de forma transparente a matemática de custos (Nuvem Fiscal planos, PlugNotas preço e Focus NFe comparados ao modelo de CNPJs ilimitados da Notaas) e, em seguida, implementar passo a passo uma migração multi-CNPJ com Zero-Downtime em TypeScript, utilizando sincronização prévia de numeração via Org API e o padrão de projeto Adapter Pattern com Canary Rollout por CNPJ.
A Matemática do TCO para Software Houses: Nuvem Fiscal Planos, PlugNotas Preço e Focus NFe vs. Notaas
Se você já pesquisou sobre nuvem fiscal planos, plugnotas preço ou a tabela para Software Houses da Focus NFe, já notou que o mercado de mensageria fiscal no Brasil foi desenhado na década passada com foco em empresas emissoras únicas de alto volume, e não na realidade de um Micro-SaaS, ERP Cloud ou plataforma de BPO Contábil que possui dezenas de clientes pequenos e médios.
Enquanto no nosso comparativo geral das APIs de emissão de NF-e, NFS-e e NFC-e avaliamos recursos gerais de plataforma, aqui o foco é o Custo Total de Propriedade (TCO) e a Developer Experience (DX) em cenários Multi-CNPJ:
| Critério de Engenharia & Custo | PlugNotas (TecnoSpeed) | Focus NFe | Nuvem Fiscal API | Notaas (Org API Multi-Tenant) |
|---|---|---|---|---|
| Barreira de Entrada & Homologação Multi-CNPJ | Exige negociação comercial e contrato mínimo mensal elevado para parceiros de software. | Ambiente de testes disponível, mas planos de produção exigem franquia mínima mensal fixa. | Possui cota gratuita inicial, mas limita recursos empresariais e escala por faixa de volume/empresa. | R$ 0/mês no Plano Free: até 3 Organization Tokens, 5 CNPJs simultâneos grátis em Homologação + 1 CNPJ em Produção (20 notas/mês) sem cartão. |
| Escada de Preço para Crescimento (Ramp-up) | Mensalidades iniciais na faixa de R$ 250 a R$ 500+/mês somadas a cobranças por CNPJ ativo ou pacote de documentos. | Cobrança de franquia base + taxa adicional por CNPJ emitente ativo na carteira da Software House. | Planos escalonados onde o custo cresce conforme o volume e o suporte técnico dedicado sobe de faixa. | Plano Dev (R$ 99/mês): até 3 CNPJs em Produção (500 notas/mês). Plano SaaS Pro (R$ 249/mês): CNPJs Ilimitados em Produção + 2.500 notas/mês. |
| Geração do DANFSe v2.0 (NT-008 Padrão Nacional) | Depende de consultas ou layouts intermediários que sofrem quando o ADN oscila. | Frequentemente impactado pela instabilidade do visualizador público do ADN (adn.nfse.gov.br). |
Depende da disponibilidade síncrona dos serviços da Receita Federal para retorno do PDF oficial. | Geração 100% local e instantânea do DANFSe v2.0 (além da biblioteca open-source MIT @notaas/danfse-viewer). |
| Defaults de IBS/CBS (Anexo VIII) por CNPJ | Exige atualização dos campos da Reforma Tributária no payload de emissão do ERP. | Exige envio explícito das tags de IBS/CBS em cada requisição HTTP de nota. | Exige mapeamento manual do bloco IBSCBS no JSON de cada documento emitido. |
Herança automática via Org API (PATCH /api/v1/org/projects/{id}) sem alterar o payload de emissão do ERP. |
| Integração Nativa com Agentes de IA (MCP) | Não possui servidor MCP oficial. | Não possui servidor MCP oficial. | Não possui servidor MCP oficial. | @notaas/mcp v0.2.1 com 44 Tools prontas para Cursor, Claude Code e Windsurf. |
O problema oculto do "Custo por CNPJ Ativo" em ERPs
Imagine uma Software House que vende um sistema de gestão por R$ 149/mês para clínicas, agências de publicidade ou pequenos comércios. Se você tem 80 clientes na base e cada um emite apenas 15 a 25 notas fiscais por mês (totalizando 1.600 notas/mês na operação inteira):
- Em APIs que cobram adicional de R$ 15 a R$ 35 por CNPJ ativo além da franquia, sua fatura fiscal passa facilmente de R$ 1.500 a R$ 2.800 por mês.
- Na Notaas, como o Plano SaaS Pro (R$ 249/mês) inclui CNPJs ilimitados em produção e uma franquia global compartilhada de 2.500 notas/mês, esses mesmos 80 CNPJs custam exatamente R$ 249/mês no total. Você economiza mais de R$ 15.000 por ano em infraestrutura fiscal logo de cara, mantendo isolamento criptográfico total de certificados A1 e tokens por cliente.
Arquitetura de Migração Multi-CNPJ Zero-Downtime em 4 Etapas
Migrar dezenas ou centenas de clientes de uma API fiscal legada para a Org API multi-tenant da Notaas não deve ser feito num "Big Bang" na sexta-feira à noite.
Aqui na Notaas, desenhamos com os times de engenharia parceiros um protocolo em 4 etapas determinísticas que garante zero indisponibilidade e zero risco de duplicidade de numeração (Rejeição 539 na NF-e/NFC-e ou erro de RPS já informado na NFS-e):
⚡ Fluxo Arquitetural de Migração Zero-Downtime (Canary Rollout):
- 1. Provisionamento Silencioso (
POST /api/v1/org/projects): Um script de backoffice lê os CNPJs ativos no banco do seu ERP, cria os projetos isolados na Notaas via Org API e faz o upload dos arquivos.pfx(Certificado A1) já armazenados no seu cofre.- 2. Sincronização de Ponteiro de Série/Numeração (
PATCH /api/v1/org/projects/{id}/numeracao): Para cada CNPJ, o script consulta o último número de RPS, NF-e (Mod 55) e NFC-e (Mod 65) autorizado no provedor antigo e grava o ponteiro inicial na Notaas (ultimoNumero + 1).- 3. Camada de Abstração (
FiscalProviderAdapter): Seu backend encapsula a chamada HTTP dentro de uma interface única que traduz o domínio interno do ERP para o provedor antigo ou para a Notaas de acordo com uma flagfiscal_provider = 'notaas' | 'legacy'na tabela de tenants.- 4. Virada Canary (5% ➔ 25% ➔ 100%): Você altera a flag no banco para 3 clientes piloto, valida o retorno do webhook
invoice.issuede o DANFSe/DANFE em PDF, e depois executa umUPDATE tenants SET fiscal_provider = 'notaas'para toda a carteira.
Vamos ao código real de cada etapa.
Provisionamento em Lote e Sincronização de Numeração via TypeScript
O maior erro ao trocar de API fiscal é esquecer de sincronizar a numeração atual de RPS (na NFS-e) ou a série/número da NF-e e NFC-e. Se o seu cliente emitiu a nota nº 1450 na Nuvem Fiscal, na Focus NFe ou no PlugNotas e você simplesmente criar o CNPJ em outra API começando do número 1, a SEFAZ ou a prefeitura vai rejeitar a nota por duplicidade de numeração.
O script abaixo resolve o onboarding completo de cada CNPJ da sua base: cria o projeto na Org API, sobe o certificado digital .pfx em Base64, sincroniza o ponteiro de numeração (numeracao) e já configura os defaults da Reforma Tributária:
import fs from "node:fs/promises";
interface LegacyTenantRecord {
tenantId: string;
razaoSocial: string;
cnpj: string;
inscricaoMunicipal: string;
inscricaoEstadual?: string;
codigoIbge: string;
regimeTributario: 1 | 2 | 3; // 1=Simples, 2=Simples Excesso, 3=Regime Normal
pfxFilePath: string;
pfxPassword: string;
// Últimos números autorizados na Nuvem Fiscal / Focus NFe / PlugNotas
lastAuthorizedRpsNumber: number;
rpsSerie: string;
lastAuthorizedNfeNumber?: number;
nfeSerie?: string;
}
const NOTAAS_BASE_URL = "https://platform.notaas.com.br/api/v1";
const ORG_API_KEY = process.env.NOTAAS_ORG_API_KEY!;
export async function migrateTenantToNotaas(tenant: LegacyTenantRecord) {
// 1. Cria o Projeto isolado para o CNPJ via Org API
const createRes = await fetch(`${NOTAAS_BASE_URL}/org/projects`, {
method: "POST",
headers: {
"Authorization": `Bearer ${ORG_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
name: tenant.razaoSocial,
cnpj: tenant.cnpj,
inscricaoMunicipal: tenant.inscricaoMunicipal,
inscricaoEstadual: tenant.inscricaoEstadual,
municipioIbge: tenant.codigoIbge,
regimeTributario: tenant.regimeTributario,
environment: "production",
}),
});
if (!createRes.ok) {
throw new Error(`Erro ao criar projeto para CNPJ ${tenant.cnpj}: ${await createRes.text()}`);
}
const { projectId, apiKey } = (await createRes.json()) as {
projectId: string;
apiKey: string;
};
// 2. Faz o upload do Certificado A1 (.pfx) para o cofre AES-256-GCM do projeto
const pfxBuffer = await fs.readFile(tenant.pfxFilePath);
const certRes = await fetch(`${NOTAAS_BASE_URL}/org/projects/${projectId}/certificate`, {
method: "POST",
headers: {
"Authorization": `Bearer ${ORG_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
certificateBase64: pfxBuffer.toString("base64"),
password: tenant.pfxPassword,
}),
});
if (!certRes.ok) {
throw new Error(`Erro no upload do certificado A1 (${tenant.cnpj}): ${await certRes.text()}`);
}
// 3. Sincroniza o ponteiro de numeração para evitar colisão de RPS / NF-e
const numRes = await fetch(`${NOTAAS_BASE_URL}/org/projects/${projectId}/numeracao`, {
method: "PATCH",
headers: {
"Authorization": `Bearer ${ORG_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
nfse: {
serieRps: tenant.rpsSerie,
proximoNumeroRps: tenant.lastAuthorizedRpsNumber + 1,
},
...(tenant.lastAuthorizedNfeNumber
? {
nfe: {
serie: tenant.nfeSerie || "1",
proximoNumero: tenant.lastAuthorizedNfeNumber + 1,
},
}
: {}),
}),
});
if (!numRes.ok) {
throw new Error(`Erro ao sincronizar numeração (${tenant.cnpj}): ${await numRes.text()}`);
}
console.log(
`[MIGRADO] CNPJ ${tenant.cnpj} -> ProjectID: ${projectId} (Próximo RPS: ${
tenant.lastAuthorizedRpsNumber + 1
})`
);
// Salve projectId e apiKey na tabela de tenants do seu ERP
return { projectId, apiKey };
}
Tabela De-Para de Payloads JSON (Nuvem Fiscal, Focus NFe e PlugNotas para Notaas)
Um dos maiores alívios relatados pelos desenvolvedores que migram para a API NFS-e Nacional da Notaas, bem como para nossos endpoints de API NF-e (Modelo 55) e API NFC-e (Modelo 65), é a eliminação do aninhamento profundo de tags XML disfarçadas de JSON (DPS.infDPS.prest, valores.vServPrest.vServ).
Abaixo está o mapeamento direto (De-Para) dos campos principais para você construir ou gerar no Cursor/Claude Code seu tradutor de payload em minutos:
| Conceito no Domínio do ERP | Nuvem Fiscal API (POST /nfse/dps) |
Focus NFe (POST /v2/nfse) |
PlugNotas (POST /nfse) |
Notaas (POST /api/v1/emitir) |
|---|---|---|---|---|
| Chave de Idempotência | referencia |
?ref=ID (Query param) |
idIntegracao |
externalId ou referencia |
| Ambiente de Emissão | ambiente (1 ou 2) |
Definido pela URL de host | Definido pela conta/header | ambiente ("producao" / "homologacao") |
| CNPJ do Prestador | infDPS.prest.CNPJ |
prestador.cnpj |
prestador.cpfCnpj |
prestador.cnpj |
| Documento do Tomador | infDPS.toma.CNPJ / CPF |
tomador.cnpj / cpf |
tomador.cpfCnpj |
tomador.cpfCnpj (aceita CPF ou CNPJ limpo) |
| Município do Tomador | infDPS.toma.end.endNac.cMun |
tomador.endereco.codigo_municipio |
tomador.endereco.codigoCidade |
tomador.endereco.codigoMunicipio |
| Código do Serviço (LC 116 / Nacional) | infDPS.serv.cServ.cTribNac |
servico.item_lista_servico |
servico.codigo |
servico.codigo (aceita "01.05" ou "010501") |
| Valor do Serviço | infDPS.valores.vServPrest.vServ |
servico.valor_servicos |
servico.valor.servico |
servico.valor (number, ex.: 1500.00) |
| Alíquota de ISS (%) | infDPS.valores.trib.tribMun.pAliq |
servico.aliquota |
servico.iss.aliquota |
servico.aliquota (number, ex.: 2.0) |
| Reforma Tributária (IBS/CBS) | infDPS.valores.trib.IBSCBS.* |
servico.ibs_cbs.* |
servico.ibscbs.* |
ibscbs (ou automático via Defaults do Projeto) |
Implementando o FiscalProviderAdapter com Feature Flag (Canary Rollout)
Para virar a chave em produção com segurança cirúrgica, nunca apague o código do provedor antigo de uma vez. Implemente uma interface FiscalProviderAdapter e selecione o driver dinamicamente por CNPJ (ou por percentual da base).
Veja a implementação limpa em TypeScript que permite rodar o provedor antigo e a Notaas lado a lado e virar 100% do tráfego alterando apenas uma coluna no banco de dados:
export interface ErpInvoiceCommand {
orderId: string;
tenant: {
id: string;
cnpj: string;
fiscalProvider: "legacy" | "notaas";
notaasApiKey: string;
legacyToken?: string;
};
customer: {
document: string;
name: string;
email: string;
address: {
street: string;
number: string;
district: string;
ibgeCode: string;
state: string;
zipCode: string;
};
};
service: {
code: string;
description: string;
amount: number;
issRate: number;
};
}
export interface FiscalEmissionResult {
provider: "legacy" | "notaas";
trackingId: string;
status: "processing" | "authorized";
}
export class NotaasFiscalAdapter {
async emitNfse(cmd: ErpInvoiceCommand): Promise<FiscalEmissionResult> {
const externalId = `erp_order_${cmd.tenant.id}_${cmd.orderId}`;
const response = await fetch("https://platform.notaas.com.br/api/v1/emitir", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-Key": cmd.tenant.notaasApiKey,
},
body: JSON.stringify({
tipo: "nfse",
ambiente: "producao",
externalId,
prestador: {
cnpj: cmd.tenant.cnpj,
},
tomador: {
cpfCnpj: cmd.customer.document,
razaoSocial: cmd.customer.name,
email: cmd.customer.email,
endereco: {
logradouro: cmd.customer.address.street,
numero: cmd.customer.address.number,
bairro: cmd.customer.address.district,
codigoMunicipio: cmd.customer.address.ibgeCode,
uf: cmd.customer.address.state,
cep: cmd.customer.address.zipCode,
},
},
servico: {
codigo: cmd.service.code,
descricao: cmd.service.description,
valor: cmd.service.amount,
aliquota: cmd.service.issRate,
},
// Os campos de IBS/CBS (Anexo VIII) são herdados automaticamente
// dos defaults do projeto configurados na Org API!
}),
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`Falha na emissão Notaas (${response.status}): ${errorText}`);
}
const data = await response.json();
return {
provider: "notaas",
trackingId: data.id,
status: data.status === "autorizada" ? "authorized" : "processing",
};
}
}
// Roteador Canary por Tenant no seu Service de Faturamento
export async function dispatchInvoiceByTenantFlag(
cmd: ErpInvoiceCommand,
notaasAdapter: NotaasFiscalAdapter,
legacyAdapter: { emitNfse: (c: ErpInvoiceCommand) => Promise<FiscalEmissionResult> }
): Promise<FiscalEmissionResult> {
if (cmd.tenant.fiscalProvider === "notaas") {
return notaasAdapter.emitNfse(cmd);
}
return legacyAdapter.emitNfse(cmd);
}
Com esse adaptador em produção, o roteiro de virada na sua Software House leva menos de uma tarde:
- Você roda o script de onboarding da Etapa 1 para cadastrar seus CNPJs na Notaas.
- Escolhe 3 clientes de confiança e executa
UPDATE tenants SET fiscal_provider = 'notaas' WHERE id IN (...). - Acompanha os primeiros webhooks
invoice.issuedchegando com o XML assinado e o DANFSe v2.0 gerado localmente (sem depender do visualizador instável do ADN). - Com tudo validado, roda o
UPDATEpara os 95% restantes da base e cancela a assinatura antiga antes da renovação do ciclo de faturamento.
E se a sua equipe quiser acelerar ainda mais a criação do adaptador, basta instalar nosso servidor MCP (npx -y @notaas/mcp) no Cursor ou Claude Code: o agente lê o arquivo atual de integração da Nuvem Fiscal, Focus NFe ou PlugNotas no seu repositório e gera a classe NotaasFiscalAdapter já tipada com os schemas do seu projeto. Para entender como lidamos com os novos campos fiscais sem quebrar integrações legadas, veja também nosso artigo sobre como implementar IBS/CBS e o Anexo VIII na NFS-e sem erros E363 e E637.
Perguntas Frequentes sobre Migração para a Notaas
1. Como funciona a cobrança por CNPJ na Notaas em comparação com Nuvem Fiscal planos e PlugNotas preço?
Na Notaas, você não é penalizado por crescer sua carteira de clientes. No Plano Free (R$ 0/mês), você tem até 3 Organization Tokens, 5 CNPJs simultâneos grátis em Homologação e 1 CNPJ em Produção com 20 notas fiscais gratuitas por mês. No Plano Dev (R$ 99/mês), você opera até 3 CNPJs em Produção com 500 notas/mês. Já no Plano SaaS Pro (R$ 249/mês), você tem CNPJs ilimitados em Produção compartilhando uma franquia de 2.500 notas/mês — sem pagar taxa extra a cada novo cliente que assina o seu ERP.
2. Preciso pedir para o meu cliente final enviar o Certificado Digital A1 (.pfx) novamente durante a migração?
Não, desde que o seu ERP já armazene o arquivo .pfx/.p12 e a senha de forma criptografada no seu próprio servidor ou bucket privado. Basta usar o endpoint POST /api/v1/org/projects/{id}/certificate da Org API da Notaas para transferir os certificados programaticamente em lote, tornando a migração 100% invisível para o usuário final do seu software.
3. O que acontece com as notas fiscais emitidas anteriormente na Focus NFe, PlugNotas ou Nuvem Fiscal?
As notas emitidas no passado continuam válidas na SEFAZ e no Ambiente Nacional da NFS-e, e recomendamos que você faça o backup dos XMLs históricos no seu próprio storage (S3/R2). Ao sincronizar o ponteiro de numeração via PATCH /api/v1/org/projects/{id}/numeracao, a Notaas assume a sequência exatamente a partir do próximo número disponível (ultimoNumero + 1), mantendo a continuidade contábil perfeita.
Migre sua Carteira Multi-CNPJ para a Notaas Hoje Mesmo
Pare de pagar taxas por CNPJ ativo ou mensalidades pesadas para manter seu SaaS funcionando. Crie sua conta gratuita na Notaas, gere seu Organization Token e faça o teste de migração em homologação para até 5 CNPJs agora mesmo:
👉 Criar Conta Gratuita na Notaas (5 CNPJs em Homologação + 20 Notas/Mês em Produção)
👉 Consultar a Documentação da Org API e Endpoints de Migração

