Como validar a inscrição estadual no cadastro de clientes
IE errada no cadastro do cliente só aparece na hora de faturar, como rejeição da NF-e. Dá para pegar antes, no próprio formulário.
O fluxo tem três passos: conferir o número na hora, consultar o cadastro ao salvar e gravar o resultado.
O fluxo#
| Passo | Quando | Confere | Se falhar |
|---|---|---|---|
| 1. Formato e dígito | No envio do formulário | Tamanho, prefixo e dígito verificador da UF | Bloqueia e mostra o motivo |
| 2. Consulta | Ao salvar, em segundo plano | Se a IE existe, está ativa e é do CNPJ ou CPF | Alerta e marca para revisão |
| 3. Registro | Depois da consulta | — | — |
Por que os dois primeiros passos: o dígito pega digitação, só a consulta pega situação e vínculo. Detalhes em dígito verificador ou consulta.
Passo 1: formato e dígito no formulário (Node.js ou navegador)#
Use a biblioteca aberta validador-ie (npm install validador-ie). Ela tem as regras das 27 UFs e roda sem rede:
import { validarIE } from "validador-ie";
export function checarIE(ie, uf) {
if (/^\s*isento\s*$/i.test(ie)) {
return { ok: true, isento: true }; // sem número: o fiscal decide o indIEDest
}
const r = validarIE(ie, uf);
if (!r.valida) {
return { ok: false, erro: `IE inválida para ${uf}: ${r.motivo}` };
}
return { ok: true, ie: r.formatada, zerosCompletados: r.zerosCompletados };
} - Mostre o motivo. "Dígito verificador inválido" resolve mais rápido que "IE inválida".
- Zeros à esquerda. Se
zerosCompletadosfor maior que zero, a IE veio sem os zeros (comum em planilha). Mostre a IE completada ao usuário. - Para testar sem código, use o validador de inscrição estadual.
Em Python, a mesma biblioteca: pip install validador-ie e from validador_ie import validar_ie.
Passo 2: consultar ao salvar (Python)#
Consulte pelo CNPJ do cliente, na UF dele, e procure a IE digitada na lista:
import os
import time
import requests
API = "https://api.fiscalapi.com.br/api/consultar"
CHAVE = os.environ["FISCALAPI_KEY"] # nunca no código-fonte
def so_digitos(texto: str) -> str:
return "".join(c for c in texto or "" if c.isdigit()).lstrip("0")
def conferir_ie(uf: str, cnpj: str, ie: str, tentativas: int = 3) -> tuple[str, dict | None]:
for tentativa in range(tentativas):
resp = requests.get(
API,
headers={"X-API-Key": CHAVE},
params={"uf": uf, "cnpj": cnpj},
timeout=95,
)
if resp.status_code == 429: # limite por minuto do plano
time.sleep(int(resp.headers.get("Retry-After", "60")))
continue
if resp.status_code in (502, 503, 504): # o estado não respondeu
time.sleep(30 * (tentativa + 1))
continue
resp.raise_for_status() # 400, 402, 403: repetir não resolve
dados = resp.json()
for inscricao in dados["results"]:
if so_digitos(inscricao["inscricao_estadual"]) == so_digitos(ie):
# situacao_ie: "Habilitado" ou "Não habilitado" (maiúsculas variam)
ativa = inscricao["situacao_ie"].strip().casefold() == "habilitado"
return ("ok" if ativa else "alerta", {**inscricao, "request_id": dados["request_id"]})
return ("alerta", None) # IE não encontrada para este CNPJ na UF
return ("pendente", None) # tente de novo mais tarde -
ok: IE ativa e do CNPJ. -
alerta: IE não encontrada, de outro contribuinte ou fora de situação ativa. Não fature no automático: revise com o fiscal. -
pendente: a consulta não terminou. Deixe numa fila e tente depois.
Não prenda o formulário esperando a consulta. Ela vai até o cadastro do estado, e a API encerra a chamada em 90 segundos. Salve o cliente com a IE "pendente" e consulte numa fila.
Para produtor rural, troque cnpj por cpf. A busca por CPF depende do estado: São Paulo, por exemplo, só consulta por CNPJ ou pela IE.
Passo 2 em PHP (Laravel)#
use Illuminate\Support\Facades\Http;
$resp = Http::withHeaders(['X-API-Key' => config('services.fiscalapi.key')])
->timeout(95)
->get('https://api.fiscalapi.com.br/api/consultar', ['uf' => $uf, 'cnpj' => $cnpj]);
if ($resp->status() === 429) {
// devolva para a fila: espere $resp->header('Retry-After') segundos
} elseif ($resp->successful()) {
$digitos = fn ($s) => ltrim(preg_replace('/\D/', '', $s ?? ''), '0');
$achada = collect($resp->json('results'))
->first(fn ($i) => $digitos($i['inscricao_estadual']) === $digitos($ie));
$situacao = $achada['situacao_ie'] ?? 'NAO_ENCONTRADA';
// "Habilitado" ou "Não habilitado" (maiúsculas variam)
$ativa = mb_strtolower(trim($situacao)) === 'habilitado';
} Erros e limites#
| HTTP | Significa | O que fazer |
|---|---|---|
| 400 | Parâmetro ausente, conflitante ou documento inválido | Corrigir a chamada. Não repetir |
| 402 | Saldo do plano esgotado (LIMITE_ATINGIDO) | Não repetir. Avisar quem cuida da conta |
| 403 | Chave ausente, inválida ou revogada | Conferir o header X-API-Key |
| 429 | Limite por minuto do plano: 5, 20, 60 ou 120 | Esperar o Retry-After e repetir |
| 502, 503, 504 | O estado não respondeu a tempo | Repetir depois, com espera crescente |
Detalhes em rate limiting.
O que gravar#
- IE e UF
-
situacao_ie(HabilitadoouNão habilitado) esituacao_nfe(ex.:NFe,NFCe, NFe) - Data e hora da consulta
-
request_idda resposta, para rastrear a consulta - Resultado: ok, alerta ou pendente
Reconsulte antes de faturar quando a última consulta estiver antiga. Defina o prazo com o fiscal. Para revisar a carteira inteira sem código, suba uma planilha de até 20.000 linhas na consulta de IE em massa.
Perguntas frequentes#
Se o dígito confere, ainda preciso consultar? Sim. O dígito só mostra que o número foi digitado certo. A IE pode não existir, estar suspensa ou ser de outro CNPJ.
Posso consultar pela IE em vez do CNPJ? Pode, com o parâmetro ie. Compare o campo cpf_cnpj da resposta com o documento do cliente para conferir o vínculo.
E se o cliente informar "ISENTO"? Não há número para validar. Grave sem IE e decida o indIEDest com o fiscal. Veja como preencher o indIEDest.
A chave da API pode ficar no front-end? Não. A consulta roda no seu servidor. No navegador, só a validação de formato e dígito.
Fontes#
- Documentação da consulta de IE, FiscalAPI
- Rate limiting, FiscalAPI
- validador-ie, biblioteca aberta da FiscalAPI
Artigos relacionados#
Consulte dados fiscais via API
Consulte Inscrições Estaduais, CNPJs e Certidões Negativas via API REST. Dados direto da SEFAZ e Receita Federal. Planos a partir de R$ 19,99/mês.
Criar conta →