API de Classificação NCM: Como Integrar ao ERP
Aprenda a integrar classificação NCM e cClassTrib ao ERP com X-API-Key, exemplos em Python e JavaScript e processamento em lote.
Seus NCMs estão corretos?
Um NCM incorreto pode gerar autuação, imposto pago a mais e inconsistências na Reforma Tributária. Audite sua base de produtos com uma IA especializada em classificação fiscal.
20 análises grátis, sem cartão.
Uma API de classificação NCM permite que o ERP envie a descrição de um produto e receba sugestões estruturadas de NCM, hierarquia fiscal, benefícios de IBS/CBS e situações de cClassTrib. A integração reduz o trabalho manual no cadastro e ajuda a manter o mesmo fluxo de análise em diferentes sistemas.
A API do Tax Radar está disponível nos planos Business e Enterprise. Antes de implementar, consulte a visão geral para desenvolvedores, a documentação completa e o OpenAPI público.
O que a API retorna
O endpoint de classificação recebe uma descrição em texto livre e pode retornar:
- até 10 sugestões de NCM;
- probabilidade e faixa de confiança de cada sugestão;
- descrição oficial e hierarquia da NCM;
- benefícios fiscais associados ao código;
- situações possíveis de cClassTrib e CST;
- indicação de compatibilidade com NF-e e NFC-e;
- consumo atualizado do plano.
O resultado é uma sugestão para apoiar a classificação. Descrições genéricas, produtos compostos e operações com condições fiscais específicas podem exigir revisão profissional.
Autenticação e endereço base
Todas as chamadas usam HTTPS e a chave deve ser enviada no cabeçalho X-API-Key:
X-API-Key: sua_chave
O endereço base é:
https://api.taxradar.app/api/v1
Guarde a chave no servidor ou em um gerenciador de segredos. Não coloque a chave no navegador, em aplicativos distribuídos, repositórios ou arquivos versionados.
Classificação de um produto
O endpoint POST /ingest/classify recebe descricao, top_k e, opcionalmente, external_id, ean, ncm_atual e o contexto usado para resolver o cClassTrib. Os metadados do ERP são repetidos na resposta e no histórico, mas não são usados pelo modelo.
curl --fail-with-body -X POST "https://api.taxradar.app/api/v1/ingest/classify" \
-H "X-API-Key: $TAXRADAR_API_KEY" \
-H "Idempotency-Key: 3f32f94d-9b40-4494-a65e-0e8be44d9346" \
-H "Content-Type: application/json" \
-d '{
"external_id": "SKU-001",
"descricao": "ARROZ TIPO 1 LONGO FINO 5KG",
"ean": "7891234567895",
"ncm_atual": "10063021",
"top_k": 3,
"contexto_cclasstrib": {
"tipo_dfe": "nfce"
}
}'
top_k aceita valores de 1 a 10. A quantidade de sugestões não altera o consumo: cada descrição processada utiliza uma classificação do plano.
Trecho da resposta
{
"request_id": "5e34325a-2947-49fd-8c57-b332fdc51dd9",
"external_id": "SKU-001",
"descricao": "ARROZ TIPO 1 LONGO FINO 5KG",
"ean": "7891234567895",
"ncm_atual": "10063021",
"sugestoes": [
{
"ncm": "10063021",
"descricao": "Polido ou brunido",
"probabilidade": 85.2,
"confianca_faixa": "alta",
"hierarquia": {
"capitulo": "10",
"capitulo_desc": "Cereais",
"posicao": "1006",
"posicao_desc": "Arroz"
},
"beneficios": [
{
"tipo": "Alíquota Zero",
"lista": "Anexo I",
"descricao": "Cesta Básica Nacional"
},
{
"tipo": "Redução 60%",
"lista": "Anexo IX",
"descricao": "Insumos Agropecuários"
}
],
"classificacao_tributaria": {
"situacoes": [
{
"cclasstrib": "200003",
"cst": "200",
"ind_nfe": true,
"ind_nfce": true
}
],
"tipo_resolucao": "condicionado",
"cst_padrao": "200"
}
}
],
"usage": {
"current_usage": 1250,
"limit": 500000,
"remaining": 498750,
"plan": "business"
}
}
Use beneficios, no plural. O cClassTrib fica em classificacao_tributaria.situacoes[].cclasstrib; cst_padrao contém o CST de três dígitos.
Implementação em Python
Use variável de ambiente, timeout e validação do status HTTP:
import os
import requests
API_URL = "https://api.taxradar.app/api/v1"
API_KEY = os.environ["TAXRADAR_API_KEY"]
def classificar_produto(
descricao: str,
top_k: int = 3,
contexto: dict | None = None,
) -> dict:
payload = {
"descricao": descricao,
"top_k": top_k,
}
if contexto:
payload["contexto_cclasstrib"] = contexto
response = requests.post(
f"{API_URL}/ingest/classify",
json=payload,
headers={"X-API-Key": API_KEY},
timeout=15,
)
response.raise_for_status()
return response.json()
resultado = classificar_produto(
"ARROZ TIPO 1 LONGO FINO 5KG",
contexto={"tipo_dfe": "nfce"},
)
if resultado["sugestoes"]:
melhor = resultado["sugestoes"][0]
situacoes = melhor.get("classificacao_tributaria", {}).get("situacoes", [])
print("NCM:", melhor["ncm"])
print("Confiança:", melhor["confianca_faixa"])
print("cClassTrib:", situacoes[0]["cclasstrib"] if situacoes else "Revisar")
sugestoes pode vir vazio quando não houver resultado confiável. A integração deve tratar esse caso sem presumir que sempre haverá uma primeira posição.
Implementação em JavaScript
Este exemplo foi pensado para Node.js 18 ou superior. A chave permanece no servidor:
const API_URL = 'https://api.taxradar.app/api/v1';
const API_KEY = process.env.TAXRADAR_API_KEY;
if (!API_KEY) {
throw new Error('Defina a variável TAXRADAR_API_KEY');
}
async function classificarProduto(descricao, topK = 3, contexto = undefined) {
const body = { descricao, top_k: topK };
if (contexto) body.contexto_cclasstrib = contexto;
const response = await fetch(`${API_URL}/ingest/classify`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': API_KEY
},
body: JSON.stringify(body),
signal: AbortSignal.timeout(15000)
});
if (!response.ok) {
throw new Error(`Falha na API: ${response.status} ${await response.text()}`);
}
return response.json();
}
const resultado = await classificarProduto(
'ARROZ TIPO 1 LONGO FINO 5KG',
3,
{ tipo_dfe: 'nfce' }
);
console.log(resultado.sugestoes[0] ?? 'Nenhuma sugestão');
Classificação em lote
O endpoint POST /ingest/classify/batch recebe de 1 a 100 entradas. O formato recomendado usa itens: cada objeto exige external_id e descricao e pode trazer ean e ncm_atual. A resposta preserva a ordem, repete index e external_id e isola erros semânticos no próprio item.
import uuid
def classificar_lote(itens: list[dict], idempotency_key: str) -> dict:
if not 1 <= len(itens) <= 100:
raise ValueError("Envie de 1 a 100 itens por lote")
response = requests.post(
f"{API_URL}/ingest/classify/batch",
json={
"itens": itens,
"top_k": 3,
"contexto_cclasstrib": {"tipo_dfe": "nfce"},
"incluir_nesh": False,
},
headers={
"X-API-Key": API_KEY,
"Idempotency-Key": idempotency_key,
},
timeout=60,
)
response.raise_for_status()
return response.json()
chave = str(uuid.uuid4())
resultado = classificar_lote([
{
"external_id": "SKU-001",
"descricao": "ARROZ TIPO 1 5KG",
"ean": "7891234567895",
"ncm_atual": "10063021",
},
{"external_id": "SKU-002", "descricao": "x"},
], chave)
for item in resultado["resultados"]:
if item["status"] == "error":
print(item["external_id"], item["error"]["code"])
else:
print(item["external_id"], item["sugestoes"][0]["ncm"] if item["sugestoes"] else None)
Somente itens válidos enviados ao classificador consomem cota; um item válido com sugestoes: [] foi processado e consome uma classificação. Se todos forem inválidos, a API retorna 200 com os erros, sem classificador, histórico ou consumo. O formato legado {"descricoes": [...]} continua compatível, sem data de remoção.
Gere uma Idempotency-Key por operação e reutilize a mesma chave e o mesmo body após timeout. Um replay concluído retorna o body original e o header Idempotency-Replayed: true, sem nova cobrança ou histórico. usage é o snapshot da resposta original; consulte GET /ingest/usage para o consumo atual.
Uma resposta parcial mantém uma entrada para cada item:
{
"request_id": "5e34325a-2947-49fd-8c57-b332fdc51dd9",
"resultados": [
{
"index": 0,
"external_id": "SKU-001",
"descricao": "ARROZ TIPO 1 5KG",
"ean": "7891234567895",
"ncm_atual": "10063021",
"status": "success",
"sugestoes": [{"ncm": "10063021", "probabilidade": 85.2, "confianca_faixa": "alta"}],
"notas_explicativas": [],
"error": null
},
{
"index": 1,
"external_id": "SKU-002",
"descricao": "x",
"ean": null,
"ncm_atual": null,
"status": "error",
"sugestoes": [],
"notas_explicativas": [],
"error": {
"code": "INVALID_DESCRIPTION",
"field": "descricao",
"message": "A descrição deve ter entre 3 e 500 caracteres."
}
}
],
"total": 2,
"sucessos": 1,
"erros": 1
}
Como interpretar a confiança
probabilidade varia de 0 a 100. As faixas atuais são:
Tax Radar
Quantos produtos da sua empresa têm NCM incorreto?
Um erro de classificação pode virar autuação ou imposto pago a mais. Audite sua base com uma IA especializada em classificação fiscal. 20 análises grátis, sem cartão.
| Faixa | Valor | Tratamento sugerido |
|---|---|---|
alta | 50 ou mais | Validar conforme o risco do produto e da operação |
media | De 20 a 49,99 | Comparar as principais sugestões |
baixa | Abaixo de 20 | A API encerra normalmente, sem pergunta, confirmação ou interação adicional |
A faixa alta não é uma autorização automática para alterar o cadastro fiscal. Produtos de importação, alto valor, composição complexa ou benefício fiscal merecem revisão mesmo quando a confiança é alta.
Contexto do cClassTrib
O cClassTrib não depende apenas da NCM. O perfil da empresa fornecedora, a natureza da operação e o tipo de documento fiscal podem mudar o enquadramento.
O objeto contexto_cclasstrib aceita:
tipo_dfe:nfeounfce;perfil_fornecedor: perfil da empresa que vende ou fornece o produto;situacao_operacao: exportação, transferência, bonificação e outras situações especiais.
tipo_resolucao informa como o resultado foi obtido:
deterministico: regra direta identificada;condicionado: existem condições ou mais de uma situação possível;fallback: resultado padrão que exige atenção adicional.
Resultados condicionados ou de fallback devem ser revisados antes da emissão fiscal.
Permissões da API Key
Cada chave pode receber permissões independentes:
classify: classificação individual e em lote;search: consultas de NCM, benefícios e resolução de cClassTrib (o endpoint de resolução consome 1 crédito a cada 5 consultas do ciclo);history: leitura e exportação do histórico;usage: consulta do consumo do plano.
Crie chaves separadas por sistema e conceda somente as permissões necessárias. Isso facilita revogação, auditoria e controle do limite por minuto.
Erros e tentativas
A integração deve tratar pelo menos estes códigos:
| Código | Significado |
|---|---|
| 401 | Chave ausente, inválida, expirada ou revogada |
| 403 | Chave sem a permissão necessária |
409 IDEMPOTENCY_KEY_REUSED | A mesma chave foi enviada com outro body |
409 IDEMPOTENCY_IN_PROGRESS | A tentativa original ainda está ativa; respeite Retry-After |
| 422 | Corpo ou parâmetros inválidos |
| 429 | Cota do plano ou limite por minuto atingido |
| 502 | Resposta inválida do serviço de classificação |
| 503 | Serviço temporariamente indisponível |
Quando o limite por minuto ou uma tentativa idempotente ativa informar Retry-After, respeite o cabeçalho. Para timeout e falhas temporárias, use espera progressiva e repita exatamente a mesma chave e o mesmo body. Respostas 502, 503 e falta de cota não viram replay definitivo; a chave permanece reutilizável.
Fluxo recomendado no ERP
Uma integração segura costuma seguir estas etapas:
- Padronizar a descrição do produto com material, função, dimensões e aplicação.
- Enviar a descrição e o contexto fiscal disponível.
- Salvar as sugestões, a confiança e os dados de cClassTrib recebidos.
- Encaminhar casos de maior risco para revisão.
- Registrar a decisão final e quem a aprovou.
- Reavaliar itens quando a descrição, a operação ou a tabela NCM mudar.
Para auditorar uma base existente, compare a NCM atual com a primeira sugestão, mas preserve todas as alternativas e o resultado tributário. Uma divergência é um sinal para revisão, não uma autorização automática para substituir o código.
Como começar
- Crie uma conta e confirme se o plano Business ou Enterprise atende ao volume.
- Gere uma API Key com as permissões necessárias.
- Teste uma descrição conhecida na classificação individual.
- Valide o tratamento de respostas vazias, erros e limites.
- Passe para lotes pequenos antes de processar o catálogo completo.
Consulte a página para desenvolvedores para uma visão rápida ou use a documentação da API para ver todos os campos, consultas fiscais e exemplos em outras linguagens.
Perguntas frequentes
A API funciona com qualquer ERP?
Sim. Qualquer ERP ou sistema que consiga fazer requisições HTTPS e processar JSON pode integrar. A implementação pode ser feita em Python, JavaScript, Java, C#, PHP, AdvPL ou outra linguagem com cliente HTTP.
Posso chamar a API diretamente do navegador?
Não é recomendado. A chave ficaria exposta no código e nas ferramentas do navegador. Faça a chamada no backend da sua aplicação.
Quantos produtos posso enviar por lote?
De 1 a 100 itens por chamada. O formato estruturado correlaciona cada produto por external_id; o formato legado com descricoes permanece disponível. Catálogos maiores devem ser divididos em blocos.
A API identifica benefícios fiscais?
Sim. Cada sugestão pode incluir beneficios com o tipo, a lista legal e a descrição do tratamento encontrado. O enquadramento final continua sujeito às condições do produto e da operação.
A API devolve um único cClassTrib?
Nem sempre. classificacao_tributaria.situacoes pode conter mais de uma situação, e tipo_resolucao indica se o resultado é direto, condicionado ou de fallback.
Onde acompanho o consumo?
Use GET /api/v1/ingest/usage com uma chave que tenha a permissão usage. O Business possui 500.000 classificações por ciclo; no Enterprise, os campos de limite e saldo retornam null. O campo classtrib_unit_count mostra a posição no bloco de 5 consultas do resolver cClassTrib: a 1ª, a 6ª e a 11ª consulta do ciclo debitam 1 crédito cada, e as outras quatro de cada bloco não debitam.
Artigos Relacionados
Ex-tarifário: o que é, como consultar e solicitar
Regime de Ex-tarifário para redução do Imposto de Importação em bens de capital e informática. Consulta, solicitação e impacto sob IBS/CBS.
Reforma TributáriaImposto Seletivo: Produtos Afetados e Alíquotas na Reforma Tributária
Guia técnico do Imposto Seletivo (IS): 6 categorias tributadas, NCMs do Anexo XVII, base legal na LC 214/2025 e impacto operacional.
NCMNCM de Camiseta: Algodão, Poliéster e Dry Fit (2026)
Veja o NCM de camiseta de algodão, poliéster, dry fit, regata, polo, infantil e bebê e quando usar 6109.10.00, 6109.90.00, 6105, 6106 e 6111.
Seus NCMs estão corretos?
Um NCM incorreto pode gerar autuação, imposto pago a mais e inconsistências na Reforma Tributária. Audite sua base de produtos com uma IA especializada em classificação fiscal.
20 análises grátis, sem cartão.