Pular para o conteúdo principal
Abrir no ChatGPTAbrir no Claude

Primeira chamada em 5 minutos

Consulte a alíquota interna de ICMS do NCM 85414121 (iluminação LED) em SP, na competência 2026-10, pelo sandbox. Nada do que você enviar lá chega à produção.

5 minutosEscopo consultas:lerAmbiente: sandbox

Antes de começar​

  • Uma chave de sandbox rmf_test_ com o escopo consultas:ler. A equipe da RMF emite a chave: peça pelo seu contato comercial (veja Como conseguir a chave).
  • A chave e o endereço numa variável de ambiente. Nenhum exemplo desta página leva a chave no código, e todos leem RMF_API_URL e RMF_API_KEY:
export RMF_API_URL="https://sandbox.api.rmfestrategia.com/v1"
export RMF_API_KEY="<sua chave do sandbox, 75 caracteres>"
A chave é segredo

Ela vai no cabeçalho Authorization: Bearer, nunca na URL, no código, em log ou em mensagem de commit. Chave rmf_test_ só vale no sandbox; rmf_live_, só na produção.

1. Faça a chamada​

Um GET /v1/icms/aliquotas com o NCM, a UF e a competência em inicio e fim. Os exemplos tratam o 429: esperam o Retry-After e tentam de novo, até 5 vezes.

consulta.sh
#!/bin/sh
# Consulta a alíquota de ICMS de um NCM e trata o 429 (espera o Retry-After).
# Precisa de RMF_API_URL (comece pelo sandbox) e RMF_API_KEY no ambiente. Requer curl e jq.
set -eu
: "${RMF_API_URL:?defina RMF_API_URL (sandbox: https://sandbox.api.rmfestrategia.com/v1)}"
: "${RMF_API_KEY:?defina RMF_API_KEY (chave rmf_test_ no sandbox)}"

tmp=$(mktemp -d)
trap 'rm -rf "$tmp"' EXIT

for tentativa in 1 2 3 4 5; do
# RMF_SIMULAR_429=1 pede ao sandbox um 429 na primeira tentativa (X-Sandbox-Simular: limite), para ver a espera funcionar
simular=""; [ "$tentativa" = 1 ] && [ "${RMF_SIMULAR_429:-}" = 1 ] && simular="X-Sandbox-Simular: limite"
status=$(curl -sS -G "$RMF_API_URL/icms/aliquotas" \
--data-urlencode ncm=85414121 --data-urlencode uf=SP \
--data-urlencode inicio=2026-10 --data-urlencode fim=2026-10 \
-H "Authorization: Bearer $RMF_API_KEY" -H 'Accept: application/json' ${simular:+-H "$simular"} \
-D "$tmp/cabecalhos" -o "$tmp/corpo" -w '%{http_code}')
if [ "$status" = 429 ]; then
espera=$(awk -F': ' 'tolower($1)=="retry-after" {print int($2)}' "$tmp/cabecalhos")
echo "429: aguardando ${espera:-1}s (tentativa $tentativa)" >&2
sleep "${espera:-1}"
continue
fi
if [ "$status" -ge 400 ]; then # application/problem+json
jq -r '"\(.codigo) (\(.request_id)): \(.detail)"' "$tmp/corpo" >&2
exit 1
fi
jq -r '.periodos[0] | "aliquota_interna=\(.aliquota_interna) aliquota_st=\(.aliquota_st) confianca=\(.confianca)"' "$tmp/corpo"
exit 0
done
echo "limite_excedido: tente mais tarde" >&2
exit 1
Exemplo testado no CI contra o sandbox

2. Leia a resposta​

A resposta vem agrupada em períodos: um novo período começa quando alguma informação muda. Para uma competência só, vem um período.

200 OK, application/json
{
"ncm": "85414121",
"uf": "SP",
"versao_base": "e964db7cb0e8",
"periodos": [
{
"inicio": "2026-10",
"fim": "2026-10",
"aliquota_interna": 12,
"aliquota_st": 12,
"na_st": true,
"situacao_st": "Na lista de ST",
"origem": "lei",
"confianca": "confirmada",
"texto_curto": "Lei do estado; na lista de ST; confirmada"
}
]
}
CampoTipoO que é
aliquota_internanúmeroAlíquota interna da operação própria, pela lei do estado ou, sem mapa da lei, a padrão do estado. Vem sempre, dentro ou fora da ST
aliquota_stnúmero ou nullAlíquota que a substituição tributária usa quando na_st é true (pode ser diferente da interna); null fora da ST. Nunca vem 0 para dizer "fora da ST"
na_stbooleano ou nullSe o NCM está na lista de ST no período. null quando a lista não é avaliada no estado (hoje, fora de SP)
situacao_sttextoPara exibir ao usuário. Para decidir no código, use na_st
origemlei, padrao_uf, pratica_mercadoDe onde vem a alíquota: a lei do estado, a alíquota padrão do estado ou a prática de mercado agregada e anonimizada
confiancaconfirmada, provavel, a_confirmarQuanto a base confia no resultado do período inteiro
texto_curtotextoUma frase com a origem, a situação na ST e a confiança, para exibir
versao_basetextoVersão da base de alíquotas usada. Guarde junto do resultado

A resposta traz o resultado, não a regra: sem artigo de lei e sem o caminho que levou ao valor.

3. Decida pela confiança​

Leia confianca antes de usar o valor. Ela é a mais fraca entre a confiança na situação na ST e a confiança na alíquota interna.

confirmadaA lei decide o NCM sem dúvida.
provavelA lei decide, mas a descrição do produto não foi conferida: o NCM está na ST apenas pelo código.
a_confirmarA base não decide sozinha. O valor é a melhor estimativa: confirme antes de usar em apuração.
Fora de SP, toda alíquota sai a_confirmar

Hoje só SP tem mapa da lei. Os demais estados usam a alíquota padrão do estado, com na_st e aliquota_st nulos. A cobertura de cada UF está em GET /v1/icms/cobertura.

Se der erro​

Erros vêm em application/problem+json (RFC 9457). Decida pelo codigo, nunca pelo texto, e guarde o request_id para falar com o suporte.

HTTPcodigoO que fazer
401chave_ausente, chave_invalidaEnvie Authorization: Bearer. Confira o ambiente: chave rmf_test_ só vale no sandbox
403escopo_insuficienteUse uma chave com o escopo consultas:ler
403fora_do_planoO produto não está no plano da conta. Fale com a equipe da RMF para mudar o plano
422parametro_invalidoVeja erros: o NCM tem 8 dígitos, sem ponto; a competência é AAAA-MM
429limite_excedidoEspere o tempo de Retry-After e tente de novo
503servico_indisponivelO serviço está fora do ar ou ocupado. Repita com espera exponencial, respeitando Retry-After. Em POST, repita com a mesma Idempotency-Key
429, application/problem+json, Retry-After: 23
{
"type": "https://docs.rmfestrategia.com/erros/limite_excedido",
"title": "Limite excedido",
"status": 429,
"detail": "Você passou do limite de chamadas por minuto. Tente de novo em 23 segundos.",
"instance": "/v1/icms/aliquotas",
"codigo": "limite_excedido",
"request_id": "req_01JC8FBG6R8V2X5Z9C3E7HKMNP"
}

Próximos passos​

Ambiente desta página

Sandbox, banco próprio: https://sandbox.api.rmfestrategia.com/v1.