Pular para o conteúdo
FiscalAPI
API & Integração

Como revalidar o cadastro de clientes periodicamente

Equipe FiscalAPI 5 min de leitura
PythonTutorialAPI

A IE estava ativa no dia do cadastro. Isso não diz nada sobre hoje. Para pegar a mudança antes da nota, revalide a carteira numa rotina: um job que reconsulta cada cliente, respeita o limite do plano e avisa quando a situação muda.

Com que frequência revalidar#

Não há prazo legal único para isso. Comece pelo risco de cada grupo e ajuste com o fiscal:

GrupoSugestão
Clientes que compram todo mêsMensal, e de novo antes de faturar se a última consulta passou do prazo que vocês definiram
Clientes parados há mesesNa volta, antes do primeiro pedido
Produtores ruraisAntes da safra e mensal para quem entrega com frequência
Cadastro alterado (endereço, razão social, IE)Na hora da alteração

A FiscalAPI não avisa quando uma IE muda de situação. Quem percebe a mudança é a sua rotina.

Quanto tempo o job leva#

O limite por minuto é da conta e depende do plano: 5, 20, 60 ou 120 requisições. O tempo mínimo é o número de clientes dividido pelo limite:

Limite do plano2.000 clientes10.000 clientes
20 por minuto1 h 40 min8 h 20 min
60 por minuto34 min2 h 47 min
120 por minuto17 min1 h 24 min

Antes de agendar:

  • Saldo. Cada cliente revalidado usa 1 consulta do plano. 2.000 clientes por mês são 2.000 consultas. Compare em planos e preços.
  • Limite compartilhado. O ERP que consulta na mesma conta durante o dia disputa o mesmo limite. Rode o job à noite ou deixe folga.
  • Cache. Toda requisição conta no limite, inclusive a que volta do cache (cached: true).
  • Paralelismo. O job abaixo faz uma consulta por vez. Uma consulta que vai ao estado pode levar alguns segundos, então ele não chega a 60 ou 120 por minuto sozinho. Para chegar perto da tabela, divida a carteira entre alguns trabalhadores e mantenha o ritmo total dentro do limite.

O job em Python#

Reconsulta cada cliente na UF dele, no ritmo do plano. Compara com o que está gravado e chama alertar quando muda:

python
import os
import time
from datetime import datetime, timezone

import requests

API = "https://api.fiscalapi.com.br/api/consultar"
CHAVE = os.environ["FISCALAPI_KEY"]  # nunca no código-fonte
LIMITE_POR_MINUTO = 20  # o do seu plano: 5, 20, 60 ou 120
INTERVALO = 60 / LIMITE_POR_MINUTO


class SaldoEsgotado(Exception):
    def __init__(self, restantes: list):
        super().__init__("saldo do plano esgotado")
        self.restantes = restantes  # retome por eles quando houver saldo


def so_digitos(texto: str) -> str:
    return "".join(c for c in texto or "" if c.isdigit()).lstrip("0")


def situacao_atual(dados: dict, ie: str) -> tuple[str, str]:
    for inscricao in dados["results"]:
        if so_digitos(inscricao["inscricao_estadual"]) == so_digitos(ie):
            return inscricao["situacao_ie"].strip(), inscricao["situacao_nfe"].strip()
    return "NAO_ENCONTRADA", ""  # a IE gravada não está mais neste CNPJ, nesta UF


def revalidar(clientes: list, salvar, alertar) -> list:
    """Devolve os clientes que ficaram para a próxima rodada."""
    pendentes = []
    for i, cliente in enumerate(clientes):
        inicio = time.monotonic()
        try:
            resp = requests.get(
                API,
                headers={"X-API-Key": CHAVE},
                params={"uf": cliente["uf"], "cnpj": cliente["cnpj"]},
                timeout=95,
            )
        except requests.RequestException:  # rede ou tempo esgotado
            pendentes.append(cliente)
            continue
        if resp.status_code == 429:  # passou do limite por minuto
            time.sleep(int(resp.headers.get("Retry-After", "60")))
            pendentes.append(cliente)
            continue
        if resp.status_code == 402:  # saldo do plano esgotado: repetir não resolve
            raise SaldoEsgotado(pendentes + clientes[i:])
        if resp.status_code >= 500:  # o estado ou a API não responderam
            pendentes.append(cliente)
        elif resp.ok:
            dados = resp.json()
            antes = (cliente["situacao_ie"], cliente["situacao_nfe"])
            depois = situacao_atual(dados, cliente["ie"])
            salvar(cliente["id"], *depois, dados["request_id"], datetime.now(timezone.utc))
            if depois != antes:
                alertar(cliente, antes, depois)
        else:  # 400 ou 403: corrija o cadastro ou a chave
            alertar(cliente, None, f"HTTP {resp.status_code}")
        time.sleep(max(0.0, INTERVALO - (time.monotonic() - inicio)))
    return pendentes

Como rodar:

  • Agende com o cron, o agendador do seu ERP ou uma fila. Uma rodada por mês, à noite.
  • Pendentes: rode revalidar(pendentes, ...) de novo uma hora depois. O que sobrar vai para a rodada seguinte.
  • Produtor rural: troque cnpj por cpf. São Paulo, por exemplo, não busca por CPF: lá, consulte pela IE (ie=). Veja qual IE usar quando o produtor tem várias.

Erros e limites#

HTTPNo job
429Espere o Retry-After e devolva o cliente para a fila
500 a 504, ou erro de redeO estado ou a API não responderam. Tente na próxima rodada
402Saldo esgotado. O job para e devolve quem faltou. Avise quem cuida da conta
400, 403Documento inválido ou chave errada. Corrija antes de repetir

As respostas trazem X-RateLimit-Remaining, quantas requisições restam no minuto. Detalhes em rate limiting.

O que fazer com o alerta#

Mudou paraAção sugerida
Não habilitadoBloqueie o faturamento automático e peça ao cliente que regularize
NAO_ENCONTRADAA IE gravada não aparece mais para o CNPJ. Confirme a IE com o cliente
situacao_nfe diferenteMudou a lista de documentos eletrônicos habilitados (por exemplo, saiu NFe). Revise antes da próxima nota
Voltou a HabilitadoLibere, com a data e o request_id da consulta

O que cada situação significa está em situação cadastral da inscrição estadual.

Sem código: a planilha#

Para revisar a carteira sem programar, suba uma planilha de até 20.000 CPFs, CNPJs ou IEs na consulta de IE em massa e baixe o resultado com a situação de cada um. Linha com erro não é cobrada.


Perguntas frequentes#

A API tem rota de lote? Não. Pela API é uma chamada por documento, dentro do limite por minuto. Para lote sem código, use a planilha do painel.

Consulta que falha é cobrada? Não. Falha da FiscalAPI ou da fonte oficial não é cobrada.

Por que consultar pelo CNPJ e não pela IE? Pelo CNPJ, a resposta mostra se a IE gravada ainda pertence ao cliente. Pela IE, compare o campo cpf_cnpj da resposta com o documento do cliente.

Uso ERP com vários clientes. O limite é por cliente? O limite e o saldo são da conta. Numa conta só, os clientes do ERP somam. Com a chave de cada cliente, cada um tem o próprio plano. Veja ERPs e hubs de marketplace.


Fontes#

Artigos relacionados#

Compartilhar: WhatsApp LinkedIn Twitter

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 →