# Documentação da API GetTax > API B2B de classificação fiscal da POS Controle para a reforma tributária do consumo (IBS e CBS). A software house envia GTIN e CFOP (e, opcionalmente, o setor do cliente final) e recebe as alternativas de enquadramento: CST, cClassTrib, condições, fundamento legal e alíquotas de CBS, IBS-UF e IBS-município, com as versões usadas na decisão. - Base URL (homologação): `https://app-web-hmg-01-api-gettax-hmg-dvawffg9g9cpcef3.brazilsouth-01.azurewebsites.net`. Toda rota sob `/v1/` exige `Authorization: Bearer `. - Corpo e respostas em JSON UTF-8. Erros têm o formato `{"error": "CODIGO"}`, sem detalhe do campo. - Valores fiscais são strings de fração decimal com 6 casas: `"0.009000"` = 0,9%; redução `"0.600000"` = 60%. - Toda página desta documentação tem versão markdown: troque a barra final da URL por `.md`. --- # Início rápido Valide a sua chave e faça a primeira consulta de classificação fiscal. Versão HTML: https://kind-coast-062131010.2.azurestaticapps.net/guias/inicio-rapido/ O GetTax recebe o GTIN de um produto e o CFOP da operação e devolve as alternativas de enquadramento de CBS e IBS: CST, cClassTrib, alíquotas por componente e fundamento legal, com a versão de cada regra e tabela usada na decisão. > [!WARNING] > A API está em homologação. Regras, tabela de cClassTrib e alíquotas ainda estão em validação pela curadoria fiscal e podem incluir dados de demonstração. Não emita documento fiscal real com base nestas respostas. ## Antes de começar Você precisa de: - Uma chave de API, no formato `gtx_<16 hex>.<64 hex>`, criada no [portal da revenda](https://app-web-05-prd-wl-gettax-prd.azurewebsites.net), em **Chaves de API**. O acesso ao portal é por convite da equipe GetTax. Ver [Autenticação](https://kind-coast-062131010.2.azurestaticapps.net/guias/autenticacao.md#como-obter-a-chave). - A URL base da API, informada pela equipe GetTax. - Um backend para fazer as chamadas. A chave não pode ir para navegador, app ou PDV. Defina as duas variáveis usadas em todos os exemplos: ```shell export GETTAX_URL="https://..." # URL base informada pela equipe GetTax export GETTAX_KEY="gtx_0123456789abcdef." ``` Requisições e respostas usam JSON em UTF-8. Envie `Content-Type: application/json` em toda requisição com corpo. ## 1. Valide a chave A lista de setores exige chave e não consome franquia. É o jeito mais barato de confirmar que a chave e o cabeçalho estão certos. ```shell curl -sS "$GETTAX_URL/v1/enums/sectors" \ -H "Authorization: Bearer $GETTAX_KEY" ``` ```json { "sectors": ["VAREJO_GERAL", "BAR_RESTAURANTE", "PRODUTOR_RURAL", "GOVERNO", "ATACADO", "ZONA_FRANCA"] } ``` Se vier `401` com `{"error": "INVALID_API_KEY"}`, confira a chave e o cabeçalho `Authorization`. ## 2. Consulte um produto Envie o GTIN e o CFOP da operação. Esta consulta consome uma unidade da [franquia](https://kind-coast-062131010.2.azurestaticapps.net/guias/franquia.md). ```shell curl -sS -X POST "$GETTAX_URL/v1/classifications/resolve" \ -H "Authorization: Bearer $GETTAX_KEY" \ -H "Content-Type: application/json" \ -d '{"gtin": "7891000315507", "cfop": "5102"}' ``` `sector` (setor do cliente final) e `referenceDate` (data de vigência) são opcionais. Ver [Dados da consulta](https://kind-coast-062131010.2.azurestaticapps.net/guias/dados-da-consulta.md). ## 3. Leia a resposta Uma resposta `CLASSIFIED` com uma alternativa (valores ilustrativos): ```json { "decisionVersion": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d", "status": "CLASSIFIED", "reason": null, "gtin": "07891000315507", "cfop": "5102", "sector": null, "referenceDate": "2026-10-20", "product": { "id": "5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9", "gtinAsProvided": "7891000315507", "description": "ARROZ BRANCO TIPO 1 5KG", "brand": "MARCA EXEMPLO", "ncm": "10063021", "ncmSource": "GS1", "cest": null, "gpcCode": null, "imageUrl": null, "sourceKind": "BULK" }, "classifications": [ { "stage": "PRODUCT", "rule": { "id": "3f6b2c1e-8a4d-4f2b-9c7e-1d2a3b4c5d6e", "version": 1, "effectiveFrom": "2026-01-01", "effectiveTo": null, "ncm": "1006", "gtin": null, "sector": null }, "cst": "200", "cClassTrib": "200034", "applicability": "Venda para alimentação humana.", "observation": null, "legalBasis": "LC 214/2025, Art. 135", "taxClassification": { "id": "6f7a8b9c-0d1e-4f2a-b3c4-d5e6f7a8b9c0", "sourceVersion": "CCLASSTRIB-2026", "effectiveFrom": "2026-01-01", "effectiveTo": null, "cst": "200", "cClassTrib": "200034", "reductionPctIbs": "0.600000", "reductionPctCbs": "0.600000", "gTribRegular": false, "isApplicable": true, "calculationMode": "STANDARD", "legalBasis": "LC 214/2025, Art. 135" }, "rates": [ { "id": "0b1c2d3e-4f50-4a61-8b72-c3d4e5f60718", "sourceVersion": "ALIQUOTAS-2026", "effectiveFrom": "2026-01-01", "effectiveTo": null, "component": "CBS", "rate": "0.009000" }, { "id": "1c2d3e4f-5061-4b72-9c83-d4e5f6071829", "sourceVersion": "ALIQUOTAS-2026", "effectiveFrom": "2026-01-01", "effectiveTo": null, "component": "IBS_UF", "rate": "0.001000" }, { "id": "2d3e4f50-6172-4c83-ad94-e5f60718293a", "sourceVersion": "ALIQUOTAS-2026", "effectiveFrom": "2026-01-01", "effectiveTo": null, "component": "IBS_MUN", "rate": "0.000000" } ], "components": [ { "component": "CBS", "cst": "200", "cClassTrib": "200034", "status": "STANDARD", "standardRate": "0.009000", "reductionPct": "0.600000", "effectiveRate": "0.003600" }, { "component": "IBS_UF", "cst": "200", "cClassTrib": "200034", "status": "STANDARD", "standardRate": "0.001000", "reductionPct": "0.600000", "effectiveRate": "0.000400" }, { "component": "IBS_MUN", "cst": "200", "cClassTrib": "200034", "status": "STANDARD", "standardRate": "0.000000", "reductionPct": "0.600000", "effectiveRate": "0.000000" } ], "calculation": { "status": "CALCULATED" } } ] } ``` Leia nesta ordem: 1. **`status`**: `CLASSIFIED` quer dizer que todas as alternativas têm resultado. `PENDING`, `IN_REVIEW` e `NOT_FOUND` também chegam com HTTP 200 e pedem outra ação. Ver [Status e alternativas](https://kind-coast-062131010.2.azurestaticapps.net/guias/status-e-alternativas.md). 2. **`classifications[]`**: cada item é uma alternativa de enquadramento. `cst` e `cClassTrib` vão no documento fiscal; `applicability` diz quando a alternativa se aplica. Com mais de uma alternativa, a ordem não é recomendação. 3. **`components[]`**: a alíquota de cada componente. Aqui, CST 200 com redução de 60% (`0.600000`) sobre CBS de 0,9% dá CBS efetiva de 0,36% (`0.003600`). Os valores são strings de fração decimal. Ver [Componentes e alíquotas](https://kind-coast-062131010.2.azurestaticapps.net/guias/componentes-e-aliquotas.md). 4. **`decisionVersion`**: identifica esta decisão na trilha de auditoria. Guarde junto do documento emitido. ## Próximos passos - [Autenticação](https://kind-coast-062131010.2.azurestaticapps.net/guias/autenticacao.md): formato da chave, troca, revogação e como guardá-la. - [Status e alternativas](https://kind-coast-062131010.2.azurestaticapps.net/guias/status-e-alternativas.md): o que fazer em cada status. - [Consultar em lote](https://kind-coast-062131010.2.azurestaticapps.net/referencia/resolve-classification-batch.md): até 100 itens por requisição, para carga de catálogo. - [Boas práticas](https://kind-coast-062131010.2.azurestaticapps.net/guias/boas-praticas.md): o que guardar, como tratar decimais e quando repetir uma consulta. --- # Autenticação Envie a chave de API no cabeçalho Authorization, no esquema Bearer, a partir do seu backend. Versão HTML: https://kind-coast-062131010.2.azurestaticapps.net/guias/autenticacao/ Toda rota em `/v1/` exige uma chave de API, inclusive a lista de setores. Cada software house recebe a sua. ## Formato da chave ```http gtx_<16 hex>.<64 hex> ``` | Parte | O que é | | --- | --- | | `gtx_` + 16 caracteres hexadecimais | Prefixo público. Identifica a chave e pode aparecer em logs. | | `.` | Separador. | | 64 caracteres hexadecimais | Segredo. Nunca registre em log nem envie a terceiros. | ## Cabeçalho Envie a chave inteira, prefixo e segredo, no cabeçalho `Authorization`: ```http Authorization: Bearer gtx_0123456789abcdef. ``` ```shell curl -sS "$GETTAX_URL/v1/enums/sectors" \ -H "Authorization: Bearer $GETTAX_KEY" ``` ## Quando a autenticação falha A resposta é sempre HTTP 401 com o mesmo corpo: ```json { "error": "INVALID_API_KEY" } ``` Vale para cabeçalho ausente, fora do formato `Bearer gtx_…`, chave inexistente, chave revogada ou substituída numa rotação e cliente desativado. A API não diz qual foi o caso. - A autenticação acontece antes da validação do corpo: sem chave válida, a resposta é 401 mesmo que o corpo também esteja errado. - Requisições recusadas com 401 não consomem franquia. ## Como obter a chave As chaves são criadas no [portal da revenda](https://app-web-05-prd-wl-gettax-prd.azurewebsites.net), em **Chaves de API**. O acesso ao portal é por convite: quando a equipe GetTax libera a software house, o e-mail de contato recebe o convite. Cada software house é uma organização no portal, e os administradores dela convidam o resto da equipe. - Crie uma chave por ambiente, com um nome que diga onde ela é usada, por exemplo "Produção" e "Homologação". São até 10 chaves ativas por software house, sem repetir o nome de uma ativa. - A chave completa aparece **uma única vez**, na criação. Depois, o portal mostra só o prefixo. O GetTax guarda só o hash do segredo: uma chave perdida não pode ser recuperada, só substituída por outra. - Só administradores da organização criam e revogam chaves. Os demais membros veem a lista, com o último uso de cada chave. - Todas as chaves da software house dividem a mesma [franquia](https://kind-coast-062131010.2.azurestaticapps.net/guias/franquia.md). > [!NOTE] > A chave que a sua integração já usava antes do portal aparece lá como "Chave principal". Ela continua valendo, sem troca. ## Trocar e revogar a chave Para trocar uma chave sem parada: 1. Crie uma chave nova no portal. 2. Troque a chave na integração e confirme que ela autentica, com a lista de setores, que não consome franquia. 3. Revogue a chave antiga no portal. As duas chaves valem ao mesmo tempo até a revogação. A revogação vale na hora e não pode ser desfeita: a partir dela, toda chamada com a chave revogada recebe 401. ## Chame a API pelo backend O PDV, a retaguarda ou o ERP falam com o seu servidor, e o seu servidor fala com o GetTax: ```http PDV / ERP ──▶ seu backend ──▶ GetTax (guarda a chave) navegador ──✕──▶ GetTax ``` - O CORS da API não libera chamadas feitas direto do navegador. Isso é intencional: protege a chave. - Guarde a chave num cofre de segredos ou em variável de ambiente do servidor. Nunca em código-fonte, app instalado no cliente ou front-end. - Se a chave vazar, revogue-a no portal na hora e crie outra. --- # Dados da consulta GTIN, CFOP, setor e data de referência, e como cada um muda o resultado. Versão HTML: https://kind-coast-062131010.2.azurestaticapps.net/guias/dados-da-consulta/ Uma consulta tem quatro campos. Dois são obrigatórios: | Campo | Obrigatório | Formato | | --- | --- | --- | | `gtin` | sim | 8, 12, 13 ou 14 dígitos, com dígito verificador válido | | `cfop` | sim | 4 dígitos | | `sector` | não | um dos códigos de [`GET /v1/enums/sectors`](https://kind-coast-062131010.2.azurestaticapps.net/referencia/list-sectors.md) | | `referenceDate` | não | data `AAAA-MM-DD` | O corpo aceita exatamente esses campos. Qualquer outro, como um CNPJ, é recusado com `400 INVALID_REQUEST`. O mesmo vale para cada item de um [lote](https://kind-coast-062131010.2.azurestaticapps.net/referencia/resolve-classification-batch.md). ## GTIN O código de barras do produto, só com dígitos: sem máscara, espaços ou hífens. GTIN-8, GTIN-12, GTIN-13 (o EAN-13 comum) e GTIN-14 são aceitos, desde que o dígito verificador confira (módulo 10 da GS1). A resposta devolve o GTIN normalizado com 14 dígitos, com zeros à esquerda: `7891000315507` volta como `07891000315507`. A identidade do produto não muda; use a forma de 14 dígitos como chave no seu banco. ## CFOP O CFOP é atributo da operação, não do produto. Venda a consumidor, devolução, transferência entre filiais e remessa podem ter CST diferentes para o mesmo produto, por isso o campo é obrigatório e não tem valor padrão. Envie o CFOP da operação real. O CFOP não é curinga. As regras fiscais são cadastradas para um CFOP exato ou para uma **operação**: uma lista explícita e versionada de CFOPs. O GetTax traduz o CFOP da consulta para a operação a que ele pertence na data de referência e aplica as regras daquela operação mais as cadastradas para o CFOP exato. Algumas operações resolvem a classificação sozinhas, sem depender do produto. Uma transferência entre estabelecimentos do mesmo titular, por exemplo, pode ter uma regra de etapa `OPERATION` que vale para qualquer NCM. Ver [Etapas do motor](https://kind-coast-062131010.2.azurestaticapps.net/guias/status-e-alternativas.md#etapas-do-motor). ## Setor O setor de atuação do cliente final da software house (supermercado, restaurante etc.). É opcional. | Código | Contexto | | --- | --- | | `VAREJO_GERAL` | Varejo em geral | | `BAR_RESTAURANTE` | Bares e restaurantes | | `PRODUTOR_RURAL` | Produtor rural | | `GOVERNO` | Governo | | `ATACADO` | Atacado | | `ZONA_FRANCA` | Zona Franca | O setor filtra, não decide: - **Sem `sector`**: vêm todas as alternativas pertinentes ao produto e ao CFOP, de qualquer setor. - **Com `sector`**: vêm as alternativas genéricas (sem setor) mais as daquele setor. As genéricas não são descartadas por existir uma específica. - Omitir o setor não equivale a `VAREJO_GERAL`. - O setor sozinho não garante uma redução. `BAR_RESTAURANTE`, por exemplo, não reduz nada automaticamente: as condições aparecem em cada alternativa, em `applicability`. - Valor fora da lista é recusado com `400 INVALID_REQUEST`. A lista pode crescer. Leia de [`GET /v1/enums/sectors`](https://kind-coast-062131010.2.azurestaticapps.net/referencia/list-sectors.md), que não consome franquia, em vez de fixá-la no código. ## Data de referência `referenceDate` escolhe as regras e alíquotas vigentes. Sem ela, vale a data de hoje no fuso de São Paulo, independente do fuso do servidor ou do cliente. A data usada volta na resposta, em `referenceDate`. - Para emitir um documento agora, omita o campo. - Para reprocessar ou conferir um documento antigo, envie a data do documento. Toda vigência no GetTax (regra, linha de cClassTrib, alíquota) é um intervalo `[effectiveFrom, effectiveTo)`: início inclusivo, fim exclusivo. `effectiveTo: null` quer dizer sem data de término. --- # Status e alternativas Como ler o resultado de uma consulta, o que fazer em cada status e por que nunca escolher uma alternativa pela posição. Versão HTML: https://kind-coast-062131010.2.azurestaticapps.net/guias/status-e-alternativas/ Toda consulta processada responde HTTP 200. O que aconteceu está em dois campos: `status` diz o resultado, `reason` diz o motivo. As alternativas de enquadramento vêm em `classifications`. ## Status | `status` | `reason` | Quando | O que fazer | | --- | --- | --- | --- | | `CLASSIFIED` | `null` | Produto conhecido e todas as alternativas com resultado (`CALCULATED` ou `NOT_DUE`). | Use as alternativas, respeitando `applicability`. Guarde o `decisionVersion` com o documento. | | `PENDING` | `LOCAL_PRODUCT_MISSING` | O GTIN não está no catálogo e a busca do produto ainda não concluiu. | Consulte de novo mais tarde. Se vier `retryAfterSeconds`, espere pelo menos esse tempo. | | `IN_REVIEW` | `MISSING_NCM` | O produto está no catálogo sem NCM, e nenhuma regra que dispense o NCM se aplicou. | Não presuma tributação integral. O caso vai para a curadoria fiscal; consulte de novo depois. | | `IN_REVIEW` | `MISSING_RULE` | O produto tem NCM, mas não há regra vigente para ele com esse CFOP (e setor). | Idem: curadoria fiscal, nova consulta depois. | | `IN_REVIEW` | `INCOMPLETE_CLASSIFICATION` | Há alternativas, mas pelo menos uma está sem cálculo (`UNAVAILABLE`) ou é um alerta de coerência (`stage: COHERENCE`). | Não emita automaticamente. As alternativas calculadas são informativas; encaminhe para revisão. | | `NOT_FOUND` | `null` | A GS1 informou que o GTIN não existe. Só na consulta unitária. | Confira o código de barras no cadastro do item. | Sem classificação concluída, nunca preencha o documento com tributação integral por conta própria. A ausência de regra não quer dizer que o produto é tributado integralmente: quer dizer que ninguém decidiu ainda. ## Produto fora do catálogo O catálogo do GetTax é formado por produtos da GS1. Quando o GTIN ainda não está lá: - **Consulta unitária**: o GetTax pode buscar o produto na GS1 no momento da requisição, quando essa busca está ativa no ambiente. Se encontrar, classifica na mesma resposta. Se não conseguir concluir, responde `PENDING`. Se a GS1 informar que o GTIN não existe, responde `NOT_FOUND`; essa resposta fica guardada por um período (hoje, 7 dias) e é repetida sem nova busca. - **Lote**: nunca busca na GS1. GTIN fora do catálogo volta `PENDING` e entra na fila de busca. `retryAfterSeconds` só aparece em `PENDING`, quando a busca foi adiada porque o limite diário de consultas do GetTax à GS1 acabou. É o número de segundos até esse limite reiniciar. > [!WARNING] > Não repita a consulta em loop. Toda consulta admitida consome franquia, inclusive as que respondem `PENDING`. Depois de uma falha da GS1, o GetTax espera um intervalo antes de tentar de novo, então repetir antes disso só gasta franquia. Se um GTIN continuar `PENDING` por dias, fale com a equipe GetTax. `PENDING` por limite diário da GS1: ```json { "decisionVersion": "7b8c9d0e-1f2a-4b3c-8d4e-5f6a7b8c9d0e", "status": "PENDING", "retryAfterSeconds": 41520, "reason": "LOCAL_PRODUCT_MISSING", "gtin": "07891000315521", "cfop": "5102", "sector": null, "referenceDate": "2026-10-20", "product": null, "classifications": [] } ``` `IN_REVIEW` por falta de NCM: ```json { "decisionVersion": "9d0e1f2a-3b4c-4d5e-af60-7b8c9d0e1f2a", "status": "IN_REVIEW", "reason": "MISSING_NCM", "gtin": "07898357410015", "cfop": "5102", "sector": "VAREJO_GERAL", "referenceDate": "2026-10-20", "product": { "id": "0e1f2a3b-4c5d-4e6f-8a7b-8c9d0e1f2a3b", "gtinAsProvided": "7898357410015", "description": "BISCOITO EXEMPLO 200G", "brand": "MARCA EXEMPLO", "ncm": null, "ncmSource": null, "cest": null, "gpcCode": null, "imageUrl": null, "sourceKind": "BULK" }, "classifications": [] } ``` `NOT_FOUND`: ```json { "decisionVersion": "8c9d0e1f-2a3b-4c4d-9e5f-6a7b8c9d0e1f", "status": "NOT_FOUND", "reason": null, "gtin": "07891234567895", "cfop": "5102", "sector": null, "referenceDate": "2026-10-20", "product": null, "classifications": [] } ``` `NOT_FOUND` no corpo de uma resposta 200 não é o mesmo que HTTP 404, que indica rota inexistente. ## Alternativas Mais de uma alternativa é normal. Acontece quando existe regra genérica e regra do setor, ou quando o mesmo produto tem cClassTribs diferentes para condições diferentes (por exemplo, conforme o regime do destinatário). Nenhuma alternativa é descartada só porque outra é mais específica. > [!IMPORTANT] > A ordem das alternativas não é recomendação fiscal. É técnica e estável (por etapa, depois por código), para a resposta não mudar entre execuções. Nunca escolha a primeira automaticamente. Cada alternativa traz: - `cst` e `cClassTrib`: o par que vai no documento fiscal, igual para CBS e IBS. - `applicability`: a condição em que a alternativa se aplica, em texto, ou `null`. - `observation`: um alerta ou contexto da curadoria, ou `null`. - `legalBasis`: o fundamento legal. - `components` e `calculation`: as alíquotas por componente. Ver [Componentes e alíquotas](https://kind-coast-062131010.2.azurestaticapps.net/guias/componentes-e-aliquotas.md). O GetTax não recebe o regime do emitente nem detalhes da operação além do CFOP. Quem confirma se a condição de uma alternativa vale para a operação é o emissor: uma pessoa, ou uma regra de negócio explícita do seu sistema que avalie a condição. Com uma única alternativa sem condição, não há o que escolher. ## Etapas do motor `stage` diz qual etapa produziu a alternativa. As etapas são percorridas nesta ordem: | Etapa | O que faz | | --- | --- | | `OPERATION` | A operação (CFOP) resolve sozinha, sem depender do produto. Se houver regra desta etapa, a classificação termina aqui, sem passar pelas etapas seguintes. | | `COHERENCE` | Alerta de incoerência entre produto e operação, por exemplo um combustível vendido com CFOP genérico de venda. Acrescenta alternativas às de `PRODUCT`; nunca resolve sozinha. Torna o status `IN_REVIEW`. | | `PRODUCT` | Classificação pelo produto: família de NCM (4 dígitos), NCM completo (8 dígitos) ou exceção cadastrada para um GTIN. | | `FALLBACK` | Regra de contingência cadastrada explicitamente pela curadoria. Só entra quando `PRODUCT` não resolve e o produto tem NCM. | Não existe classificação padrão implícita: se nenhuma regra se aplica, o resultado é `IN_REVIEW`, nunca uma alíquota cheia presumida. ## Versões e vigências Cada alternativa diz de onde veio cada peça: - `rule.id` e `rule.version`: a regra curada aplicada. - `taxClassification`: a linha da tabela oficial de cClassTrib, com `sourceVersion`. - `rates[]`: as linhas da tabela de alíquotas, uma por componente, com `sourceVersion`. Todas têm vigência `[effectiveFrom, effectiveTo)`. Guarde esses campos com o documento emitido: é o que permite explicar depois de onde veio cada número. Ver [Boas práticas](https://kind-coast-062131010.2.azurestaticapps.net/guias/boas-praticas.md#guarde-a-decisao-com-o-documento). --- # Componentes e alíquotas CBS, IBS_UF e IBS_MUN, valores decimais em string e os três estados de cálculo de uma alternativa. Versão HTML: https://kind-coast-062131010.2.azurestaticapps.net/guias/componentes-e-aliquotas/ Cada alternativa de enquadramento traz o resultado por componente do tributo, em `components`, e o estado do cálculo, em `calculation`. ## Um par CST/cClassTrib, três componentes A regra fiscal produz um par (CST, cClassTrib). O GetTax aplica esse par aos três componentes: | Componente | Tributo | | --- | --- | | `CBS` | Contribuição sobre Bens e Serviços (federal) | | `IBS_UF` | Imposto sobre Bens e Serviços, parcela estadual | | `IBS_MUN` | Imposto sobre Bens e Serviços, parcela municipal | CST e cClassTrib são os mesmos nos três componentes. O que varia é a alíquota e, entre CBS e IBS, a redução: a tabela oficial de cClassTrib traz uma redução para a CBS (`reductionPctCbs`) e outra para o IBS (`reductionPctIbs`, aplicada a `IBS_UF` e `IBS_MUN`). Trate a lista de componentes como aberta: o Imposto Seletivo, por exemplo, está previsto para 2027. Seu sistema não deve quebrar ao receber um componente novo. ## Valores decimais Alíquotas e reduções são strings com fração decimal e 6 casas. Nunca percentuais inteiros, nunca números de ponto flutuante. | Valor | Significa | | --- | --- | | `"0.009000"` | 0,9% | | `"0.001000"` | 0,1% | | `"0.600000"` | 60% | | `"1.000000"` | 100% | A alíquota efetiva segue sempre a mesma fórmula: ```http effectiveRate = standardRate × (1 − reductionPct) ``` Com CBS de 0,9% e redução de 60%: `0.009000 × (1 − 0.600000) = 0.003600`, ou seja, 0,36%. Converta as strings direto para um tipo decimal exato (`decimal` em C# e SQL, `BigDecimal` em Java, `Decimal` em Python, `bcmath` em PHP) e guarde como texto ou decimal. Não passe por `float` ou `double`. Ver [Boas práticas](https://kind-coast-062131010.2.azurestaticapps.net/guias/boas-praticas.md#valores-fiscais-como-decimal). ## Estado do cálculo `calculation.status` diz se a alternativa tem números e de que tipo. Ele deriva do `calculationMode` da linha de cClassTrib: | `calculationMode` (tabela) | `calculation.status` | `components` | | --- | --- | --- | | `STANDARD` | `CALCULATED` | Três componentes `STANDARD`, com `standardRate`, `reductionPct` e `effectiveRate`. | | `NOT_DUE` | `NOT_DUE` | Três componentes `NOT_DUE`, sem alíquota nem redução. | | `UNSUPPORTED` | `UNAVAILABLE` com `CALCULATION_UNSUPPORTED` | `null` | `UNAVAILABLE` também aparece quando falta algo para calcular. O motivo vem em `calculation.reason`: | `reason` | Significa | | --- | --- | | `TAX_CLASSIFICATION_MISSING` | Não há linha vigente de cClassTrib para o código produzido pela regra. `taxClassification` vem `null`. | | `CST_MISMATCH` | O CST da regra diverge do CST do código na tabela oficial. | | `RATE_MISSING` | Falta alíquota vigente para algum componente. | | `CALCULATION_UNSUPPORTED` | O código tem mecânica que o motor ainda não calcula, como diferimento e monofasia. | Uma alternativa `UNAVAILABLE` continua na resposta, com o motivo. Ela não é descartada nem recebe uma alíquota obtida por analogia, e deixa o status da consulta em `IN_REVIEW` com `INCOMPLETE_CLASSIFICATION`. Trecho de `classifications` com duas alternativas para o mesmo produto: uma calculada, com reduções diferentes para CBS e IBS, e uma de diferimento, sem cálculo (valores ilustrativos): ```json [ { "stage": "PRODUCT", "rule": { "id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d", "version": 1, "effectiveFrom": "2026-01-01", "effectiveTo": null, "ncm": "10062010", "gtin": null, "sector": null }, "cst": "200", "cClassTrib": "200038", "applicability": "Insumo agropecuário, destinatário fora das hipóteses do art. 138 §2º.", "observation": null, "legalBasis": "LC 214/2025, Art. 138", "taxClassification": { "id": "b2c3d4e5-f6a7-4b8c-9d0e-1f2a3b4c5d6e", "sourceVersion": "CCLASSTRIB-2026", "effectiveFrom": "2026-01-01", "effectiveTo": null, "cst": "200", "cClassTrib": "200038", "reductionPctIbs": "0.600000", "reductionPctCbs": "0.300000", "gTribRegular": false, "isApplicable": true, "calculationMode": "STANDARD", "legalBasis": "LC 214/2025, Art. 138" }, "rates": [ { "id": "0b1c2d3e-4f50-4a61-8b72-c3d4e5f60718", "sourceVersion": "ALIQUOTAS-2026", "effectiveFrom": "2026-01-01", "effectiveTo": null, "component": "CBS", "rate": "0.009000" }, { "id": "1c2d3e4f-5061-4b72-9c83-d4e5f6071829", "sourceVersion": "ALIQUOTAS-2026", "effectiveFrom": "2026-01-01", "effectiveTo": null, "component": "IBS_UF", "rate": "0.001000" }, { "id": "2d3e4f50-6172-4c83-ad94-e5f60718293a", "sourceVersion": "ALIQUOTAS-2026", "effectiveFrom": "2026-01-01", "effectiveTo": null, "component": "IBS_MUN", "rate": "0.000000" } ], "components": [ { "component": "CBS", "cst": "200", "cClassTrib": "200038", "status": "STANDARD", "standardRate": "0.009000", "reductionPct": "0.300000", "effectiveRate": "0.006300" }, { "component": "IBS_UF", "cst": "200", "cClassTrib": "200038", "status": "STANDARD", "standardRate": "0.001000", "reductionPct": "0.600000", "effectiveRate": "0.000400" }, { "component": "IBS_MUN", "cst": "200", "cClassTrib": "200038", "status": "STANDARD", "standardRate": "0.000000", "reductionPct": "0.600000", "effectiveRate": "0.000000" } ], "calculation": { "status": "CALCULATED" } }, { "stage": "PRODUCT", "rule": { "id": "c3d4e5f6-a7b8-4c9d-8e0f-1a2b3c4d5e6f", "version": 1, "effectiveFrom": "2026-01-01", "effectiveTo": null, "ncm": "10062010", "gtin": null, "sector": null }, "cst": "515", "cClassTrib": "515001", "applicability": "Insumo agropecuário com destinatário do regime regular nas hipóteses do art. 138 §2º.", "observation": "Depende do regime do destinatário, que a requisição não carrega.", "legalBasis": "LC 214/2025, Art. 138, § 2º", "taxClassification": { "id": "d4e5f6a7-b8c9-4d0e-9f1a-2b3c4d5e6f7a", "sourceVersion": "CCLASSTRIB-2026", "effectiveFrom": "2026-01-01", "effectiveTo": null, "cst": "515", "cClassTrib": "515001", "reductionPctIbs": "0.600000", "reductionPctCbs": "0.600000", "gTribRegular": false, "isApplicable": true, "calculationMode": "UNSUPPORTED", "legalBasis": "LC 214/2025, Art. 138, § 2º" }, "rates": [ { "id": "0b1c2d3e-4f50-4a61-8b72-c3d4e5f60718", "sourceVersion": "ALIQUOTAS-2026", "effectiveFrom": "2026-01-01", "effectiveTo": null, "component": "CBS", "rate": "0.009000" }, { "id": "1c2d3e4f-5061-4b72-9c83-d4e5f6071829", "sourceVersion": "ALIQUOTAS-2026", "effectiveFrom": "2026-01-01", "effectiveTo": null, "component": "IBS_UF", "rate": "0.001000" }, { "id": "2d3e4f50-6172-4c83-ad94-e5f60718293a", "sourceVersion": "ALIQUOTAS-2026", "effectiveFrom": "2026-01-01", "effectiveTo": null, "component": "IBS_MUN", "rate": "0.000000" } ], "components": null, "calculation": { "status": "UNAVAILABLE", "reason": "CALCULATION_UNSUPPORTED" } } ] ``` A primeira alternativa tem CBS efetiva de 0,63% (redução de 30%) e IBS-UF efetiva de 0,04% (redução de 60%). A segunda depende do regime do destinatário, como diz `observation`, e não tem número. A consulta inteira volta `IN_REVIEW`. ## Não incidência não é redução de 100% São situações fiscais diferentes, com CSTs diferentes, e o GetTax as representa de formas diferentes: - **Redução de 100%**: o tributo é devido, com base reduzida a zero. Componentes `STANDARD`, com `reductionPct` `"1.000000"` e `effectiveRate` `"0.000000"`. - **Não incidência, imunidade**: não há tributo a apresentar. `calculation.status` é `NOT_DUE` e os componentes vêm com `status: "NOT_DUE"`, sem alíquota nem redução. Não converta um no outro. Em `NOT_DUE`, não preencha alíquotas zeradas por conta própria. Alternativa `NOT_DUE`, de uma transferência entre estabelecimentos do mesmo titular (CFOP `5152`, etapa `OPERATION`): ```json { "stage": "OPERATION", "rule": { "id": "e5f6a7b8-c9d0-4e1f-a2b3-c4d5e6f7a8b9", "version": 1, "effectiveFrom": "2026-01-01", "effectiveTo": null, "ncm": null, "gtin": null, "sector": null }, "cst": "410", "cClassTrib": "410002", "applicability": "Transferência entre estabelecimentos do mesmo titular.", "observation": null, "legalBasis": "LC 214/2025, Art. 6º, II", "taxClassification": { "id": "f6a7b8c9-d0e1-4f2a-b3c4-d5e6f7a8b9c0", "sourceVersion": "CCLASSTRIB-2026", "effectiveFrom": "2026-01-01", "effectiveTo": null, "cst": "410", "cClassTrib": "410002", "reductionPctIbs": "0.000000", "reductionPctCbs": "0.000000", "gTribRegular": false, "isApplicable": true, "calculationMode": "NOT_DUE", "legalBasis": "LC 214/2025, Art. 6º, II" }, "rates": [ { "id": "0b1c2d3e-4f50-4a61-8b72-c3d4e5f60718", "sourceVersion": "ALIQUOTAS-2026", "effectiveFrom": "2026-01-01", "effectiveTo": null, "component": "CBS", "rate": "0.009000" }, { "id": "1c2d3e4f-5061-4b72-9c83-d4e5f6071829", "sourceVersion": "ALIQUOTAS-2026", "effectiveFrom": "2026-01-01", "effectiveTo": null, "component": "IBS_UF", "rate": "0.001000" }, { "id": "2d3e4f50-6172-4c83-ad94-e5f60718293a", "sourceVersion": "ALIQUOTAS-2026", "effectiveFrom": "2026-01-01", "effectiveTo": null, "component": "IBS_MUN", "rate": "0.000000" } ], "components": [ { "component": "CBS", "cst": "410", "cClassTrib": "410002", "status": "NOT_DUE" }, { "component": "IBS_UF", "cst": "410", "cClassTrib": "410002", "status": "NOT_DUE" }, { "component": "IBS_MUN", "cst": "410", "cClassTrib": "410002", "status": "NOT_DUE" } ], "calculation": { "status": "NOT_DUE" } } ``` ## Tabelas por trás do cálculo - `taxClassification` é a linha da tabela oficial de cClassTrib usada: CST, reduções de CBS e IBS, modo de cálculo e fundamento legal do código, com `sourceVersion` e vigência. - `rates[]` são as alíquotas padrão vigentes na data de referência, uma por componente, também com `sourceVersion` e vigência. Elas vêm mesmo quando a alternativa não tem cálculo. - O `legalBasis` que vale para a alternativa é o dela, não o de `taxClassification`: a curadoria pode cadastrar um fundamento próprio para a regra. --- # Franquia e consumo O que consome a franquia mensal de consultas, o que não consome e o que acontece quando ela acaba. Versão HTML: https://kind-coast-062131010.2.azurestaticapps.net/guias/franquia/ Cada software house tem uma franquia mensal de consultas, definida no plano. A franquia é da software house, não da chave: todas as chaves dela consomem do mesmo saldo. O mês é o mês-calendário no fuso de São Paulo: o contador recomeça às 00h00 do dia 1º, horário de Brasília. ## O que consome Uma consulta consome uma unidade quando é **admitida**: a chave é válida, o corpo é válido e ainda há franquia. A partir daí, a unidade está gasta, qualquer que seja o resultado. | Consome uma unidade | Não consome | | --- | --- | | Cada consulta admitida em `POST /v1/classifications/resolve`. | `GET /v1/enums/sectors`. | | Cada item admitido em `POST /v1/classifications/batch`: um lote de 40 itens válidos consome 40. | Requisições recusadas na validação (`400`). | | GTIN repetido, no mesmo lote ou em requisições diferentes. | Requisições recusadas na autenticação (`401`). | | Consultas com qualquer status: `CLASSIFIED`, `PENDING`, `IN_REVIEW` ou `NOT_FOUND`. | Itens do lote recusados com `INVALID_REQUEST`. | | Consultas admitidas que falham depois (`503`): a unidade já tinha sido reservada. | Itens do lote recusados com `QUOTA_EXCEEDED` depois que a franquia acabou. | ## Quando a franquia acaba - **Consulta unitária**: HTTP 429 com `{"error": "QUOTA_EXCEEDED"}`. - **Lote**: HTTP 200. Os itens admitidos antes do limite são mantidos e resolvidos; os restantes voltam como `REJECTED` com `QUOTA_EXCEEDED`. O lote nunca responde 429. As consultas voltam a ser aceitas na virada do mês. Para ampliar a franquia antes disso, fale com a equipe GetTax. ## Onde acompanhar o consumo A API não devolve o saldo em cabeçalho nem em rota própria. O consumo fica no [portal da revenda](https://app-web-05-prd-wl-gettax-prd.azurewebsites.net), em **Consumo**: - a franquia do mês: quanto já foi usado, quanto resta e quando renova; - as consultas por dia; - as consultas recentes, com GTIN, CFOP, setor e status de cada uma. O detalhe das consultas fica disponível pelos últimos 12 meses. ## Como gastar menos - **Reaproveite as respostas.** A classificação depende de GTIN, CFOP, setor e data de referência, não do seu cliente final. Guarde a resposta no seu banco com essa chave e reutilize entre os seus clientes, em vez de consultar de novo a cada venda. Ver [Boas práticas](https://kind-coast-062131010.2.azurestaticapps.net/guias/boas-praticas.md#reaproveite-as-respostas). - **Não repita `PENDING` em loop.** Cada nova consulta consome. Respeite `retryAfterSeconds` e espace as tentativas. Ver [Status e alternativas](https://kind-coast-062131010.2.azurestaticapps.net/guias/status-e-alternativas.md#produto-fora-do-catalogo). - **Não reenvie itens de lote já resolvidos.** Reenvie só os `REJECTED` com `SERVICE_UNAVAILABLE` ou `QUOTA_EXCEEDED`. - **Valide a chave com a lista de setores**, que não consome, e não com uma consulta. --- # Erros e novas tentativas Códigos de erro, status HTTP, o que fazer em cada caso e quando repetir uma requisição. Versão HTML: https://kind-coast-062131010.2.azurestaticapps.net/guias/erros/ Erros têm sempre o mesmo formato: um objeto com o código em `error`. ```json { "error": "INVALID_REQUEST" } ``` Não há mensagem detalhada. Erros de validação não dizem qual campo falhou: confira o corpo contra a [referência](https://kind-coast-062131010.2.azurestaticapps.net/referencia/resolve-classification.md) e o guia [Dados da consulta](https://kind-coast-062131010.2.azurestaticapps.net/guias/dados-da-consulta.md). ## Códigos | HTTP | `error` | Quando | O que fazer | | --- | --- | --- | --- | | 400 | `INVALID_REQUEST` | JSON malformado, campo obrigatório ausente, GTIN fora do formato ou com dígito verificador errado, CFOP sem 4 dígitos, setor desconhecido, data inválida, campo não previsto; no lote, envelope inválido (vazio, mais de 100 itens, campo além de `items`, item sem `gtin` ou `cfop` em texto). | Corrija a requisição. Não repita igual. Não consome franquia. | | 401 | `INVALID_API_KEY` | Cabeçalho ausente ou fora do formato `Bearer gtx_…`; chave inexistente, revogada ou substituída; cliente desativado. | Confira o cabeçalho e, no portal da revenda, se a chave está ativa. Persistindo, crie uma nova. Não consome franquia. | | 404 | `NOT_FOUND` | Rota inexistente. | Confira o método e o caminho. | | 429 | `QUOTA_EXCEEDED` | Franquia mensal esgotada. Só na consulta unitária; no lote, aparece por item. | Espere a virada do mês ou fale com a equipe GetTax. Não repita antes disso. | | 500 | `INTERNAL_ERROR` | Erro inesperado. | Repita com backoff. Persistindo, reporte. | | 503 | `SERVICE_UNAVAILABLE` | Banco ou serviço temporariamente indisponível. | Repita com backoff. Se a falha ocorreu depois da admissão, a unidade já foi consumida. | O 404 de rota inexistente não tem relação com `status: "NOT_FOUND"` no corpo de uma resposta 200, que diz que o GTIN não existe na GS1. > [!TIP] > Sempre envie `Content-Type: application/json` nas requisições com corpo. Uma requisição com outro tipo de conteúdo não é tratada como erro de validação e pode voltar como `500 INTERNAL_ERROR`. ## Quando repetir Repita só o que pode dar certo sem mudar nada: | Resposta | Repetir? | | --- | --- | | `500`, `503` | Sim, com backoff exponencial. | | `429` | Não, até a virada do mês. | | `400`, `401`, `404` | Não. Corrija a requisição ou a chave. | | `200` com `PENDING` | Mais tarde, respeitando `retryAfterSeconds`. Não em loop. | | `200` com `IN_REVIEW` | Mais tarde: depende da curadoria fiscal, não de tentativa. | Um backoff razoável: espere 1 s, depois 2 s, 4 s, 8 s, com uma variação aleatória em cada espera, e desista depois de 4 ou 5 tentativas. Cada nova tentativa de uma consulta que já tinha sido admitida consome outra unidade da franquia. ## Erros no lote No lote, problemas de um item não derrubam os outros. A resposta é HTTP 200, e cada item recusado volta com `outcome: "REJECTED"` e o próprio `error`: | `error` do item | Significa | Consome? | O que fazer | | --- | --- | --- | --- | | `INVALID_REQUEST` | O item é inválido. Afeta só ele. | Não | Corrija o item. | | `QUOTA_EXCEEDED` | A franquia acabou neste item. Este e todos os seguintes voltam assim. | Não | Reenvie depois da virada do mês. | | `INVALID_API_KEY` | A chave deixou de valer durante o lote. Este e todos os seguintes voltam assim. | Não | Confira a chave e reenvie. | | `SERVICE_UNAVAILABLE` | Falha temporária. Na admissão, afeta este item e os seguintes; ao resolver um item já admitido, afeta só ele. | Só se o item já tinha sido admitido | Reenvie com backoff. | Reenvie só os itens recusados. Os `RESOLVED` já foram cobrados. ```json { "results": [ { "outcome": "REJECTED", "index": 0, "error": "INVALID_REQUEST" }, { "outcome": "REJECTED", "index": 1, "error": "QUOTA_EXCEEDED" }, { "outcome": "REJECTED", "index": 2, "error": "QUOTA_EXCEEDED" } ] } ``` ## Ao reportar um problema Envie à equipe GetTax: horário da chamada, rota, corpo enviado (sem a chave), status HTTP recebido e o `decisionVersion` da resposta, quando houver. --- # Boas práticas O que guardar, como tratar valores fiscais e como integrar o GetTax a um emissor de documentos fiscais. Versão HTML: https://kind-coast-062131010.2.azurestaticapps.net/guias/boas-praticas/ ## Envie a operação real - Envie o CFOP da operação que vai ser emitida. Não use um CFOP de venda como padrão para tudo: devolução, transferência e remessa podem ter outro CST. - Envie `sector` quando souber o setor do seu cliente final. Sem setor, vêm todas as alternativas, de qualquer setor. - Valide o dígito verificador do GTIN antes de enviar. Um GTIN inválido não consome franquia, mas custa uma ida e volta. ## Trate os quatro status - Só `CLASSIFIED` é resultado concluído. `IN_REVIEW` pode trazer alternativas calculadas, mas não deve ser emitido automaticamente. - Sem classificação concluída, não presuma tributação integral nem preencha alíquotas por conta própria. - Com mais de uma alternativa, a escolha é do emissor, pela condição em `applicability`. Nunca pela posição na lista. ```node const res = await fetch(`${process.env.GETTAX_URL}/v1/classifications/resolve`, { method: "POST", headers: { Authorization: `Bearer ${process.env.GETTAX_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ gtin: "7891000315507", cfop: "5102", sector: "VAREJO_GERAL" }), }); if (!res.ok) { const { error } = await res.json(); // { "error": "INVALID_REQUEST" }, etc. throw new Error(`GetTax ${res.status}: ${error}`); } const decision = await res.json(); switch (decision.status) { case "CLASSIFIED": // Todas as alternativas pertinentes. A ordem não é recomendação: // com mais de uma, o emissor escolhe pela condição em `applicability`. await saveDecision(decision); break; case "IN_REVIEW": // Pode trazer alternativas, mas o resultado não está concluído. await sendToReview(decision); break; case "PENDING": // Produto fora do catálogo. Consulte de novo mais tarde, sem loop. await retryLater(decision.gtin, decision.retryAfterSeconds); break; case "NOT_FOUND": // A GS1 não conhece o GTIN: confira o cadastro do item. await flagInvalidGtin(decision.gtin); break; } ``` ## Guarde a decisão com o documento Junto de cada documento fiscal emitido, guarde: - `decisionVersion`: identifica a decisão na trilha de auditoria do GetTax. - `referenceDate`, `cfop` e `sector` usados na consulta. - Da alternativa aplicada: `cst`, `cClassTrib`, `rule.id`, `rule.version`, `taxClassification.sourceVersion` e os `sourceVersion` de `rates[]`. - Os valores de `components[]` como vieram. É o que permite explicar depois de onde veio cada número, mesmo que a regra ou a alíquota mude. `decisionVersion` é novo a cada consulta, mesmo com a mesma entrada e o mesmo resultado. Ele identifica a consulta, não a classificação: para saber se a classificação mudou, compare `cst`, `cClassTrib`, `rule.id` e `rule.version`. ## Valores fiscais como decimal Alíquotas e reduções chegam como strings de fração decimal (`"0.009000"` = 0,9%). Mantenha a precisão: - Converta direto para um tipo decimal exato e guarde como decimal ou texto. Nunca passe por `float` ou `double`. - Não converta para percentual inteiro antes de guardar. Se precisar exibir, formate só na tela. - Recalcule, se quiser conferir, com a fórmula `effectiveRate = standardRate × (1 − reductionPct)`, em decimal. ```csharp using System.Globalization; // "0.003600" -> 0.003600m, sem passar por double var effectiveRate = decimal.Parse(component.GetProperty("effectiveRate").GetString()!, CultureInfo.InvariantCulture); ``` ```python from decimal import Decimal effective_rate = Decimal(component["effectiveRate"]) # Decimal('0.003600') ``` Em JavaScript, `Number("0.003600")` é ponto flutuante. Mantenha a string ou use uma biblioteca decimal. ## Reaproveite as respostas A classificação depende de GTIN, CFOP, setor e data de referência, não do seu cliente final. Guarde a resposta no seu banco e reutilize entre os seus clientes: - Use como chave o GTIN de 14 dígitos, o CFOP e o setor (ou a ausência dele). - A decisão vale enquanto a data de referência estiver dentro da vigência de tudo o que ela usou: o menor `effectiveTo` entre a regra, a linha de cClassTrib e as alíquotas. `null` quer dizer sem término previsto. - A curadoria publica regras e versões novas. Reconsulte periodicamente, e sempre que a data passar de um `effectiveTo`. - Não guarde em cache `PENDING` nem `IN_REVIEW` como resultado final. ## Escolha a rota certa - **Consulta unitária** para o dia a dia: item novo no cadastro, conferência antes da emissão. Pode buscar na GS1 um produto que ainda não está no catálogo, quando a busca está ativa no ambiente, por isso pode levar alguns segundos a mais nesse caso. - **Lote** para carga e revisão de catálogo: até 100 itens por requisição, sem busca na GS1. Itens `PENDING` do lote podem ser reconsultados depois, pela consulta unitária. - **Lista de setores** para validar a chave e checar a saúde da integração, sem consumir franquia. ## Integração robusta - Chame a API pelo seu backend e guarde a chave num cofre de segredos. Ver [Autenticação](https://kind-coast-062131010.2.azurestaticapps.net/guias/autenticacao.md). - Configure timeout no seu cliente HTTP e repita só `500` e `503`, com backoff. Ver [Erros e novas tentativas](https://kind-coast-062131010.2.azurestaticapps.net/guias/erros.md#quando-repetir). - Trate enums como abertos: novos setores e componentes podem surgir. Leia os setores de [`GET /v1/enums/sectors`](https://kind-coast-062131010.2.azurestaticapps.net/referencia/list-sectors.md). - Ignore campos que você não conhece na resposta, em vez de falhar. --- # Consultar classificação Classifica um produto (GTIN) para uma operação (CFOP) e devolve as alternativas de enquadramento de CBS e IBS. Versão HTML: https://kind-coast-062131010.2.azurestaticapps.net/referencia/resolve-classification/ `POST /v1/classifications/resolve` Base URL: `https://app-web-hmg-01-api-gettax-hmg-dvawffg9g9cpcef3.brazilsouth-01.azurewebsites.net` (homologação). Autenticação: header `Authorization: Bearer `. [Como obter a chave](https://kind-coast-062131010.2.azurestaticapps.net/guias/autenticacao.md) Classifica um produto para uma operação, com as regras e alíquotas vigentes na data de referência. É a consulta do dia a dia: cadastro de um item novo, conferência antes da emissão, reclassificação de um produto específico. - **Todo resultado de negócio chega com HTTP 200.** O que aconteceu está em `status` e `reason`; trate os quatro casos. Ver [Status e alternativas](https://kind-coast-062131010.2.azurestaticapps.net/guias/status-e-alternativas.md). - **Pode vir mais de uma alternativa** em `classifications`. A ordem não é recomendação: o emissor escolhe pela condição em `applicability`. - **GTIN fora do catálogo.** A consulta unitária pode buscar o produto na GS1 no momento da requisição, quando essa busca está ativa no ambiente. Se não conseguir, responde `PENDING`; respeite `retryAfterSeconds` quando vier. - **Franquia.** Cada consulta admitida consome uma unidade, qualquer que seja o status, GTIN repetido inclusive. Respostas 400 e 401 não consomem. Ver [Franquia e consumo](https://kind-coast-062131010.2.azurestaticapps.net/guias/franquia.md). Para classificar muitos itens de uma vez, use a [consulta em lote](https://kind-coast-062131010.2.azurestaticapps.net/referencia/resolve-classification-batch.md). > [!NOTE] > Os valores fiscais dos exemplos (NCM, cClassTrib, alíquotas, fundamento legal) são ilustrativos. ## Requisição Corpo JSON (`Content-Type: application/json`). - `gtin` (string, obrigatório) — Código de barras do produto: só dígitos, com 8, 12, 13 ou 14 posições e dígito verificador válido. Sem máscara, espaços ou hífens. Restrições: padrão `^\d{8}$|^\d{12,14}$`. - `cfop` (string, obrigatório) — CFOP da operação, com 4 dígitos (ex.: `5102`). Obrigatório e sem valor padrão: o CST pode mudar com a operação. Ver [Dados da consulta](https://kind-coast-062131010.2.azurestaticapps.net/guias/dados-da-consulta.md#cfop). Restrições: padrão `^\d{4}$`. - `sector` (string, opcional) — Setor do cliente final. Ausente: todas as alternativas pertinentes. Informado: as genéricas mais as daquele setor. Omitir não equivale a `VAREJO_GERAL`. Valores: `VAREJO_GERAL`, `BAR_RESTAURANTE`, `PRODUTOR_RURAL`, `GOVERNO`, `ATACADO`, `ZONA_FRANCA`. - `referenceDate` (string, opcional) — Data (`AAAA-MM-DD`) usada para escolher regras e alíquotas vigentes. Padrão: hoje, no fuso de São Paulo. Restrições: data AAAA-MM-DD. ## Exemplo `$GETTAX_URL` é a base URL acima e `$GETTAX_KEY` a sua chave de API. ```shell curl -sS -X POST "$GETTAX_URL/v1/classifications/resolve" \ -H "Authorization: Bearer $GETTAX_KEY" \ -H "Content-Type: application/json" \ -d '{"gtin":"7891000315507","cfop":"5102"}' ``` ## Respostas ### 200 · Consulta processada. Os quatro status de negócio (`CLASSIFIED`, `PENDING`, `IN_REVIEW`, `NOT_FOUND`) chegam com 200. Campos: - `decisionVersion` (string, obrigatório) — Identificador da decisão, gravada em trilha de auditoria imutável. Cada consulta gera um novo, mesmo com a mesma entrada. Guarde junto do documento fiscal e informe ao reportar um problema. Restrições: UUID. - `status` (string, obrigatório) — Resultado da consulta: `CLASSIFIED`, `PENDING`, `IN_REVIEW` ou `NOT_FOUND`. Ver [Status e alternativas](https://kind-coast-062131010.2.azurestaticapps.net/guias/status-e-alternativas.md). Valores: `CLASSIFIED`, `PENDING`, `IN_REVIEW`, `NOT_FOUND`. - `retryAfterSeconds` (integer, opcional) — Só em `PENDING`, quando a busca do produto foi adiada pelo limite diário de consultas do GetTax à GS1: segundos até esse limite reiniciar. Não consulte o mesmo GTIN antes disso. Ausente nos demais casos. Restrições: mínimo 0. - `reason` (string, obrigatório, pode ser null) — Motivo do status: `LOCAL_PRODUCT_MISSING` (produto fora do catálogo), `MISSING_NCM`, `MISSING_RULE` ou `INCOMPLETE_CLASSIFICATION`. `null` em `CLASSIFIED` e `NOT_FOUND`. Valores: `LOCAL_PRODUCT_MISSING`, `MISSING_NCM`, `MISSING_RULE`, `INCOMPLETE_CLASSIFICATION`. - `gtin` (string, obrigatório) — GTIN normalizado com 14 dígitos (zeros à esquerda). - `cfop` (string, obrigatório) — CFOP consultado. - `sector` (string, obrigatório, pode ser null) — Setor enviado; `null` quando a consulta não informou setor. Valores: `VAREJO_GERAL`, `BAR_RESTAURANTE`, `PRODUTOR_RURAL`, `GOVERNO`, `ATACADO`, `ZONA_FRANCA`. - `referenceDate` (string, obrigatório) — Data de referência efetivamente usada: a enviada ou a data de hoje em São Paulo. Restrições: data AAAA-MM-DD. - `product` (object, obrigatório, pode ser null) — Produto no catálogo do GetTax. `null` quando o GTIN não está no catálogo (`PENDING` e `NOT_FOUND`). - `id` (string, obrigatório) — Identificador interno do produto. Restrições: UUID. - `gtinAsProvided` (string, obrigatório, pode ser null) — GTIN na forma em que entrou no catálogo, antes da normalização para 14 dígitos. - `description` (string, obrigatório, pode ser null) — Descrição do produto, quando a origem informa. - `brand` (string, obrigatório, pode ser null) — Marca, quando a origem informa. - `ncm` (string, obrigatório, pode ser null) — NCM de 8 dígitos, sem pontuação. `null` quando a origem não informou. Sem NCM, só se aplicam regras que não dependem dele (por operação ou exceção por GTIN). - `ncmSource` (string, obrigatório, pode ser null) — Origem do NCM (hoje, `GS1`). `null` quando não há NCM. - `cest` (string, obrigatório, pode ser null) — CEST, quando a origem informa. - `gpcCode` (string, obrigatório, pode ser null) — Código de categoria GPC da GS1, quando informado. - `imageUrl` (string, obrigatório, pode ser null) — URL de imagem do produto, quando informada. - `sourceKind` (string, obrigatório) — Como o produto entrou no catálogo: `BULK` (carga de arquivo da GS1) ou `PROVIDER` (busca individual na GS1). - `classifications` (array, obrigatório) — Alternativas de enquadramento. Vazio quando não há alternativa. A ordem é técnica e estável, não recomendação: não escolha a primeira automaticamente. - `stage` (string, obrigatório) — Etapa do motor que produziu a alternativa: `OPERATION`, `COHERENCE`, `PRODUCT` ou `FALLBACK`. Ver [Etapas do motor](https://kind-coast-062131010.2.azurestaticapps.net/guias/status-e-alternativas.md#etapas-do-motor). Valores: `OPERATION`, `COHERENCE`, `PRODUCT`, `FALLBACK`. - `rule` (object, obrigatório) — Regra curada que produziu a alternativa, com versão, vigência e escopo. - `id` (string, obrigatório) — Identificador da regra. Restrições: UUID. - `version` (integer, obrigatório) — Versão da regra. Junto com `rule.id`, identifica exatamente o que foi aplicado. - `effectiveFrom` (string, obrigatório) — Início da vigência da regra (inclusivo). Restrições: data AAAA-MM-DD. - `effectiveTo` (string, obrigatório, pode ser null) — Fim da vigência da regra (exclusivo). `null` = sem data de término. Restrições: data AAAA-MM-DD. - `ncm` (string, obrigatório, pode ser null) — Escopo de NCM da regra: família de 4 dígitos, NCM completo de 8, ou `null` quando a regra não depende de NCM. - `gtin` (string, obrigatório, pode ser null) — GTIN (14 dígitos) quando a regra é exceção para um produto específico; senão `null`. - `sector` (string, obrigatório, pode ser null) — Setor da regra. `null` = regra genérica, vale para qualquer setor. Valores: `VAREJO_GERAL`, `BAR_RESTAURANTE`, `PRODUTOR_RURAL`, `GOVERNO`, `ATACADO`, `ZONA_FRANCA`. - `cst` (string, obrigatório) — CST a informar no documento fiscal. É o mesmo para CBS e IBS. - `cClassTrib` (string, obrigatório) — Código de classificação tributária a informar no documento fiscal. É o mesmo para CBS e IBS. - `applicability` (string, obrigatório, pode ser null) — Condição em que a alternativa se aplica, em texto. `null` quando não há condição. Quem confirma se a condição vale para a operação é o emissor. - `observation` (string, obrigatório, pode ser null) — Observação da curadoria fiscal, em texto, ou `null`. - `legalBasis` (string, obrigatório, pode ser null) — Fundamento legal da alternativa: o da regra, quando a curadoria cadastrou um próprio; senão o do cClassTrib na fonte oficial (ex.: `LC 214/2025, Art. 135`). `null` quando nenhum dos dois existe. - `taxClassification` (object, obrigatório, pode ser null) — Linha da tabela oficial de cClassTrib usada no cálculo. `null` quando não há linha vigente para o código (o cálculo fica `UNAVAILABLE`). - `id` (string, obrigatório) — Identificador da linha na tabela de cClassTrib. Restrições: UUID. - `sourceVersion` (string, obrigatório) — Versão da fonte de onde a linha foi carregada. - `effectiveFrom` (string, obrigatório) — Início da vigência da linha (inclusivo). Restrições: data AAAA-MM-DD. - `effectiveTo` (string, obrigatório, pode ser null) — Fim da vigência da linha (exclusivo). `null` = sem data de término. Restrições: data AAAA-MM-DD. - `cst` (string, obrigatório) — CST do código na tabela oficial. Se divergir do CST da regra, o cálculo fica `UNAVAILABLE` com `CST_MISMATCH`. - `cClassTrib` (string, obrigatório) — Código cClassTrib da linha. - `reductionPctIbs` (string, obrigatório) — Redução do IBS (vale para `IBS_UF` e `IBS_MUN`), fração decimal em string, com 6 casas: `0.600000` = 60%. - `reductionPctCbs` (string, obrigatório) — Redução da CBS, fração decimal em string, com 6 casas: `0.600000` = 60%. - `gTribRegular` (boolean, obrigatório) — Indicador `gTribRegular` do código, como publicado na tabela oficial de cClassTrib. - `isApplicable` (boolean, obrigatório) — Indicador de aplicabilidade do código, como publicado na tabela oficial de cClassTrib. - `calculationMode` (string, obrigatório) — Como o código é calculado: `STANDARD` (alíquota × (1 − redução)), `NOT_DUE` (sem tributo devido) ou `UNSUPPORTED` (mecânica que o motor ainda não calcula, como diferimento e monofasia). Valores: `STANDARD`, `NOT_DUE`, `UNSUPPORTED`. - `legalBasis` (string, obrigatório, pode ser null) — Fundamento legal do código na fonte oficial. O que vale para a alternativa é o `legalBasis` dela. - `rates` (array, obrigatório) — Linhas da tabela de alíquotas vigentes na data de referência, uma por componente. - `id` (string, obrigatório) — Identificador da linha na tabela de alíquotas. Restrições: UUID. - `sourceVersion` (string, obrigatório) — Versão da fonte de onde a alíquota foi carregada. - `effectiveFrom` (string, obrigatório) — Início da vigência da alíquota (inclusivo). Restrições: data AAAA-MM-DD. - `effectiveTo` (string, obrigatório, pode ser null) — Fim da vigência da alíquota (exclusivo). `null` = sem data de término. Restrições: data AAAA-MM-DD. - `component` (string, obrigatório) — Componente a que a alíquota se refere. Valores: `CBS`, `IBS_UF`, `IBS_MUN`. - `rate` (string, obrigatório) — Alíquota padrão do componente, fração decimal em string, com 6 casas: `0.009000` = 0,9%. - `components` (array, obrigatório, pode ser null) — Resultado por componente (`CBS`, `IBS_UF`, `IBS_MUN`). `null` quando o cálculo está indisponível (`calculation.status = UNAVAILABLE`). Ver [Componentes e alíquotas](https://kind-coast-062131010.2.azurestaticapps.net/guias/componentes-e-aliquotas.md). - Uma das formas abaixo (`oneOf`): - **status = STANDARD** - `component` (string, obrigatório) — Componente: `CBS`, `IBS_UF` ou `IBS_MUN`. Trate a lista como aberta: novos componentes podem surgir. Valores: `CBS`, `IBS_UF`, `IBS_MUN`. - `cst` (string, obrigatório) — CST do componente. Igual ao da alternativa. - `cClassTrib` (string, obrigatório) — cClassTrib do componente. Igual ao da alternativa. - `status` (string, obrigatório) — `STANDARD`: tributo devido, com alíquota padrão, redução e alíquota efetiva. `NOT_DUE`: sem tributo devido; não traz números. Valores: `STANDARD`. - `standardRate` (string, obrigatório) — Alíquota padrão do componente na data de referência, fração decimal em string, com 6 casas. - `reductionPct` (string, obrigatório) — Redução aplicada ao componente, fração decimal em string, com 6 casas. - `effectiveRate` (string, obrigatório) — Alíquota efetiva: `standardRate × (1 − reductionPct)`, fração decimal em string, com 6 casas. - **status = NOT_DUE** - `component` (string, obrigatório) — Componente: `CBS`, `IBS_UF` ou `IBS_MUN`. Trate a lista como aberta: novos componentes podem surgir. Valores: `CBS`, `IBS_UF`, `IBS_MUN`. - `cst` (string, obrigatório) — CST do componente. Igual ao da alternativa. - `cClassTrib` (string, obrigatório) — cClassTrib do componente. Igual ao da alternativa. - `status` (string, obrigatório) — `STANDARD`: tributo devido, com alíquota padrão, redução e alíquota efetiva. `NOT_DUE`: sem tributo devido; não traz números. Valores: `NOT_DUE`. - `calculation` (um de, obrigatório) — Estado do cálculo da alternativa. Uma alternativa sem cálculo continua na resposta, com o motivo. - Uma das formas abaixo (`oneOf`): - **status = CALCULATED** - `status` (string, obrigatório) — `CALCULATED` (componentes `STANDARD`), `NOT_DUE` (componentes `NOT_DUE`) ou `UNAVAILABLE` (`components` nulo). Valores: `CALCULATED`. - **status = NOT_DUE** - `status` (string, obrigatório) — `CALCULATED` (componentes `STANDARD`), `NOT_DUE` (componentes `NOT_DUE`) ou `UNAVAILABLE` (`components` nulo). Valores: `NOT_DUE`. - **status = UNAVAILABLE** - `status` (string, obrigatório) — `CALCULATED` (componentes `STANDARD`), `NOT_DUE` (componentes `NOT_DUE`) ou `UNAVAILABLE` (`components` nulo). Valores: `UNAVAILABLE`. - `reason` (string, obrigatório) — Só em `UNAVAILABLE`: `TAX_CLASSIFICATION_MISSING`, `CST_MISMATCH`, `RATE_MISSING` ou `CALCULATION_UNSUPPORTED`. Valores: `TAX_CLASSIFICATION_MISSING`, `CST_MISMATCH`, `RATE_MISSING`, `CALCULATION_UNSUPPORTED`. Exemplo: ```json { "decisionVersion": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d", "status": "CLASSIFIED", "reason": null, "gtin": "07891000315507", "cfop": "5102", "sector": null, "referenceDate": "2026-10-20", "product": { "id": "5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9", "gtinAsProvided": "7891000315507", "description": "ARROZ BRANCO TIPO 1 5KG", "brand": "MARCA EXEMPLO", "ncm": "10063021", "ncmSource": "GS1", "cest": null, "gpcCode": null, "imageUrl": null, "sourceKind": "BULK" }, "classifications": [ { "stage": "PRODUCT", "rule": { "id": "3f6b2c1e-8a4d-4f2b-9c7e-1d2a3b4c5d6e", "version": 1, "effectiveFrom": "2026-01-01", "effectiveTo": null, "ncm": "1006", "gtin": null, "sector": null }, "cst": "200", "cClassTrib": "200034", "applicability": "Venda para alimentação humana.", "observation": null, "legalBasis": "LC 214/2025, Art. 135", "taxClassification": { "id": "6f7a8b9c-0d1e-4f2a-b3c4-d5e6f7a8b9c0", "sourceVersion": "CCLASSTRIB-2026", "effectiveFrom": "2026-01-01", "effectiveTo": null, "cst": "200", "cClassTrib": "200034", "reductionPctIbs": "0.600000", "reductionPctCbs": "0.600000", "gTribRegular": false, "isApplicable": true, "calculationMode": "STANDARD", "legalBasis": "LC 214/2025, Art. 135" }, "rates": [ { "id": "0b1c2d3e-4f50-4a61-8b72-c3d4e5f60718", "sourceVersion": "ALIQUOTAS-2026", "effectiveFrom": "2026-01-01", "effectiveTo": null, "component": "CBS", "rate": "0.009000" }, { "id": "1c2d3e4f-5061-4b72-9c83-d4e5f6071829", "sourceVersion": "ALIQUOTAS-2026", "effectiveFrom": "2026-01-01", "effectiveTo": null, "component": "IBS_UF", "rate": "0.001000" }, { "id": "2d3e4f50-6172-4c83-ad94-e5f60718293a", "sourceVersion": "ALIQUOTAS-2026", "effectiveFrom": "2026-01-01", "effectiveTo": null, "component": "IBS_MUN", "rate": "0.000000" } ], "components": [ { "component": "CBS", "cst": "200", "cClassTrib": "200034", "status": "STANDARD", "standardRate": "0.009000", "reductionPct": "0.600000", "effectiveRate": "0.003600" }, { "component": "IBS_UF", "cst": "200", "cClassTrib": "200034", "status": "STANDARD", "standardRate": "0.001000", "reductionPct": "0.600000", "effectiveRate": "0.000400" }, { "component": "IBS_MUN", "cst": "200", "cClassTrib": "200034", "status": "STANDARD", "standardRate": "0.000000", "reductionPct": "0.600000", "effectiveRate": "0.000000" } ], "calculation": { "status": "CALCULATED" } } ] } ``` ### 400 · Corpo inválido: JSON malformado, campo obrigatório ausente, GTIN fora do formato ou com dígito verificador errado, CFOP sem 4 dígitos, setor desconhecido, data inválida ou campo não previsto. Não consome franquia. Campos: - `error` (string, obrigatório) — Código do erro, sem mensagem detalhada. Ver [Erros e novas tentativas](https://kind-coast-062131010.2.azurestaticapps.net/guias/erros.md). Valores: `INVALID_REQUEST`. Exemplo: ```json { "error": "INVALID_REQUEST" } ``` ### 401 · Chave ausente, malformada, inexistente, revogada ou de cliente desativado. Não consome franquia. Campos: - `error` (string, obrigatório) — Código do erro, sem mensagem detalhada. Ver [Erros e novas tentativas](https://kind-coast-062131010.2.azurestaticapps.net/guias/erros.md). Valores: `INVALID_API_KEY`. Exemplo: ```json { "error": "INVALID_API_KEY" } ``` ### 429 · Franquia mensal esgotada. As consultas voltam a ser aceitas na virada do mês (horário de Brasília). Campos: - `error` (string, obrigatório) — Código do erro, sem mensagem detalhada. Ver [Erros e novas tentativas](https://kind-coast-062131010.2.azurestaticapps.net/guias/erros.md). Valores: `QUOTA_EXCEEDED`. Exemplo: ```json { "error": "QUOTA_EXCEEDED" } ``` ### 500 · Erro inesperado. Repita com backoff exponencial. Campos: - `error` (string, obrigatório) — Código do erro, sem mensagem detalhada. Ver [Erros e novas tentativas](https://kind-coast-062131010.2.azurestaticapps.net/guias/erros.md). Valores: `INTERNAL_ERROR`. Exemplo: ```json { "error": "INTERNAL_ERROR" } ``` ### 503 · Serviço temporariamente indisponível. Se a falha ocorreu depois da admissão, a unidade da franquia já foi consumida. Repita com backoff exponencial. Campos: - `error` (string, obrigatório) — Código do erro, sem mensagem detalhada. Ver [Erros e novas tentativas](https://kind-coast-062131010.2.azurestaticapps.net/guias/erros.md). Valores: `SERVICE_UNAVAILABLE`. Exemplo: ```json { "error": "SERVICE_UNAVAILABLE" } ``` --- # Consultar em lote Classifica até 100 itens numa requisição, com admissão e resultado item a item. Versão HTML: https://kind-coast-062131010.2.azurestaticapps.net/referencia/resolve-classification-batch/ `POST /v1/classifications/batch` Base URL: `https://app-web-hmg-01-api-gettax-hmg-dvawffg9g9cpcef3.brazilsouth-01.azurewebsites.net` (homologação). Autenticação: header `Authorization: Bearer `. [Como obter a chave](https://kind-coast-062131010.2.azurestaticapps.net/guias/autenticacao.md) Classifica até 100 itens numa requisição, um por um, na ordem enviada, e responde tudo na mesma resposta. Feito para carga e revisão de catálogo. Cada item tem os mesmos campos e regras da [consulta unitária](https://kind-coast-062131010.2.azurestaticapps.net/referencia/resolve-classification.md), e cada `result` tem o mesmo formato da resposta dela. ### Admissão item a item - Um item inválido (GTIN com dígito verificador errado, setor desconhecido, campo não previsto) volta como `REJECTED` com `INVALID_REQUEST`, sem consumir franquia e sem derrubar os demais. - O lote inteiro só é recusado (HTTP 400) quando o envelope é inválido: `items` vazio ou com mais de 100 itens, campo além de `items`, ou item sem `gtin` e `cfop` em texto. - `index` aponta a posição do item no array enviado. Use-o para casar cada resultado com o seu item. ### Franquia - Cada item admitido consome uma unidade, GTIN repetido inclusive. No exemplo abaixo, o lote consome 2 unidades: o item de índice 1 foi recusado. - Se a franquia acabar no meio do lote, os itens já admitidos são mantidos e resolvidos; deste ponto em diante, todos voltam como `REJECTED` com `QUOTA_EXCEEDED`. O mesmo vale para `INVALID_API_KEY` e `SERVICE_UNAVAILABLE` na admissão: o item em que o erro ocorreu e todos os seguintes recebem esse erro. - Uma falha ao resolver um item já admitido afeta só aquele item (`SERVICE_UNAVAILABLE`); a unidade dele já foi consumida. ### O lote não busca na GS1 GTIN fora do catálogo volta `PENDING` com `LOCAL_PRODUCT_MISSING` e entra na fila de busca; consulte de novo mais tarde. Para tentar a GS1 na hora, use a consulta unitária. No lote não há `NOT_FOUND` por GTIN desconhecido. ### O que reenviar Reenvie só os itens `REJECTED` com `SERVICE_UNAVAILABLE` (com backoff) ou com `QUOTA_EXCEEDED` (depois da virada do mês). Itens `RESOLVED` já foram cobrados: reenviá-los consome de novo. Itens com `INVALID_REQUEST` precisam ser corrigidos antes. > [!NOTE] > Os valores fiscais dos exemplos são ilustrativos. ## Requisição Corpo JSON (`Content-Type: application/json`). - `items` (array, obrigatório) — Itens a classificar, de 1 a 100. Cada item é validado sozinho. Restrições: mínimo de 1 item · máximo de 100 itens. - `gtin` (string, obrigatório) — Código de barras do produto, com as mesmas regras da consulta unitária. Precisa ser texto: item sem `gtin` em texto invalida o lote inteiro (400). - `cfop` (string, obrigatório) — CFOP da operação, com 4 dígitos. Precisa ser texto: item sem `cfop` em texto invalida o lote inteiro (400). - `sector` (string, opcional) — Setor do cliente final, opcional. Valor fora da lista recusa só este item, com `INVALID_REQUEST`. - `referenceDate` (string, opcional) — Data (`AAAA-MM-DD`) para regras e alíquotas vigentes, opcional. Padrão: hoje, no fuso de São Paulo. ## Exemplo `$GETTAX_URL` é a base URL acima e `$GETTAX_KEY` a sua chave de API. ```shell curl -sS -X POST "$GETTAX_URL/v1/classifications/batch" \ -H "Authorization: Bearer $GETTAX_KEY" \ -H "Content-Type: application/json" \ -d '{ "items": [ { "gtin": "7891000315507", "cfop": "5102" }, { "gtin": "7891000315508", "cfop": "5102" }, { "gtin": "7891000315521", "cfop": "5102", "sector": "VAREJO_GERAL" } ] }' ``` ## Respostas ### 200 · Lote processado, inclusive quando há itens recusados. O lote não responde 429: franquia esgotada aparece por item. Campos: - `results` (array, obrigatório) — Uma entrada por item enviado, na mesma ordem. - Uma das formas abaixo (`oneOf`): - **outcome = RESOLVED** - `outcome` (string, obrigatório) — `RESOLVED`: o item foi admitido e traz `result`. `REJECTED`: o item foi recusado e traz `error`. Valores: `RESOLVED`. - `index` (integer, obrigatório) — Posição do item no array enviado, começando em 0. Restrições: mínimo 0. - `result` (object, obrigatório) — Resposta do item, no mesmo formato da [consulta unitária](https://kind-coast-062131010.2.azurestaticapps.net/referencia/resolve-classification.md). - `decisionVersion` (string, obrigatório) — Identificador da decisão, gravada em trilha de auditoria imutável. Cada consulta gera um novo, mesmo com a mesma entrada. Guarde junto do documento fiscal e informe ao reportar um problema. Restrições: UUID. - `status` (string, obrigatório) — Resultado da consulta: `CLASSIFIED`, `PENDING`, `IN_REVIEW` ou `NOT_FOUND`. Ver [Status e alternativas](https://kind-coast-062131010.2.azurestaticapps.net/guias/status-e-alternativas.md). Valores: `CLASSIFIED`, `PENDING`, `IN_REVIEW`, `NOT_FOUND`. - `retryAfterSeconds` (integer, opcional) — Só em `PENDING`, quando a busca do produto foi adiada pelo limite diário de consultas do GetTax à GS1: segundos até esse limite reiniciar. Não consulte o mesmo GTIN antes disso. Ausente nos demais casos. Restrições: mínimo 0. - `reason` (string, obrigatório, pode ser null) — Motivo do status: `LOCAL_PRODUCT_MISSING` (produto fora do catálogo), `MISSING_NCM`, `MISSING_RULE` ou `INCOMPLETE_CLASSIFICATION`. `null` em `CLASSIFIED` e `NOT_FOUND`. Valores: `LOCAL_PRODUCT_MISSING`, `MISSING_NCM`, `MISSING_RULE`, `INCOMPLETE_CLASSIFICATION`. - `gtin` (string, obrigatório) — GTIN normalizado com 14 dígitos (zeros à esquerda). - `cfop` (string, obrigatório) — CFOP consultado. - `sector` (string, obrigatório, pode ser null) — Setor enviado; `null` quando a consulta não informou setor. Valores: `VAREJO_GERAL`, `BAR_RESTAURANTE`, `PRODUTOR_RURAL`, `GOVERNO`, `ATACADO`, `ZONA_FRANCA`. - `referenceDate` (string, obrigatório) — Data de referência efetivamente usada: a enviada ou a data de hoje em São Paulo. Restrições: data AAAA-MM-DD. - `product` (object, obrigatório, pode ser null) — Produto no catálogo do GetTax. `null` quando o GTIN não está no catálogo (`PENDING` e `NOT_FOUND`). - `id` (string, obrigatório) — Identificador interno do produto. Restrições: UUID. - `gtinAsProvided` (string, obrigatório, pode ser null) — GTIN na forma em que entrou no catálogo, antes da normalização para 14 dígitos. - `description` (string, obrigatório, pode ser null) — Descrição do produto, quando a origem informa. - `brand` (string, obrigatório, pode ser null) — Marca, quando a origem informa. - `ncm` (string, obrigatório, pode ser null) — NCM de 8 dígitos, sem pontuação. `null` quando a origem não informou. Sem NCM, só se aplicam regras que não dependem dele (por operação ou exceção por GTIN). - `ncmSource` (string, obrigatório, pode ser null) — Origem do NCM (hoje, `GS1`). `null` quando não há NCM. - `cest` (string, obrigatório, pode ser null) — CEST, quando a origem informa. - `gpcCode` (string, obrigatório, pode ser null) — Código de categoria GPC da GS1, quando informado. - `imageUrl` (string, obrigatório, pode ser null) — URL de imagem do produto, quando informada. - `sourceKind` (string, obrigatório) — Como o produto entrou no catálogo: `BULK` (carga de arquivo da GS1) ou `PROVIDER` (busca individual na GS1). - `classifications` (array, obrigatório) — Alternativas de enquadramento. Vazio quando não há alternativa. A ordem é técnica e estável, não recomendação: não escolha a primeira automaticamente. - `stage` (string, obrigatório) — Etapa do motor que produziu a alternativa: `OPERATION`, `COHERENCE`, `PRODUCT` ou `FALLBACK`. Ver [Etapas do motor](https://kind-coast-062131010.2.azurestaticapps.net/guias/status-e-alternativas.md#etapas-do-motor). Valores: `OPERATION`, `COHERENCE`, `PRODUCT`, `FALLBACK`. - `rule` (object, obrigatório) — Regra curada que produziu a alternativa, com versão, vigência e escopo. - `id` (string, obrigatório) — Identificador da regra. Restrições: UUID. - `version` (integer, obrigatório) — Versão da regra. Junto com `rule.id`, identifica exatamente o que foi aplicado. - `effectiveFrom` (string, obrigatório) — Início da vigência da regra (inclusivo). Restrições: data AAAA-MM-DD. - `effectiveTo` (string, obrigatório, pode ser null) — Fim da vigência da regra (exclusivo). `null` = sem data de término. Restrições: data AAAA-MM-DD. - `ncm` (string, obrigatório, pode ser null) — Escopo de NCM da regra: família de 4 dígitos, NCM completo de 8, ou `null` quando a regra não depende de NCM. - `gtin` (string, obrigatório, pode ser null) — GTIN (14 dígitos) quando a regra é exceção para um produto específico; senão `null`. - `sector` (string, obrigatório, pode ser null) — Setor da regra. `null` = regra genérica, vale para qualquer setor. Valores: `VAREJO_GERAL`, `BAR_RESTAURANTE`, `PRODUTOR_RURAL`, `GOVERNO`, `ATACADO`, `ZONA_FRANCA`. - `cst` (string, obrigatório) — CST a informar no documento fiscal. É o mesmo para CBS e IBS. - `cClassTrib` (string, obrigatório) — Código de classificação tributária a informar no documento fiscal. É o mesmo para CBS e IBS. - `applicability` (string, obrigatório, pode ser null) — Condição em que a alternativa se aplica, em texto. `null` quando não há condição. Quem confirma se a condição vale para a operação é o emissor. - `observation` (string, obrigatório, pode ser null) — Observação da curadoria fiscal, em texto, ou `null`. - `legalBasis` (string, obrigatório, pode ser null) — Fundamento legal da alternativa: o da regra, quando a curadoria cadastrou um próprio; senão o do cClassTrib na fonte oficial (ex.: `LC 214/2025, Art. 135`). `null` quando nenhum dos dois existe. - `taxClassification` (object, obrigatório, pode ser null) — Linha da tabela oficial de cClassTrib usada no cálculo. `null` quando não há linha vigente para o código (o cálculo fica `UNAVAILABLE`). - `id` (string, obrigatório) — Identificador da linha na tabela de cClassTrib. Restrições: UUID. - `sourceVersion` (string, obrigatório) — Versão da fonte de onde a linha foi carregada. - `effectiveFrom` (string, obrigatório) — Início da vigência da linha (inclusivo). Restrições: data AAAA-MM-DD. - `effectiveTo` (string, obrigatório, pode ser null) — Fim da vigência da linha (exclusivo). `null` = sem data de término. Restrições: data AAAA-MM-DD. - `cst` (string, obrigatório) — CST do código na tabela oficial. Se divergir do CST da regra, o cálculo fica `UNAVAILABLE` com `CST_MISMATCH`. - `cClassTrib` (string, obrigatório) — Código cClassTrib da linha. - `reductionPctIbs` (string, obrigatório) — Redução do IBS (vale para `IBS_UF` e `IBS_MUN`), fração decimal em string, com 6 casas: `0.600000` = 60%. - `reductionPctCbs` (string, obrigatório) — Redução da CBS, fração decimal em string, com 6 casas: `0.600000` = 60%. - `gTribRegular` (boolean, obrigatório) — Indicador `gTribRegular` do código, como publicado na tabela oficial de cClassTrib. - `isApplicable` (boolean, obrigatório) — Indicador de aplicabilidade do código, como publicado na tabela oficial de cClassTrib. - `calculationMode` (string, obrigatório) — Como o código é calculado: `STANDARD` (alíquota × (1 − redução)), `NOT_DUE` (sem tributo devido) ou `UNSUPPORTED` (mecânica que o motor ainda não calcula, como diferimento e monofasia). Valores: `STANDARD`, `NOT_DUE`, `UNSUPPORTED`. - `legalBasis` (string, obrigatório, pode ser null) — Fundamento legal do código na fonte oficial. O que vale para a alternativa é o `legalBasis` dela. - `rates` (array, obrigatório) — Linhas da tabela de alíquotas vigentes na data de referência, uma por componente. - `id` (string, obrigatório) — Identificador da linha na tabela de alíquotas. Restrições: UUID. - `sourceVersion` (string, obrigatório) — Versão da fonte de onde a alíquota foi carregada. - `effectiveFrom` (string, obrigatório) — Início da vigência da alíquota (inclusivo). Restrições: data AAAA-MM-DD. - `effectiveTo` (string, obrigatório, pode ser null) — Fim da vigência da alíquota (exclusivo). `null` = sem data de término. Restrições: data AAAA-MM-DD. - `component` (string, obrigatório) — Componente a que a alíquota se refere. Valores: `CBS`, `IBS_UF`, `IBS_MUN`. - `rate` (string, obrigatório) — Alíquota padrão do componente, fração decimal em string, com 6 casas: `0.009000` = 0,9%. - `components` (array, obrigatório, pode ser null) — Resultado por componente (`CBS`, `IBS_UF`, `IBS_MUN`). `null` quando o cálculo está indisponível (`calculation.status = UNAVAILABLE`). Ver [Componentes e alíquotas](https://kind-coast-062131010.2.azurestaticapps.net/guias/componentes-e-aliquotas.md). - Uma das formas abaixo (`oneOf`): - **status = STANDARD** - `component` (string, obrigatório) — Componente: `CBS`, `IBS_UF` ou `IBS_MUN`. Trate a lista como aberta: novos componentes podem surgir. Valores: `CBS`, `IBS_UF`, `IBS_MUN`. - `cst` (string, obrigatório) — CST do componente. Igual ao da alternativa. - `cClassTrib` (string, obrigatório) — cClassTrib do componente. Igual ao da alternativa. - `status` (string, obrigatório) — `STANDARD`: tributo devido, com alíquota padrão, redução e alíquota efetiva. `NOT_DUE`: sem tributo devido; não traz números. Valores: `STANDARD`. - `standardRate` (string, obrigatório) — Alíquota padrão do componente na data de referência, fração decimal em string, com 6 casas. - `reductionPct` (string, obrigatório) — Redução aplicada ao componente, fração decimal em string, com 6 casas. - `effectiveRate` (string, obrigatório) — Alíquota efetiva: `standardRate × (1 − reductionPct)`, fração decimal em string, com 6 casas. - **status = NOT_DUE** - `component` (string, obrigatório) — Componente: `CBS`, `IBS_UF` ou `IBS_MUN`. Trate a lista como aberta: novos componentes podem surgir. Valores: `CBS`, `IBS_UF`, `IBS_MUN`. - `cst` (string, obrigatório) — CST do componente. Igual ao da alternativa. - `cClassTrib` (string, obrigatório) — cClassTrib do componente. Igual ao da alternativa. - `status` (string, obrigatório) — `STANDARD`: tributo devido, com alíquota padrão, redução e alíquota efetiva. `NOT_DUE`: sem tributo devido; não traz números. Valores: `NOT_DUE`. - `calculation` (um de, obrigatório) — Estado do cálculo da alternativa. Uma alternativa sem cálculo continua na resposta, com o motivo. - Uma das formas abaixo (`oneOf`): - **status = CALCULATED** - `status` (string, obrigatório) — `CALCULATED` (componentes `STANDARD`), `NOT_DUE` (componentes `NOT_DUE`) ou `UNAVAILABLE` (`components` nulo). Valores: `CALCULATED`. - **status = NOT_DUE** - `status` (string, obrigatório) — `CALCULATED` (componentes `STANDARD`), `NOT_DUE` (componentes `NOT_DUE`) ou `UNAVAILABLE` (`components` nulo). Valores: `NOT_DUE`. - **status = UNAVAILABLE** - `status` (string, obrigatório) — `CALCULATED` (componentes `STANDARD`), `NOT_DUE` (componentes `NOT_DUE`) ou `UNAVAILABLE` (`components` nulo). Valores: `UNAVAILABLE`. - `reason` (string, obrigatório) — Só em `UNAVAILABLE`: `TAX_CLASSIFICATION_MISSING`, `CST_MISMATCH`, `RATE_MISSING` ou `CALCULATION_UNSUPPORTED`. Valores: `TAX_CLASSIFICATION_MISSING`, `CST_MISMATCH`, `RATE_MISSING`, `CALCULATION_UNSUPPORTED`. - **outcome = REJECTED** - `outcome` (string, obrigatório) — `RESOLVED`: o item foi admitido e traz `result`. `REJECTED`: o item foi recusado e traz `error`. Valores: `REJECTED`. - `index` (integer, obrigatório) — Posição do item no array enviado, começando em 0. Restrições: mínimo 0. - `error` (string, obrigatório) — Por que o item foi recusado: `INVALID_REQUEST` (item inválido; não consome), `QUOTA_EXCEEDED` (franquia esgotada), `INVALID_API_KEY` (chave deixou de valer) ou `SERVICE_UNAVAILABLE` (falha temporária). Valores: `INVALID_REQUEST`, `QUOTA_EXCEEDED`, `INVALID_API_KEY`, `SERVICE_UNAVAILABLE`. Exemplo: ```json { "results": [ { "outcome": "RESOLVED", "index": 0, "result": { "decisionVersion": "4c5d6e7f-8091-4a2b-9c3d-4e5f60718293", "status": "CLASSIFIED", "reason": null, "gtin": "07891000315507", "cfop": "5102", "sector": null, "referenceDate": "2026-10-20", "product": { "id": "5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9", "gtinAsProvided": "7891000315507", "description": "ARROZ BRANCO TIPO 1 5KG", "brand": "MARCA EXEMPLO", "ncm": "10063021", "ncmSource": "GS1", "cest": null, "gpcCode": null, "imageUrl": null, "sourceKind": "BULK" }, "classifications": [ { "stage": "PRODUCT", "rule": { "id": "3f6b2c1e-8a4d-4f2b-9c7e-1d2a3b4c5d6e", "version": 1, "effectiveFrom": "2026-01-01", "effectiveTo": null, "ncm": "1006", "gtin": null, "sector": null }, "cst": "200", "cClassTrib": "200034", "applicability": "Venda para alimentação humana.", "observation": null, "legalBasis": "LC 214/2025, Art. 135", "taxClassification": { "id": "6f7a8b9c-0d1e-4f2a-b3c4-d5e6f7a8b9c0", "sourceVersion": "CCLASSTRIB-2026", "effectiveFrom": "2026-01-01", "effectiveTo": null, "cst": "200", "cClassTrib": "200034", "reductionPctIbs": "0.600000", "reductionPctCbs": "0.600000", "gTribRegular": false, "isApplicable": true, "calculationMode": "STANDARD", "legalBasis": "LC 214/2025, Art. 135" }, "rates": [ { "id": "0b1c2d3e-4f50-4a61-8b72-c3d4e5f60718", "sourceVersion": "ALIQUOTAS-2026", "effectiveFrom": "2026-01-01", "effectiveTo": null, "component": "CBS", "rate": "0.009000" }, { "id": "1c2d3e4f-5061-4b72-9c83-d4e5f6071829", "sourceVersion": "ALIQUOTAS-2026", "effectiveFrom": "2026-01-01", "effectiveTo": null, "component": "IBS_UF", "rate": "0.001000" }, { "id": "2d3e4f50-6172-4c83-ad94-e5f60718293a", "sourceVersion": "ALIQUOTAS-2026", "effectiveFrom": "2026-01-01", "effectiveTo": null, "component": "IBS_MUN", "rate": "0.000000" } ], "components": [ { "component": "CBS", "cst": "200", "cClassTrib": "200034", "status": "STANDARD", "standardRate": "0.009000", "reductionPct": "0.600000", "effectiveRate": "0.003600" }, { "component": "IBS_UF", "cst": "200", "cClassTrib": "200034", "status": "STANDARD", "standardRate": "0.001000", "reductionPct": "0.600000", "effectiveRate": "0.000400" }, { "component": "IBS_MUN", "cst": "200", "cClassTrib": "200034", "status": "STANDARD", "standardRate": "0.000000", "reductionPct": "0.600000", "effectiveRate": "0.000000" } ], "calculation": { "status": "CALCULATED" } } ] } }, { "outcome": "REJECTED", "index": 1, "error": "INVALID_REQUEST" }, { "outcome": "RESOLVED", "index": 2, "result": { "decisionVersion": "7b8c9d0e-1f2a-4b3c-8d4e-5f6a7b8c9d0e", "status": "PENDING", "reason": "LOCAL_PRODUCT_MISSING", "gtin": "07891000315521", "cfop": "5102", "sector": "VAREJO_GERAL", "referenceDate": "2026-10-20", "product": null, "classifications": [] } } ] } ``` ### 400 · Envelope inválido: lote vazio, mais de 100 itens, campo além de `items`, item que não é objeto ou item sem `gtin`/`cfop` em texto. Nenhum item é processado nem consumido. Campos: - `error` (string, obrigatório) — Código do erro, sem mensagem detalhada. Ver [Erros e novas tentativas](https://kind-coast-062131010.2.azurestaticapps.net/guias/erros.md). Valores: `INVALID_REQUEST`. Exemplo: ```json { "error": "INVALID_REQUEST" } ``` ### 401 · Chave ausente, malformada, inexistente, revogada ou de cliente desativado. Não consome franquia. Campos: - `error` (string, obrigatório) — Código do erro, sem mensagem detalhada. Ver [Erros e novas tentativas](https://kind-coast-062131010.2.azurestaticapps.net/guias/erros.md). Valores: `INVALID_API_KEY`. Exemplo: ```json { "error": "INVALID_API_KEY" } ``` ### 500 · Erro inesperado. Repita com backoff exponencial. Campos: - `error` (string, obrigatório) — Código do erro, sem mensagem detalhada. Ver [Erros e novas tentativas](https://kind-coast-062131010.2.azurestaticapps.net/guias/erros.md). Valores: `INTERNAL_ERROR`. Exemplo: ```json { "error": "INTERNAL_ERROR" } ``` ### 503 · Serviço temporariamente indisponível. Repita com backoff exponencial. Campos: - `error` (string, obrigatório) — Código do erro, sem mensagem detalhada. Ver [Erros e novas tentativas](https://kind-coast-062131010.2.azurestaticapps.net/guias/erros.md). Valores: `SERVICE_UNAVAILABLE`. Exemplo: ```json { "error": "SERVICE_UNAVAILABLE" } ``` --- # Listar setores Lista os códigos aceitos no campo sector; exige chave e não consome franquia. Versão HTML: https://kind-coast-062131010.2.azurestaticapps.net/referencia/list-sectors/ `GET /v1/enums/sectors` Base URL: `https://app-web-hmg-01-api-gettax-hmg-dvawffg9g9cpcef3.brazilsouth-01.azurewebsites.net` (homologação). Autenticação: header `Authorization: Bearer `. [Como obter a chave](https://kind-coast-062131010.2.azurestaticapps.net/guias/autenticacao.md) Devolve os códigos aceitos no campo `sector` da [consulta unitária](https://kind-coast-062131010.2.azurestaticapps.net/referencia/resolve-classification.md) e do [lote](https://kind-coast-062131010.2.azurestaticapps.net/referencia/resolve-classification-batch.md). O significado de cada setor e o efeito dele no resultado estão em [Dados da consulta](https://kind-coast-062131010.2.azurestaticapps.net/guias/dados-da-consulta.md#setor). Exige chave de API, como toda rota em `/v1/`, e não consome franquia. Por isso é a forma recomendada de validar uma chave nova e de checar a saúde da integração. ## Exemplo `$GETTAX_URL` é a base URL acima e `$GETTAX_KEY` a sua chave de API. ```shell curl -sS "$GETTAX_URL/v1/enums/sectors" \ -H "Authorization: Bearer $GETTAX_KEY" ``` ## Respostas ### 200 · Lista de setores. Campos: - `sectors` (array, obrigatório) — Códigos de setor aceitos hoje. A lista pode crescer: leia daqui em vez de fixá-la no código. Exemplo: ```json { "sectors": [ "VAREJO_GERAL", "BAR_RESTAURANTE", "PRODUTOR_RURAL", "GOVERNO", "ATACADO", "ZONA_FRANCA" ] } ``` ### 401 · Chave ausente, malformada, inexistente, revogada ou de cliente desativado. Campos: - `error` (string, obrigatório) — Código do erro, sem mensagem detalhada. Ver [Erros e novas tentativas](https://kind-coast-062131010.2.azurestaticapps.net/guias/erros.md). Valores: `INVALID_API_KEY`. Exemplo: ```json { "error": "INVALID_API_KEY" } ``` ### 500 · Erro inesperado. Repita com backoff exponencial. Campos: - `error` (string, obrigatório) — Código do erro, sem mensagem detalhada. Ver [Erros e novas tentativas](https://kind-coast-062131010.2.azurestaticapps.net/guias/erros.md). Valores: `INTERNAL_ERROR`. Exemplo: ```json { "error": "INTERNAL_ERROR" } ``` ### 503 · Serviço temporariamente indisponível. Repita com backoff exponencial. Campos: - `error` (string, obrigatório) — Código do erro, sem mensagem detalhada. Ver [Erros e novas tentativas](https://kind-coast-062131010.2.azurestaticapps.net/guias/erros.md). Valores: `SERVICE_UNAVAILABLE`. Exemplo: ```json { "error": "SERVICE_UNAVAILABLE" } ```