API fiscal · v1

API do TributoX

Integre análises fiscais ao seu software. Você envia a demanda ou a operação e recebe um resultado estruturado, com a análise, a base legal citada e um nível de confiança, pronto para o seu sistema mostrar ao usuário.

A API é uma capacidade contratada. Não há cadastro aberto, chave emitida pelo próprio desenvolvedor, créditos gratuitos nem ambiente público: o acesso começa numa demonstração, passa por proposta e contrato e termina numa credencial exclusiva entregue pelo time. Esta página e a especificação OpenAPI pública (sem chave) são a referência do contrato.

Comece por aqui

  1. ContrateAgende a demonstração. Depois da proposta e do contrato, o time habilita o seu parceiro.
  2. Receba a credencialChave exclusiva, com escopos, empresas autorizadas e limites definidos no contrato.
  3. Chame a APIHTTP com JSON, a chave no backend. Comece pelo /auditar (síncrono) ou pelo /sugerir (assíncrono).
  4. Leia campo a campoCada decisão vem determinada, inconclusiva ou em revisão necessária, com fundamento e o que falta.

Antes de começar

O que você precisa

  • Um contrato ativo, com o parceiro habilitado pelo time
  • A chave de API exclusiva, entregue por canal seguro
  • Um backend para chamar. A chave nunca deve chegar ao navegador
  • A demanda fiscal em texto e, opcional, um contexto (regime, UF, CNAE, segmento, atividade) ou a operação a auditar

O que instalar

Nada. Não existe SDK nem CLI: a API é HTTPS com JSON e qualquer sistema ou automação que faça uma requisição HTTP consegue chamá-la.

Pacotes de terceiros com o nome tributox no npm ou PyPI não são nossos e não funcionam com esta API.

Processo de contratação

Do primeiro contato ao primeiro consumo, em oito passos. Cada um é conduzido pelo time; nenhum depende de cadastro no site.

  1. Agende a demonstraçãoPelo mesmo agendamento do site, em /signup. Você mostra o sistema e o caso de uso; o time mostra a análise fiscal funcionando.
  2. Qualificação comercialO time entende o volume esperado, as empresas atendidas, os escopos necessários e os requisitos de segurança e de dados.
  3. PropostaProposta com escopos, limites por minuto, cota mensal e vigência. O preço é por volume e contrato, nunca por tabela aberta.
  4. ContratoAssinatura do contrato, com as condições de tratamento de dados (LGPD) combinadas com o parceiro.
  5. Habilitação do parceiroO time cadastra o parceiro, as empresas autorizadas e ativa o contrato. Sem essa ativação, nenhuma chave de parceiro funciona.
  6. Escopos e limites configuradosO time configura o teto de escopos do parceiro, o limite por minuto, a cota mensal e a validade das chaves.
  7. Credencial exclusiva entregue com segurançaA chave é emitida pelo time, exclusiva do seu sistema, e entregue por canal seguro. Ela aparece uma única vez; guarde no cofre de segredos do seu backend.
  8. Homologação e produçãoVocê integra e valida com o time, com dados fictícios. Depois, a integração roda em produção com a mesma credencial. Revogação, suspensão e rotação passam pelo time, a qualquer momento.

A chave contratada acessa a API real, sem ambiente separado. Durante a integração, use dados fictícios: nada de CNPJ, nota fiscal ou documento real de cliente até a operação começar. A chave nunca deve ir para o navegador nem para o repositório.

Credenciais

A credencial é uma chave de API exclusiva do seu sistema. Quem a emite e a revoga é o time do TributoX, no marco do contrato.

  • Quem emite: o time do TributoX, depois do contrato. Não há emissão de chave pelo site nem cadastro de desenvolvedor.
  • Entrega: por canal seguro, em claro uma única vez. O TributoX guarda só o hash da chave e não consegue mostrá-la de novo.
  • Onde guardar: variável de ambiente ou cofre de segredos do seu backend. Nunca no aplicativo do usuário, no navegador ou no repositório.
  • Rotação, suspensão e revogação: pedidas ao time, com efeito na chamada seguinte. A chave pode ter validade definida no contrato.
  • Mais de uma chave: o time pode emitir chaves separadas por sistema ou ambiente. Chaves do mesmo parceiro enxergam os jobs e lotes umas das outras; parceiros diferentes não.
  • Teste: a chave contratada acessa a API real, sem ambiente separado. Durante a integração, use dados fictícios e valide com o time.

Autenticação

Máquina a máquina, por chave de API. Mande a chave no header Authorization: Bearer <chave> ou X-API-Key: <chave>. Nenhuma chamada é anônima; sem chave válida, a API responde 401.

Chave de API

Emitida pelo time para o seu sistema, depois do contrato, e usada só no seu backend. O TributoX guarda apenas o hash da chave, nunca o valor em claro.
  • Enviada em Authorization: Bearer ou X-API-Key
  • Revogação, suspensão e rotação pelo time, com efeito na chamada seguinte
  • Chave de parceiro: escopos, empresas autorizadas, limites e validade definidos no contrato
  • Consumo medido por chave, para atribuição por consumidor

Escopos e permissões

Por contrato

Exige chave de parceiro contratado, habilitado pelo time. Cada rota pede um escopo; a chave só funciona dentro do teto de escopos do contrato.

Escopos da API fiscal v1
EscopoRotasPara que serve
fiscal:sugerirPOST /api/fiscal/v1/sugerirCria sugestões fiscais fundamentadas (assíncronas).
fiscal:auditarPOST /api/fiscal/v1/auditarAudita uma operação ou NF-e na mesma chamada.
fiscal:lotesPOST /api/fiscal/v1/lotesCria um lote de 1 a 100 operações para auditoria assíncrona.
fiscal:resultadosGET /api/fiscal/v1/sugestao/{job_id} e GET /api/fiscal/v1/lotes/{lote_id}Lê o resultado de jobs e de lotes.
  • O contrato define o teto de escopos do parceiro. A chave recebe escopos dentro desse teto, nunca acima.
  • A autorização é conferida a cada requisição, na ordem: chave ativa, não expirada e não suspensa; parceiro ativo e dentro da vigência; escopo da rota; empresa autorizada; limite por minuto e cota mensal.
  • Escopo ausente responde 403 com erro escopo_insuficiente e o escopo que faltou no detail. Ampliar escopo é alteração de contrato, feita pelo time.
Resposta403 Forbidden
HTTP/1.1 403 Forbidden

{ "detail": "Esta chave nao tem o escopo fiscal:auditar.", "erro": "escopo_insuficiente" }

Autorização por empresa (X-TributoX-CNPJ)

Por contrato

Exige chave de parceiro contratado. Software houses e ERPs atendem várias empresas com a mesma credencial: o header diz em nome de quem a chamada é feita, e o contrato diz quais empresas o parceiro pode atender.

  • O contrato lista as empresas que o parceiro pode atender. Quem integra um ERP ou software com várias empresas clientes envia, em cada chamada, o header X-TributoX-CNPJ com o CNPJ da empresa em nome de quem chama.
  • Parceiro com empresas cadastradas: o header é obrigatório. Sem ele, 400 com erro cnpj_obrigatorio. CNPJ fora da lista, ou que não seja um CNPJ válido, 403 com erro cnpj_nao_autorizado.
  • Parceiro sem empresas cadastradas: o header é opcional e só é registrado no job, para rastreabilidade.
  • Formato: os 14 dígitos numéricos do CNPJ, com ou sem pontuação, com dígitos verificadores corretos. O TributoX normaliza antes de comparar. Os exemplos desta página usam o CNPJ fictício 11222333000181.
  • Inclusão ou desativação de empresa é feita pelo time; o parceiro não altera a lista.
HeadersParceiro com empresas cadastradas
# Headers de um parceiro com empresas cadastradas (CNPJ fictício)
-H "Authorization: Bearer $TRIBUTOX_API_KEY" \
-H "X-TributoX-CNPJ: 11222333000181" \
-H "Idempotency-Key: pedido-erp-000123"

# Repetir a mesma chamada devolve a resposta guardada, com o header Idempotent-Replayed: true.

Primeira requisição

A forma mais curta de ver a API funcionando é auditar uma operação: a resposta vem na mesma chamada. Troque $TRIBUTOX_API_KEY pela chave do seu contrato e use o CNPJ de uma empresa autorizada (o exemplo usa o fictício 11222333000181). Esperado: 200 com regras_icms.

curl -X POST https://api.tributox.studiolabsai.com/api/fiscal/v1/auditar \
  -H "X-API-Key: $TRIBUTOX_API_KEY" \
  -H "X-TributoX-CNPJ: 11222333000181" \
  -H "Idempotency-Key: pedido-erp-000123" \
  -H "Content-Type: application/json" \
  -d '{
    "entrada": "Venda de producao propria, NCM 84713012, de SP para BA em 2026-03-10, origem 0, para contribuinte do ICMS, emitente no Simples Nacional."
  }'

A resposta completa e a leitura de cada campo estão em Auditar operação. Para dúvida interpretativa em vez de uma operação, veja Sugerir.

Sugerir (sugestão fiscal)

POST/api/fiscal/v1/sugerir

Assíncrono: você envia a demanda, recebe o job_id e consulta o resultado quando ele estiver pronto. A sugestão traz regras, exceções, base legal citada e um nível de confiança.

  • Corpo: demanda (obrigatória, texto) e contexto opcional (regime, UF, CNAE, segmento, atividade). Demanda vazia responde 422.
  • Resposta 202 com job_id e status pendente. A geração roda em background; leia o resultado em GET /sugestao/{job_id}.
  • Use para dúvida interpretativa: o resultado traz regras, exceções, base legal e nível de confiança. Para decidir CFOP, alíquota interestadual e DIFAL de uma operação, use o /auditar.
Pedidocorpo JSON
{
  "demanda": "Empresa de servicos no Simples Nacional. O Fator R muda o anexo?",
  "contexto": { "regime": "simples", "uf": "SP", "atividade": "desenvolvimento de software" }
}
Resposta202 Accepted
{ "job_id": "3f2b9c1e-7a4d-4e8b-9c2a-1d5e6f7a8b9c", "status": "pendente" }
curl -X POST https://api.tributox.studiolabsai.com/api/fiscal/v1/sugerir \
  -H "Authorization: Bearer $TRIBUTOX_API_KEY" \
  -H "X-TributoX-CNPJ: 11222333000181" \
  -H "Idempotency-Key: sugestao-erp-000123" \
  -H "Content-Type: application/json" \
  -d '{
    "demanda": "Empresa de servicos no Simples Nacional. O Fator R muda o anexo?",
    "contexto": { "regime": "simples", "uf": "SP", "atividade": "desenvolvimento de software" }
  }'

curl https://api.tributox.studiolabsai.com/api/fiscal/v1/sugestao/3f2b9c1e-7a4d-4e8b-9c2a-1d5e6f7a8b9c \
  -H "Authorization: Bearer $TRIBUTOX_API_KEY" \
  -H "X-TributoX-CNPJ: 11222333000181"

Auditar operação

POST/api/fiscal/v1/auditar

Síncrono: você manda o texto da venda ou o XML da NF-e no campo entrada e a resposta vem na mesma chamada, em alguns segundos. Quem decide alíquota interestadual, CFOP e DIFAL é um motor de regras versionado; a IA só lê a entrada e explica o resultado. O exemplo em quatro linguagens está em Primeira requisição.

Campos da resposta do /auditar
CampoO que traz
fontemotor_interno quando o NCM tem regra no motor; rag quando não tem. Com rag, nenhum código é preenchido e status vem revisao_necessaria.
entrada_extraidaO que foi lido da entrada. Campo vazio quer dizer não informado, nunca deduzido.
regras_icmsAlíquota interestadual, CFOP e DIFAL, cada um com status (determinado, inconclusivo ou revisao_necessaria), fundamentos e o que faltou. Traz também versao_regras e, quando a entrada informa um CFOP, cfop_informado.
dados_fiscaisCSOSN, CST e CFOP do motor. null quando a fonte é rag.
insights_iaExplicação em texto das decisões do motor. Não decide código nem alíquota.
Pedidocorpo JSON
{
  "entrada": "Venda de producao propria, NCM 84713012, de SP para BA em 2026-03-10, origem 0, para contribuinte do ICMS, emitente no Simples Nacional."
}
Resposta200 OK, fonte rag
{
  "sucesso": true,
  "status": "revisao_necessaria",
  "fonte": "rag",
  "entrada_extraida": {
    "ncm": "84713012", "uf_origem": "SP", "uf_destino": "BA", "regime_emitente": "simples",
    "perfil_destinatario": "contribuinte", "tipo_operacao": "venda", "data_operacao": "2026-03-10",
    "natureza_mercadoria": "producao_propria", "origem_mercadoria": "0",
    "tipo_destinatario": "contribuinte", "consumidor_final": "", "finalidade_aquisicao": "",
    "venda_presencial": "", "regime_tributario": "simples", "cfop_informado": "",
    "competencia": "", "ind_final": "", "ind_pres": "", "ind_ie_dest": "",
    "conteudo_importacao": "", "uf_destino_fisico": ""
  },
  "dados_fiscais": null,
  "regras_icms": {
    "versao_regras": "icms-interestadual-1.0.0",
    "aliquota_interestadual": {
      "status": "determinado",
      "valor": "7.00",
      "fundamentos": [
        "Resolução do Senado Federal nº 22/1989, art. 1º e parágrafo único",
        "Resolução do Senado Federal nº 13/2012, art. 1º (§1º e §4º) e art. 2º",
        "Ajuste SINIEF 15/2013 (códigos de origem da mercadoria)"
      ],
      "motivo": "Origem no Sul/Sudeste (exceto ES) para Norte, Nordeste, Centro-Oeste ou ES.",
      "faltando": [],
      "detalhe": { "regra": "res_22_1989_reduzida", "origem_mercadoria": "0" }
    },
    "cfop": {
      "status": "determinado",
      "valor": "6101",
      "fundamentos": [
        "Convênio s/nº de 15/12/1970 (CFOP): 6.107 e 6.108 são vendas destinadas a não contribuinte",
        "MOC da NF-e, campo dest/indIEDest (1 contribuinte, 2 contribuinte isento de inscrição, 9 não contribuinte)"
      ],
      "motivo": "Venda interestadual; CFOP pela natureza da mercadoria e pela condição do destinatário.",
      "faltando": [],
      "detalhe": { "candidatos": ["6101"] }
    },
    "difal": {
      "status": "inconclusivo",
      "valor": null,
      "fundamentos": [],
      "motivo": "Faltam dados para decidir o DIFAL.",
      "faltando": ["finalidade_aquisicao"]
    }
  },
  "rag": {
    "sugestao": "Nao ha legislacao na base para sustentar esta demanda; requer verificacao manual.",
    "regras": [], "campos_afetados": [], "excecoes": [], "base_legal": [],
    "confianca": "baixa",
    "aviso": "Sem base suficiente na base de conhecimento; requer verificacao manual."
  },
  "insights_ia": "Nao ha legislacao na base para sustentar esta demanda; requer verificacao manual."
}

Decisão com status inconclusivo ou revisao_necessaria vem sem valor, com o motivo e os campos que faltaram. Com fonte: motor_interno, a resposta traz dados_fiscais preenchido e status ausente. Entrada vazia ou sem NCM, UF ou regime legíveis responde 422. O schema campo a campo está na especificação OpenAPI.

Lotes

POST/api/fiscal/v1/lotesPor contrato

Para volume: envie até 100 operações numa chamada e acompanhe o lote. Exige chave de parceiro contratado, com os escopos fiscal:lotes (criar) e fiscal:resultados (ler). O processamento é assíncrono, item a item, com o mesmo motor do /auditar.

  • POST /lotes com itens de 1 a 100; cada item traz entrada (até 16.000 caracteres lidos) e referencia, o identificador da operação no seu sistema (até 120 caracteres).
  • Resposta 202 com lote_id, total e job_ids (um por item, na ordem enviada). Cada item é auditado de forma assíncrona, com o mesmo motor e as mesmas regras do /auditar. Mais de 100 itens, lote vazio ou entrada acima de 16.000 caracteres: 422.
  • Cota mensal: cada item conta. O lote inteiro entra ou é recusado; se o total passar da cota, a resposta é 429 com erro cota_mensal_atingida e nenhum item é criado.
  • GET /lotes/{lote_id} responde 202 enquanto houver item pendente ou processando e 200 quando todos terminarem. O corpo traz status, total, criado_em (UTC, sem offset), contagem por estado (pendente, processando, concluido, erro) e, por item, job_id, referencia, status, resultado e erro. Consulte por polling, respeitando o limite por minuto.
  • Um item que falha não derruba o lote: o lote fecha como concluido e o item traz status erro e o campo erro, num destes formatos: entrada_nao_interpretavel (a entrada não permitiu extrair NCM, UF e regime), provedor_indisponivel: <Classe> ou falha_interna: <Classe>. Falha do nosso lado não consome cota.
  • O resultado de um item concluído é o mesmo objeto do /auditar. Cada job_id do lote também pode ser lido em GET /sugestao/{job_id}.
  • Lote e jobs de outra chave do mesmo parceiro são visíveis; de outro parceiro, 404. Resultados ficam guardados por pelo menos 90 dias.
  • Use Idempotency-Key no POST para não duplicar o lote numa nova tentativa.
curl -X POST https://api.tributox.studiolabsai.com/api/fiscal/v1/lotes \
  -H "Authorization: Bearer $TRIBUTOX_API_KEY" \
  -H "X-TributoX-CNPJ: 11222333000181" \
  -H "Idempotency-Key: lote-2026-03-0001" \
  -H "Content-Type: application/json" \
  -d '{
    "itens": [
      { "referencia": "PED-1001", "entrada": "Venda de producao propria, NCM 84713012, de SP para BA em 2026-03-10, origem 0, para contribuinte do ICMS, emitente no Simples Nacional." },
      { "referencia": "PED-1002", "entrada": "Venda de mercadoria, NCM 84713012, de SP para MG em 2026-03-11, origem 0, para contribuinte do ICMS, emitente no Lucro Presumido." }
    ]
  }'

curl https://api.tributox.studiolabsai.com/api/fiscal/v1/lotes/9d4c7e21-5b3a-4f60-8a1e-2c7d9b0e4f13 \
  -H "Authorization: Bearer $TRIBUTOX_API_KEY" \
  -H "X-TributoX-CNPJ: 11222333000181"
Resposta202 Accepted
{
  "lote_id": "9d4c7e21-5b3a-4f60-8a1e-2c7d9b0e4f13",
  "total": 2,
  "job_ids": [
    "3f2b9c1e-7a4d-4e8b-9c2a-1d5e6f7a8b9c",
    "5e1d0a7b-2c3f-4d9e-8a6b-0f1e2d3c4b5a"
  ]
}
ConsultaGET /api/fiscal/v1/lotes/{lote_id}, 202 enquanto houver item em andamento
{
  "lote_id": "9d4c7e21-5b3a-4f60-8a1e-2c7d9b0e4f13",
  "status": "processando",
  "total": 2,
  "criado_em": "2026-11-03T12:00:00",
  "contagem": { "pendente": 0, "processando": 1, "concluido": 0, "erro": 1 },
  "itens": [
    {
      "job_id": "3f2b9c1e-7a4d-4e8b-9c2a-1d5e6f7a8b9c",
      "referencia": "PED-1001",
      "status": "erro",
      "resultado": null,
      "erro": "entrada_nao_interpretavel"
    },
    {
      "job_id": "5e1d0a7b-2c3f-4d9e-8a6b-0f1e2d3c4b5a",
      "referencia": "PED-1002",
      "status": "processando",
      "resultado": null,
      "erro": null
    }
  ]
}

Jobs e fluxo assíncrono

Uma sugestão leva alguns segundos, então a API é assíncrona. Você cria, recebe um job_id e consulta o resultado por polling com GET /api/fiscal/v1/sugestao/{job_id}. Na v1 não há envio de eventos; para parceiros da v2, os eventos de saída estão em homologação.

  1. CriarPOST /sugerir com a demanda. Retorna 202 e o job_id, com status pendente.
  2. ProcessarO TributoX busca a norma na base, gera a sugestão e confere as citações. Status processando.
  3. ConsultarGET /sugestao/{job_id}. Enquanto roda, devolve 202. Cada consulta conta no limite por minuto da chave.
  4. LerQuando concluído, o GET devolve 200 com o resultado estruturado e a base legal.

Status do job: pendente, processando, concluido e erro. A consulta devolve 202 enquanto o job está pendente ou processando e 200 nos outros dois. Job de outro parceiro responde 404.

Resultados estruturados

O resultado de uma sugestão vem em campos: sugestao, regras, campos_afetados, excecoes, base_legal e um nível de confianca.

Quando a base não sustenta a resposta, vem confianca: baixa, base_legal: [] e a sugestão pede verificação, em vez de citar uma norma que não foi encontrada.

Com erro, a consulta volta 200 com resultado: null; crie um job novo. Falha momentânea do provedor de IA não vira erro: o job conclui com confianca: baixa e a sugestão pede para tentar de novo. Os resultados ficam guardados por pelo menos 90 dias.

Resultado200 OK
{
  "job_id": "3f2b9c1e-7a4d-4e8b-9c2a-1d5e6f7a8b9c",
  "status": "concluido",
  "resultado": {
    "sugestao": "Com Fator R igual ou acima de 28%, a atividade e tributada pelo Anexo III.",
    "regras": ["Fator R = folha de salarios dos 12 meses / receita bruta dos 12 meses."],
    "campos_afetados": ["anexo", "aliquota_efetiva"],
    "excecoes": ["O Fator R e apurado mes a mes."],
    "base_legal": ["LC 123/2006, art. 18, par. 5-J"],
    "confianca": "alta",
    "aviso": "Confirme a folha dos ultimos 12 meses."
  }
}

Consumo e limites

O volume contratado, o limite por minuto e, para parceiros, a cota mensal são combinados no contrato. Não há plano gratuito nem cota automática para quem não tem contrato.

Requisições por minuto

Quando o contrato define um limite por minuto, ele vale por chave (na chave de parceiro, vale o do parceiro quando a chave não tem o seu). A janela é de um minuto pelo relógio do servidor e conta todas as rotas da v1, inclusive o polling, as tentativas recusadas e a repetição de uma chamada com Idempotency-Key.

Headers de limite

Com limite ativo na chave, toda resposta traz X-RateLimit-Limit, X-RateLimit-Remaining e X-RateLimit-Reset. Acima do limite, 429 com Retry-After (segundos até a janela reabrir).

Cota mensal do parceiro

Chave de parceiro contratado: o contrato pode fixar uma cota mensal, contada pelos jobs do parceiro no mês de Brasília; cada item de lote conta. Ao atingir, 429 com erro cota_mensal_atingida. Falha do nosso lado não consome cota, e repetir uma chamada com Idempotency-Key também não. Sem cota no contrato, não há teto mensal.

Consumo

O consumo é medido por chave. Na v1 não há endpoint de consulta: o time informa o consumo do período ao parceiro.

Tamanho do corpo

Até 50 MB por requisição (acima disso, 413). No /auditar e em cada item de lote, só os primeiros 16.000 caracteres da entrada são lidos na análise. Lote: de 1 a 100 itens.

Retenção dos resultados

Resultados de jobs e lotes ficam guardados por pelo menos 90 dias. Guarde no seu sistema o que precisa manter além disso.

Falha do controle

Se o contador do limite estiver indisponível, a requisição é recusada com 503 e Retry-After, em vez de passar sem controle.
Resposta429 Too Many Requests
HTTP/1.1 429 Too Many Requests
Retry-After: 23
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 23

{ "detail": "Limite de 60 requisicoes por minuto atingido para esta chave." }

Idempotência (Idempotency-Key)

Repita uma chamada sem duplicar o job nem o consumo, por exemplo depois de um timeout de rede. Vale nas rotas POST de sugerir, auditar e lotes.

  • Header opcional Idempotency-Key, de 1 a 255 caracteres imprimíveis, nos POST /sugerir, /auditar e /lotes. Vale para qualquer chave de API. Use um identificador do seu lado, como o id da operação no ERP.
  • Mesma chave e mesmo corpo: a API devolve a resposta guardada, com o header Idempotent-Replayed: true, sem criar outro job e sem consumir a cota mensal. A chamada repetida ainda conta no limite por minuto.
  • Só respostas de sucesso (2xx) ficam guardadas. Uma falha (422, 503 ou erro nosso) libera a chave: repita com a mesma Idempotency-Key.
  • Mesma chave com corpo diferente: 422 com erro idempotency_key_reutilizada.
  • Mesma chave ainda em andamento: 409 com erro requisicao_em_andamento e Retry-After de 2 segundos. Espere e repita a mesma chamada. Se a primeira chamada ficou sem resposta por mais de 15 minutos, a chave volta a ficar disponível.
  • Chave vazia, com mais de 255 caracteres ou com caractere de controle: 422.
  • A chave vale por 24 horas, por chave de API e por rota.
Resposta409 Conflict
HTTP/1.1 409 Conflict
Retry-After: 2

{ "detail": "Ja existe uma requisicao em andamento com esta Idempotency-Key.", "erro": "requisicao_em_andamento" }

Guia de integração com ERP

Como um ERP ou software fiscal envia uma operação e recebe de volta uma análise estruturada. O mesmo padrão vale para sistemas contábeis e plataformas financeiras. Os exemplos em cURL, JavaScript, Python e PHP estão em Primeira requisição, Sugerir e Lotes.

01

Guarde a chave no backend

Variável de ambiente ou cofre de segredos do servidor do ERP. Nunca no aplicativo do usuário nem no navegador.
02

Monte a entrada

O texto da operação (NCM, origem, destino, data, regime, destinatário) ou o XML da NF-e no campo entrada. Até 16.000 caracteres são lidos.
03

Chame o /auditar

Resposta síncrona. Envie X-TributoX-CNPJ e Idempotency-Key quando o contrato pedir. Trate 429 e 503 com espera pelo Retry-After; 422 indica entrada a corrigir. Volume grande: use lotes.
04

Leia campo a campo

Para cada decisão em regras_icms: determinado tem valor e fundamento; inconclusivo e revisao_necessaria trazem motivo e a lista faltando.
05

Mostre no fluxo do ERP

Compare com o que o ERP vai emitir. Diferença em decisão determinada vira alerta; inconclusivo vira pedido do dado que falta.
06

Guarde a trilha

Salve versao_regras e os fundamentos junto da operação, para mostrar de onde veio cada conferência.

Erros

Erros da API e o que fazer
StatusMotivoO que fazer
400erro: cnpj_obrigatorio Por contratoO parceiro tem empresas cadastradas no contrato e a chamada veio sem o header X-TributoX-CNPJ. Envie o CNPJ da empresa em nome de quem você chama.
401Chave de API necessaria / Chave de API invalida / Chave de API expiradaSem chave, chave inválida ou revogada, ou chave expirada (quando o contrato define validade). Nenhuma chamada é anônima. Chave expirada: peça a renovação ao time.
403erro: chave_suspensa Por contratoA chave foi suspensa pelo time. Reativação só pelo time; repetir a chamada não resolve.
403erro: contrato_inativo Por contratoO contrato do parceiro não está ativo (suspenso, encerrado ou fora do período de vigência). Fale com o time.
403erro: escopo_insuficiente Por contratoA chave não tem o escopo que a rota exige. O detail diz qual, por exemplo: Esta chave nao tem o escopo fiscal:auditar. Escopo novo exige ajuste do contrato.
403erro: cnpj_nao_autorizado Por contratoO CNPJ do header X-TributoX-CNPJ não está entre as empresas autorizadas do parceiro, ou não é um CNPJ válido (14 dígitos com dígitos verificadores corretos). Inclusão de empresa é feita pelo time.
404Job nao encontrado / Lote nao encontradoJob ou lote inexistente, ou de outro parceiro ou outra chave sem vínculo. Confira o job_id ou o lote_id retornado na criação.
409erro: requisicao_em_andamentoOutra chamada com o mesmo Idempotency-Key ainda está em andamento. A resposta traz Retry-After de 2 segundos: espere e repita a mesma chamada; não crie outra chave para o mesmo pedido.
413Corpo da requisição muito grandeO corpo passou de 50 MB. Envie só a operação ou a NF-e que quer analisar.
422demanda obrigatoria / entrada obrigatoria / Nao foi possivel extrair NCM/UF/regime da entrada.Campo obrigatório vazio (detail em texto), corpo fora do schema (detail em lista, com o campo em loc) ou, no /auditar, entrada sem NCM, UF ou regime legíveis. Lote com zero itens, com mais de 100 ou com entrada acima de 16.000 caracteres também cai aqui. Corrija o pedido; repetir igual não resolve.
422erro: idempotency_key_reutilizadaO mesmo Idempotency-Key já foi usado com um corpo diferente. Use uma chave nova para um pedido novo.
422Idempotency-Key invalidaO header veio vazio, com mais de 255 caracteres ou com caractere de controle. Envie de 1 a 255 caracteres imprimíveis, ou omita o header.
429Limite de N requisicoes por minuto atingidoA chave passou do limite por minuto. Espere os segundos do header Retry-After e repita.
429erro: cota_mensal_atingida Por contratoO parceiro usou a cota mensal do contrato (mês de Brasília). Num lote, a cota é conferida pelo total de itens e o lote inteiro é recusado. Novas chamadas voltam no mês seguinte ou com ajuste de contrato, combinado com o time.
503Limite de requisicoes indisponivel / provedor_indisponivelA requisição não foi processada. Controle de limite indisponível: Retry-After de 5 s. No /auditar, provedor de IA indisponível: corpo com erro provedor_indisponivel e Retry-After de 30 s; essa tentativa não consome a cota mensal. Repita depois do Retry-After.
500Erro internoFalha inesperada, sem corpo estável. Repita com espera crescente e, se persistir, informe o horário ao time.

O 202 não é erro: é a resposta de criação e a de consulta enquanto o job ainda processa. Todo erro vem como JSON com o campo detail; os erros de contrato trazem também o campo erro, com um código estável para tratar no seu sistema. Linhas marcadas como contrato valem para chaves de parceiro contratado.

Eventos e webhooks

Em homologação, para parceiros da API v2 por contrato. Na API v1, o resultado é acompanhado por consulta.

  • Na API v1 o acompanhamento é por consulta (polling): você guarda o job_id ou o lote_id e consulta até o resultado sair.
  • Para parceiros da API v2, os eventos de saída estão em homologação: o TributoX envia um POST assinado ao destino cadastrado no contrato, e os mesmos eventos podem ser lidos por consulta com cursor. A ativação é por contrato, depois da validação com o seu receptor; até lá, a integração não deve depender deles.
  • Para consultar sem estourar o limite por minuto: comece com intervalos de 2 a 3 segundos, aumente aos poucos e respeite o Retry-After quando receber 429.
Tipos de evento de saída
EventoQuando é enviado
documento.recebidoUm documento do lote foi recebido e registrado para a empresa.
conferencia.concluidaA conferência de um rascunho de NF-e antes da emissão terminou.
auditoria.concluidaA auditoria dos documentos da empresa terminou.
acao.propostaO TributoX propôs uma ação num caso. A decisão continua com o profissional.
acao.decididaUma pessoa decidiu sobre a ação proposta.
  • Cabeçalho X-TributoX-Signature no formato t=<unix>,v1=<assinatura>. A assinatura é o HMAC-SHA256, com o segredo do seu contrato, de t, um ponto e o corpo bruto. Recuse eventos com mais de 5 minutos de diferença.
  • Cabeçalho X-TributoX-Event-Id (evt_ seguido de 32 caracteres hexadecimais). A entrega é pelo menos uma vez: deduplique por esse identificador.
  • Resposta 2xx confirma a entrega. Sem resposta ou com erro, o envio é repetido até 8 vezes, com intervalo crescente a partir de 60 segundos e teto de 6 horas.
  • O destino precisa ser https e é cadastrado pelo nosso time. Endereços internos ou privados são recusados.

Endpoints

Base https://api.tributox.studiolabsai.com. A versão fica no path (/api/fiscal/v1). A especificação OpenAPI de todos eles está em /api/fiscal/v1/openapi.json.

Endpoints da API fiscal v1
MétodoRecursoPara que serveEscopo (parceiro)
POST/api/fiscal/v1/sugerirCria uma sugestão fiscal fundamentada. Retorna 202 e o job_id; a geração roda em background.fiscal:sugerir
GET/api/fiscal/v1/sugestao/{job_id}Busca o resultado pelo job_id. 202 enquanto processa, 200 com o resultado quando concluído.fiscal:resultados
POST/api/fiscal/v1/auditarAudita uma operação (texto da venda ou XML da NF-e) e responde na mesma chamada, com as decisões de ICMS e a fonte de cada uma.fiscal:auditar
POST/api/fiscal/v1/lotesEnvia de 1 a 100 operações de uma vez. Retorna 202 com o lote_id e um job_id por item; cada item é auditado de forma assíncrona pelo mesmo motor do /auditar. Exige chave de parceiro contratado.fiscal:lotes
GET/api/fiscal/v1/lotes/{lote_id}Consulta o lote: contagem por estado e, por item, job_id, referencia, status, resultado e erro. Exige chave de parceiro contratado.fiscal:resultados
GET/api/fiscal/v1/openapi.jsonEspecificação OpenAPI só desta API, sem chave. Use para gerar cliente ou validar respostas.Sem chave

Versionamento e OpenAPI

  • A versão fica no path: /api/fiscal/v1. A especificação de cada versão sai em /api/fiscal/v1/openapi.json.
  • Mudanças aditivas entram na v1 sem aviso: campo novo na resposta, campo opcional novo no pedido, valor novo documentado num status. Ignore campos que você não conhece.
  • Remover ou renomear campo, mudar tipo ou significado, ou tornar obrigatório o que era opcional só acontece numa nova versão no path.
  • Quando uma nova versão sair, a anterior fica marcada como deprecated na especificação e continua no ar por pelo menos 90 dias, com aviso ao parceiro.
  • Existe uma API v2 para parceiros de ERP, por contrato e em piloto: lotes de NF-e por empresa autorizada com resultado estruturado, consumo da chave, casos e pendências da empresa, envio de documento para uma pendência e, em homologação, a conferência do rascunho antes da emissão e os eventos de saída. A referência completa da v2 é entregue com o contrato.
Especificaçãosem chave
curl https://api.tributox.studiolabsai.com/api/fiscal/v1/openapi.json

Segurança e LGPD

Chaves e isolamento

A chave fica guardada só em forma de hash e pode ser revogada, suspensa ou rotacionada pelo time a qualquer momento; pode ter validade. Cada chave só enxerga os próprios jobs (e, no mesmo parceiro, os das outras chaves do parceiro): job de outro parceiro responde 404. Mande só o necessário para a análise, sem dado pessoal.

Escopos e autorização por empresa

Chave de parceiro contratado tem escopos dentro do teto do contrato e só atende as empresas autorizadas (header X-TributoX-CNPJ). A conferência acontece no servidor a cada requisição.

Rastreabilidade

Cada chamada fica registrada por chave, com o status e a versão das regras de ICMS usadas (versao_regras), para auditoria do lado do parceiro e do TributoX.

Segurança e LGPD

Banco de dados e servidores da aplicação no Brasil (São Paulo), com tráfego criptografado. O processamento de IA usa fornecedores nos EUA, sob contrato. As condições de tratamento de dados são combinadas com cada parceiro.

Superfície pública

A especificação publicada cobre só a API fiscal. As rotas internas da plataforma não fazem parte do contrato.

Roadmap

Ainda não disponível. O que está no plano da API, para você saber o que vem, sem confundir com o contrato atual. Idempotência e lotes já estão disponíveis para parceiros contratados.

  • Mais tipos de análise (enquadramento, simulação da Reforma, oportunidades) via endpoint.
  • LexFeed por endpoint e por push.

Portal de autoatendimento para desenvolvedores não faz parte do roadmap: a API é um modelo contratado, com credencial exclusiva entregue pelo time depois do contrato.

Próximos passos