API

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.

Equipe Tax Radar Atualizado em 17 de julho de 2026
Tax Radar

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.

Testar grátis

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.

Testar grátis
FaixaValorTratamento sugerido
alta50 ou maisValidar conforme o risco do produto e da operação
mediaDe 20 a 49,99Comparar as principais sugestões
baixaAbaixo de 20A 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: nfe ou nfce;
  • 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ódigoSignificado
401Chave ausente, inválida, expirada ou revogada
403Chave sem a permissão necessária
409 IDEMPOTENCY_KEY_REUSEDA mesma chave foi enviada com outro body
409 IDEMPOTENCY_IN_PROGRESSA tentativa original ainda está ativa; respeite Retry-After
422Corpo ou parâmetros inválidos
429Cota do plano ou limite por minuto atingido
502Resposta inválida do serviço de classificação
503Serviç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:

  1. Padronizar a descrição do produto com material, função, dimensões e aplicação.
  2. Enviar a descrição e o contexto fiscal disponível.
  3. Salvar as sugestões, a confiança e os dados de cClassTrib recebidos.
  4. Encaminhar casos de maior risco para revisão.
  5. Registrar a decisão final e quem a aprovou.
  6. 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

  1. Crie uma conta e confirme se o plano Business ou Enterprise atende ao volume.
  2. Gere uma API Key com as permissões necessárias.
  3. Teste uma descrição conhecida na classificação individual.
  4. Valide o tratamento de respostas vazias, erros e limites.
  5. 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

Tax Radar

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.

Regimes diferenciados IBS/CBS
Justificativa técnica com NESH e RGI
Classificação em lote via CSV ou Excel
Testar grátis

20 análises grátis, sem cartão.

Classifique NCMs com IA especialista tributária

20 análises grátis, sem cartão

Testar grátis →