Referência da API
Leads e catálogo público de cidades
GET /api/cidades?q= aceita ao menos três caracteres e retorna até oito itens { ibgeCodigo, nome, uf }, priorizando SP. A busca é por prefixo do nome completo, sem diferença de acento ou caixa. Cada consulta pode ser armazenada em cache por cinco minutos.
- Consulta com menos de três caracteres retorna
[]. 429: limite de 60 consultas por IP a cada minuto; aguarde antes de repetir.
POST /api/leads recebe nome, email, telefone, whatsappOptIn e ibgeMunicipio. O IBGE é obrigatório, deve ter sete dígitos e existir no catálogo. O nome da cidade é sempre derivado do catálogo.
Envelope e códigos de erro
As rotas REST v1 usam { "erro": { "codigo", "mensagem", "detalhes" } }; detalhes é opcional.
A resposta anterior { "sucesso": false, "erros": [...] } não é mais emitida pela API REST (breaking change).
O MCP conserva seu contrato próprio de resultado de ferramenta.
| Código | Significado |
|---|---|
VALIDACAO | Corpo ou campo inválido. |
CONFIG | Empresa emissora não pôde ser resolvida. |
PERFIL_TRIBUTARIO | Perfil inválido, inativo ou não encontrado. |
BILLING | Plano ou limite bloqueou a emissão (HTTP 402). |
CONTEUDO_INADEQUADO | Conteúdo fiscal recusado pela política. |
RECONCILIACAO_INDISPONIVEL | Resultado da transmissão não pôde ser confirmado. |
REJEICAO_FISCAL | A prefeitura rejeitou a emissão; o código original permanece em detalhes[0].codigo. |
EMISSAO | Falha de emissão sem código fiscal específico. |
IDEMPOTENCIA_CONFLITO | Mesma chave com corpo diferente. |
IDEMPOTENCIA_MODO | Chave já usada no outro modo de emissão. |
EM_PROCESSAMENTO | Requisição idempotente ainda em andamento. |
LOTE_GRANDE, LOTE_VAZIO, CSV_INVALIDO | Erros de lote. |
INTERNO | Falha interna não detalhada. |
Servidor MCP
O NotasPJ também oferece um servidor MCP remoto em POST /api/mcp. Ele permite que clientes
compatíveis, como Claude Code, Cursor e ChatGPT, consultem dados e emitam NFS-e por linguagem natural.
O transporte é Streamable HTTP stateless: cada chamada é independente e não mantém sessão SSE.
A autenticação usa exclusivamente a API key do NotasPJ no header Bearer:
Authorization: Bearer <chave>
O escopo LEITURA permite as ferramentas de consulta e bloqueia emitir_nfse. O escopo EMISSAO
permite todas as ferramentas. A emissão é real e deve ser confirmada pelo usuário antes da chamada.
Não há ferramenta de cancelamento na v1.
Solução de problemas
- HTTP 401 indica chave ausente ou inválida, ou escopo incompatível com a operação solicitada.
- HTTP 402 indica que o plano atual não inclui integrações.
- Antes de usar em produção, valide a conexão e as ferramentas com a URL do ambiente de homologação.
| Ferramenta | Escopo | Finalidade |
|---|---|---|
listar_empresas | LEITURA | Lista empresas emissoras ativas da conta. |
listar_clientes | LEITURA | Busca clientes por nome ou documento, com paginação. |
listar_perfis_tributarios | LEITURA | Lista perfis cadastrados com filtros e paginação. |
sugerir_perfil_tributario | LEITURA | Sugere um perfil cadastrado para empresa, cliente e serviço. |
consultar_nfse | LEITURA | Consulta notas por empresa, período, status ou tomador. |
obter_nfse | LEITURA | Obtém o detalhe pela chave de acesso e o link da DANFSe. |
emitir_nfse | EMISSAO | Emite uma NFS-e real com o mesmo contrato estruturado da API pública. |
status_uso | LEITURA | Informa notas emitidas no mês e limite do plano. |
Claude Code
claude mcp add --transport http notaspj https://www.notaspj.com.br/api/mcp --header "Authorization: Bearer <chave>"
Cursor
Adicione ao mcp.json:
{
"mcpServers": {
"notaspj": {
"url": "https://www.notaspj.com.br/api/mcp",
"headers": {
"Authorization": "Bearer <chave>"
}
}
}
}
ChatGPT
No modo desenvolvedor, abra Configurações → Conectores, crie um conector MCP remoto com a URL
https://www.notaspj.com.br/api/mcp e configure o header Authorization como Bearer <chave>.
Para validar a integração antes do uso em produção, substitua o domínio dos exemplos por
https://homologacao.notaspj.com.br e use uma chave criada no ambiente de homologação.
API REST para integração de ERPs/sistemas externos. Base: /api/v1.
Autenticação
Emissão, idempotência e formatos
POST /api/v1/nfse aceita números decimais em formato JSON, pt-BR (1.500,00) ou en-US (1,500.00).
Booleanos aceitam boolean, 1/0 e sim/nao (sem distinção entre maiúsculas e minúsculas).
Uma Idempotency-Key não pode ser compartilhada entre emissão síncrona e assíncrona; isso retorna
IDEMPOTENCIA_MODO. Reuso com outro corpo retorna IDEMPOTENCIA_CONFLITO. Em lotes, a chave é derivada
por linha; quando um header é informado, cada linha usa <header>:<linha>. O MCP aceita idempotencyKey
e, quando omitida, deriva uma chave estável do tenant e do formulário.
GET /api/v1/nfse aceita page, limit, status, q, empresaId, competencia (AAAA-MM), de e
ate (datas inclusivas). A paginação e o filtro por status derivado são aplicados no banco.
Toda requisição exige uma API key do tenant (criada em /integracoes):
Authorization: Bearer nfse_xxxxxxxxxxxxxxxxxxxx
# ou
X-API-Key: nfse_xxxxxxxxxxxxxxxxxxxx
- A chave carrega um escopo:
LEITURA(somente GET) ouEMISSAO(total). Rotas de emissão exigemEMISSAO, senão403 ESCOPO_INSUFICIENTE. - O acesso de Integrações é revalidado em cada chamada. Se a assinatura deixar de estar vigente ou o plano não incluir Integrações, a API retorna
403 PLANO_SEM_INTEGRACOESaté a regularização. - Chaves podem expirar e ser rotacionadas (gera nova, invalida a anterior) ou revogadas.
- Rate limit (120 req/min por chave →
429comRetry-After) é entregue pela camada de confiabilidade do Sprint A consolidado no rollout.
Endpoints
| Método | Rota | Escopo | Descrição |
|---|---|---|---|
| POST | /api/v1/nfse | EMISSAO | Emite uma NFS-e. Síncrono por padrão; assíncrono com ?async=true (ou header x-async: true), que retorna um job. |
| GET | /api/v1/nfse | LEITURA | Lista notas do tenant (filtros: status, paginação). |
| GET | /api/v1/nfse/{chaveAcesso} | LEITURA | Detalha uma nota. |
| GET | /api/v1/nfse/{chaveAcesso}/danfse | LEITURA | Baixa a DANFSe (PDF). |
| POST | /api/v1/nfse/lote | EMISSAO | Emissão em lote. |
| GET | /api/v1/empresas | LEITURA | Lista empresas emissoras ativas. |
| GET | /api/v1/perfis-tributarios | LEITURA | Lista perfis tributários cadastrados. |
| GET | /api/v1/perfis-tributarios/{id} | LEITURA | Consulta um perfil tributário. |
| GET | /api/v1/perfis-tributarios/sugerir | LEITURA | Sugere um perfil cadastrado. |
| GET | /api/v1/clientes | LEITURA | Lista ou busca clientes. |
| GET | /api/v1/jobs/{id} | LEITURA | Consulta o status de um job assíncrono. |
| POST | /api/v1/recorrentes | EMISSAO | Cria uma recorrência. |
| GET | /api/v1/recorrentes/{id} | LEITURA | Consulta uma recorrência. |
| PATCH | /api/v1/recorrentes/{id} | EMISSAO | Altera uma recorrência. |
| DELETE | /api/v1/recorrentes/{id} | EMISSAO | Desativa uma recorrência. |
Empresas
GET /api/v1/empresas devolve as empresas ativas com ID, razão social, CNPJ, município, alíquota padrão e regime tributário. Use o id como empresaId nas demais chamadas.
Perfis tributários
GET /api/v1/perfis-tributarios aceita empresaId, ativo (padrão true), clienteId, codigoTribNac, page e limit. O detalhe usa GET /api/v1/perfis-tributarios/{id}. Para uma sugestão, chame GET /api/v1/perfis-tributarios/sugerir?empresaId=7&clienteId=11&codigoTribNac=010101; apenas empresaId é obrigatório.
O fluxo recomendado é listar empresas, listar ou sugerir um perfil já cadastrado na tela Perfis tributários e enviar o ID escolhido como perfilTributarioId no POST da nota. API, lote e MCP não aplicam perfis automaticamente.
Emissão em lote
O JSON recebe notas com as mesmas propriedades aceitas pela emissão avulsa. O CSV oferece essas propriedades
como colunas, aceita ;, , ou tabulação e decodifica UTF-8 ou Windows-1252. O corpo é limitado a 2 MB.
O perfilTributarioId de cada item deve ser obtido na tela ou em GET /api/v1/perfis-tributarios.
Sem async=true, o processamento é síncrono e aceita no máximo 5 linhas; lotes maiores retornam 413
LOTE_GRANDE e devem usar ?async=true. O modo assíncrono aceita até 500 linhas. Quando há mais de uma empresa
emissora ativa, toda nota deve informar empresaId; sua ausência retorna 400 CONFIG antes de enfileirar.
O campo codigo de erro é normalizado e codigoOriginal preserva o código da prefeitura quando forem diferentes.
| POST | /api/v1/clientes | EMISSAO | Cadastra um cliente (tomador reutilizável). |
Use clienteId (retornado por POST /api/v1/clientes) nos campos de tomador de POST /api/v1/nfse e POST /api/v1/recorrentes para vincular o cliente cadastrado.
Perfil tributário na emissão
POST /api/v1/nfse, cada item de POST /api/v1/nfse/lote e POST /api/v1/recorrentes aceitam o campo opcional perfilTributarioId. Informe o ID numérico inteiro positivo do perfil, não sua descrição ou código fiscal. O perfil deve existir, estar ativo e pertencer ao mesmo tenant e à empresa emissora.
Os campos não nulos definidos pelo perfil (aliquotaISSQN, tpRetISSQN, codigoTribNac, codigoTribMun, locPrestacaoIBGE e deducaoBaseISS) prevalecem sobre os valores enviados no payload. Campos nulos no perfil mantêm o valor do payload ou o padrão atual. Sem perfilTributarioId, nenhum perfil é aplicado automaticamente.
NFS-e síncrona
POST /api/v1/nfse
{
"empresaId": 7,
"perfilTributarioId": 21,
"tomadorTipo": "CNPJ",
"tomadorDoc": "12345678000190",
"tomadorNome": "Cliente Exemplo",
"descricaoServico": "Consultoria",
"codigoTribNac": "010101",
"codigoTribMun": "0101",
"dataCompetencia": "2026-08",
"valorServico": 1000
}
NFS-e assíncrona
Use o mesmo payload em POST /api/v1/nfse?async=true ou envie o header X-Async: true. O perfilTributarioId é preservado no job.
{
"empresaId": 7,
"perfilTributarioId": 21,
"tomadorTipo": "CNPJ",
"tomadorDoc": "12345678000190",
"tomadorNome": "Cliente Exemplo Assíncrono",
"descricaoServico": "Consultoria mensal",
"codigoTribNac": "010101",
"codigoTribMun": "0101",
"dataCompetencia": "2026-08",
"valorServico": 1200
}
Lote JSON ou CSV
Cada item pode escolher seu próprio perfil. Uma linha inválida é reportada sem impedir o processamento das demais.
{
"notas": [
{
"empresaId": 7,
"perfilTributarioId": 21,
"tomadorTipo": "CNPJ",
"tomadorDoc": "12345678000190",
"tomadorNome": "Cliente do Lote",
"descricaoServico": "Consultoria",
"codigoTribNac": "010101",
"codigoTribMun": "0101",
"dataCompetencia": "2026-08",
"valorServico": 1000
}
]
}
No CSV, use a coluna opcional perfilTributarioId; cada célula preenchida deve conter o ID numérico do perfil. O modelo atualizado pode ser baixado em GET /api/nfse/lote.
Cobrança recorrente
| Método | Rota | Efeito |
|---|---|---|
GET | /api/v1/recorrentes?page=1&limit=20&empresaId=7&ativo=true | Lista paginada e filtrada. pagina/limite seguem aceitos como aliases. |
GET | /api/v1/recorrentes/{id} | Consulta o registro completo. |
POST | /api/v1/recorrentes | Cria uma recorrência. |
PATCH | /api/v1/recorrentes/{id} | Altera os campos informados. |
DELETE | /api/v1/recorrentes/{id} | Desativa de forma irreversível. |
Os campos são os mesmos da tela: empresa e perfil; tomador completo, inclusive telefone, NIF e
endereço estrangeiro; os 18 campos do intermediário; serviço; valores, descontos e dedução;
observações; e-mail; boleto; tipo ILIMITADA ou LIMITADA, quantidade, status e dia (1–28).
locPrestacaoIBGE é opcional; quando omitido, usa o município da empresa.
{
"empresaId": 7,
"perfilTributarioId": 21,
"descricao": "Mensalidade de consultoria",
"tomadorDoc": "12345678000190",
"tomadorNome": "Cliente Recorrente",
"descricaoServico": "Consultoria mensal",
"codigoTribNac": "010101",
"codigoTribMun": "0101",
"valorServico": 1000,
"valorDescontoCondicionado": 50,
"deducaoBaseISS": 100,
"tomadorTelefone": "11999999999",
"tipoRecorrencia": "ILIMITADA",
"emailPara": "financeiro@example.com"
}
Erros 400 do perfil
| Situação | Código | Mensagem |
|---|---|---|
| ID não inteiro, texto, zero ou negativo | PERFIL_TRIBUTARIO | perfilTributarioId deve ser um número inteiro positivo. |
| Perfil inexistente ou de outro tenant | PERFIL_TRIBUTARIO | Perfil tributário não encontrado. |
| Perfil inativo | PERFIL_TRIBUTARIO | Perfil tributário selecionado está inativo. |
| Perfil de outra empresa emissora | PERFIL_TRIBUTARIO | Perfil tributário não pertence à empresa emissora. |
No lote síncrono, o erro aparece no resultado da linha. No lote assíncrono, erros de formato detectados antes da fila aparecem em erros; validações de existência e vínculo feitas pelo núcleo aparecem no status do job correspondente.
Idempotência
Em POST /api/v1/nfse, envie Idempotency-Key: <uuid>. Retry com a mesma chave não gera nota duplicada — devolve a resposta original. Reuso da chave com payload diferente é detectado (hash do corpo).
Erros
Formato: { "erro": { "codigo": "...", "mensagem": "..." } }. Códigos comuns: NAO_AUTORIZADO (401), ESCOPO_INSUFICIENTE (403), PLANO_SEM_INTEGRACOES (403), VALIDACAO (400), NAO_ENCONTRADO (404), rate limit (429), INTERNO (500). PLANO_SEM_INTEGRACOES indica que a assinatura ou o plano atual não dá acesso à API. Emissão bloqueada por billing retorna 402.
Webhooks
Cadastre endpoints em /integracoes. Eventos: nfse.autorizada, nfse.rejeitada, nfse.cancelada.
- Entrega
POSTcom corpo JSON do evento. - Assinatura HMAC-SHA256 no header
X-NotasPJ-Signature(verifique com o segredo do webhook). - Reentrega automática com backoff (Sprint A consolidado) e reenvio manual no painel.
Não confunda com o webhook do Stripe (
/api/billing/webhook), que é interno ao billing da plataforma (assinaturas/faturas), não exposto a integradores.