🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

iptuapi

Package Overview
Dependencies
Maintainers
1
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

iptuapi - npm Package Compare versions

Comparing version
2.0.3
to
2.1.0
+449
-269
dist/index.d.mts
/**
* IPTU API - JavaScript/TypeScript SDK
*
* SDK oficial para integração com a IPTU API.
* Suporta retry automático, logging e rate limit tracking.
*
* @example
* ```typescript
* import { IPTUClient } from 'iptuapi';
*
* const client = new IPTUClient('sua_api_key');
* const resultado = await client.consultaEndereco('Avenida Paulista', '1000');
* console.log(resultado);
* ```
*
* @example
* ```typescript
* // Com configuração customizada
* const client = new IPTUClient('sua_api_key', {
* timeout: 60000,
* retries: 5,
* logger: console,
* });
* ```
* Tipos e interfaces para a IPTU API.
*/
type Cidade = 'sp' | 'bh' | 'recife';
declare const CidadeEnum: {
readonly SAO_PAULO: Cidade;
readonly BELO_HORIZONTE: Cidade;
readonly RECIFE: Cidade;
};
interface RetryConfig {
maxRetries: number;
initialDelay: number;
maxDelay: number;
backoffFactor: number;
retryableStatusCodes: number[];
}
interface ClientConfig {
baseUrl: string;
timeout: number;
retryConfig: RetryConfig;
}
interface ClientOptions {
baseUrl?: string;
timeout?: number;
retryConfig?: Partial<RetryConfig>;
}
interface RateLimitInfo {
limit: number;
remaining: number;
reset: number;
resetDate: Date;
resetAt: Date;
}
interface ConsultaEnderecoParams {
logradouro: string;
numero?: string;
complemento?: string;
cidade?: Cidade;
incluirHistorico?: boolean;
incluirComparaveis?: boolean;
incluirZoneamento?: boolean;
}
interface ConsultaEnderecoResult {
interface Imovel {
sql: string;
logradouro: string;
numero?: string;
complemento?: string;
bairro?: string;
numero: string;
bairro: string;
cep?: string;
area_terreno?: number;
area_construida?: number;
valor_venal_terreno?: number;
valor_venal_construcao?: number;
valor_venal_total?: number;
iptu_valor?: number;
ano_construcao?: number;
tipo_uso?: string;
areaTerreno?: number;
areaConstruida?: number;
valorVenal?: number;
valorVenalTerreno?: number;
valorVenalConstrucao?: number;
anoConstrucao?: number;
uso?: string;
padrao?: string;
testada?: number;
fracaoIdeal?: number;
quantidadePavimentos?: number;
}
interface Zoneamento {
zona: string;
usoPermitido: string;
coeficienteAproveitamento?: number;
taxaOcupacao?: number;
gabarito?: number;
recuoFrontal?: number;
legislacao?: string;
}
interface Valuation {
valorEstimado: number;
valorMinimo: number;
valorMaximo: number;
confianca: number;
valorM2: number;
metodologia: string;
dataReferencia: string;
}
interface ValuationParams {
areaTerreno: number;
areaConstruida: number;
bairro: string;
cidade?: string;
zona?: string;
historico?: HistoricoItem[];
comparaveis?: ComparavelItem[];
zoneamento?: ZoneamentoResult;
tipoUso?: string;
tipoPadrao?: string;
anoConstrucao?: number;
}
interface ConsultaSQLResult {
interface Comparavel {
sql: string;
ano?: number;
valor_venal?: number;
valor_venal_terreno?: number;
valor_venal_construcao?: number;
valor_venal_total?: number;
iptu_valor?: number;
logradouro?: string;
numero?: string;
bairro?: string;
area_terreno?: number;
area_construida?: number;
logradouro: string;
bairro: string;
areaConstruida: number;
valorVenal: number;
valorM2: number;
distanciaKm?: number;
}
interface HistoricoItem {
ano: number;
valor_venal_terreno?: number;
valor_venal_construcao?: number;
valor_venal_total?: number;
iptu_valor?: number;
interface ComparablesParams {
bairro: string;
areaMin: number;
areaMax: number;
cidade?: string;
limit?: number;
}
interface ComparavelItem {
sql?: string;
logradouro?: string;
numero?: string;
bairro?: string;
area_terreno?: number;
area_construida?: number;
valor_venal_total?: number;
distancia_metros?: number;
interface ITBIStatus {
protocolo: string;
status: string;
dataSolicitacao: string;
valorTransacao: number;
valorVenalReferencia: number;
baseCalculo: number;
aliquota: number;
valorITBI: number;
dataAprovacao?: string;
}
interface ZoneamentoResult {
zona?: string;
zona_descricao?: string;
coeficiente_aproveitamento_basico?: number;
coeficiente_aproveitamento_maximo?: number;
taxa_ocupacao_maxima?: number;
gabarito_maximo?: number;
interface ITBICalculo {
sql: string;
valorTransacao: number;
valorVenalReferencia: number;
baseCalculo: number;
aliquota: number;
valorITBI: number;
isencaoAplicavel: boolean;
fundamentacaoLegal: string;
}
interface ValuationParams {
area_terreno: number;
area_construida: number;
bairro: string;
zona: string;
tipo_uso: string;
tipo_padrao: string;
ano_construcao?: number;
cidade?: Cidade;
interface ITBICalculoParams {
sql: string;
valorTransacao: number;
cidade?: string;
}
interface ValuationResult {
valor_estimado: number;
valor_minimo?: number;
valor_maximo?: number;
confianca?: number;
metodo?: string;
comparaveis_utilizados?: number;
data_avaliacao?: string;
interface ITBIHistorico {
protocolo: string;
dataTransacao: string;
tipoTransacao: string;
valorTransacao: number;
valorITBI: number;
}
interface BatchValuationResult {
resultados: ValuationResult[];
total_processados: number;
total_erros: number;
erros?: Array<{
index: number;
error: string;
}>;
interface ITBIAliquota {
cidade: string;
aliquotaPadrao: number;
aliquotaFinanciamentoSFH: number;
valorMinimoIsencao: number;
baseLegal: string;
vigencia: string;
}
declare class IPTUAPIError extends Error {
readonly statusCode?: number;
readonly requestId?: string;
readonly responseBody?: Record<string, unknown>;
constructor(message: string, statusCode?: number, requestId?: string, responseBody?: Record<string, unknown>);
get isRetryable(): boolean;
interface ITBIIsencao {
tipo: string;
descricao: string;
requisitos: string[];
baseLegal: string;
}
declare class AuthenticationError extends IPTUAPIError {
constructor(message?: string, requestId?: string, responseBody?: Record<string, unknown>);
interface Pessoa {
nome: string;
documento: string;
email?: string;
}
declare class ForbiddenError extends IPTUAPIError {
readonly requiredPlan?: string;
constructor(message?: string, requiredPlan?: string, requestId?: string, responseBody?: Record<string, unknown>);
interface ITBIGuiaParams {
sql: string;
valorTransacao: number;
comprador: Pessoa;
vendedor: Pessoa;
cidade?: string;
}
declare class NotFoundError extends IPTUAPIError {
constructor(message?: string, requestId?: string, responseBody?: Record<string, unknown>);
interface ITBIGuia {
protocolo: string;
codigoBarras: string;
linhaDigitavel: string;
dataEmissao: string;
dataVencimento: string;
valorITBI: number;
}
declare class RateLimitError extends IPTUAPIError {
readonly retryAfter?: number;
readonly limit?: number;
readonly remaining?: number;
constructor(message?: string, retryAfter?: number, limit?: number, remaining?: number, requestId?: string, responseBody?: Record<string, unknown>);
get isRetryable(): boolean;
interface ITBIValidacao {
protocolo: string;
valido: boolean;
pago: boolean;
dataPagamento?: string;
valorPago?: number;
}
declare class ValidationError extends IPTUAPIError {
readonly errors?: Array<{
field: string;
message: string;
}>;
constructor(message?: string, errors?: Array<{
field: string;
message: string;
}>, requestId?: string, responseBody?: Record<string, unknown>);
interface ITBISimularParams {
valorTransacao: number;
cidade?: string;
tipoFinanciamento?: 'sfh' | 'nao_sfh';
valorFinanciado?: number;
}
declare class ServerError extends IPTUAPIError {
constructor(message?: string, statusCode?: number, requestId?: string, responseBody?: Record<string, unknown>);
get isRetryable(): boolean;
interface ITBISimulacao {
valorTransacao: number;
valorFinanciado: number;
valorNaoFinanciado: number;
aliquotaSFH: number;
aliquotaPadrao: number;
valorITBIFinanciado: number;
valorITBINaoFinanciado: number;
valorITBITotal: number;
economiaSFH: number;
}
declare class TimeoutError extends IPTUAPIError {
readonly timeoutMs?: number;
constructor(message?: string, timeoutMs?: number);
get isRetryable(): boolean;
interface EvaluateParams {
/** Numero SQL do imovel (alternativa ao endereco) */
sql?: string;
/** Nome da rua/avenida (alternativa ao SQL) */
logradouro?: string;
/** Numero do imovel */
numero?: number;
/** Apartamento, sala, etc. */
complemento?: string;
/** Bairro */
bairro?: string;
/** Codigo da cidade (sp, bh) */
cidade?: string;
/** Incluir estimativa baseada em ITBI */
incluirItbi?: boolean;
/** Incluir lista de imoveis comparaveis */
incluirComparaveis?: boolean;
}
declare class NetworkError extends IPTUAPIError {
readonly originalError?: Error;
constructor(message?: string, originalError?: Error);
get isRetryable(): boolean;
interface AVMEstimate {
/** Valor estimado em R$ */
valorEstimado: number;
/** Valor minimo do intervalo */
valorMinimo: number;
/** Valor maximo do intervalo */
valorMaximo: number;
/** Valor por m2 */
valorM2: number;
/** Nivel de confianca (0-1) */
confianca: number;
/** Versao do modelo */
modeloVersao: string;
}
interface Logger {
debug?(message: string, ...args: unknown[]): void;
info?(message: string, ...args: unknown[]): void;
warn?(message: string, ...args: unknown[]): void;
error?(message: string, ...args: unknown[]): void;
interface ITBIMarketEstimate {
/** Valor estimado em R$ */
valorEstimado: number;
/** Valor minimo da faixa */
faixaMinima: number;
/** Valor maximo da faixa */
faixaMaxima: number;
/** Valor por m2 (mediana) */
valorM2Mediana: number;
/** Total de transacoes analisadas */
totalTransacoes: number;
/** Periodo considerado */
periodo: string;
/** Fonte dos dados */
fonte: string;
}
interface RetryConfig {
/** Maximum number of retry attempts (default: 3) */
maxRetries: number;
/** Initial delay in ms between retries (default: 500) */
initialDelay: number;
/** Maximum delay in ms between retries (default: 10000) */
maxDelay: number;
/** Backoff factor (default: 2) */
backoffFactor: number;
/** Status codes that trigger retry (default: [429, 500, 502, 503, 504]) */
retryableStatuses: number[];
interface FinalValuation {
/** Valor estimado final */
estimado: number;
/** Valor minimo */
minimo: number;
/** Valor maximo */
maximo: number;
/** Metodo utilizado (blend_avm_itbi, avm_only, itbi_only) */
metodo: string;
/** Peso do AVM no calculo (0-1) */
pesoAvm: number;
/** Peso do ITBI no calculo (0-1) */
pesoItbi: number;
/** Nivel de confianca */
confianca: number;
/** Nota explicativa */
nota?: string;
}
interface IPTUClientOptions {
/** Base URL for the API (default: https://iptuapi.com.br/api/v1) */
baseUrl?: string;
/** Request timeout in milliseconds (default: 30000) */
timeout?: number;
/** Retry configuration */
retry?: Partial<RetryConfig>;
/** Logger instance for debugging */
logger?: Logger;
/** Enable request logging (default: false) */
logRequests?: boolean;
/** Enable response logging (default: false) */
logResponses?: boolean;
/** Custom User-Agent header */
userAgent?: string;
interface PropertyEvaluation {
/** Se a avaliacao foi bem sucedida */
success: boolean;
/** Dados cadastrais do imovel */
imovel: Record<string, unknown>;
/** Avaliacao pelo modelo ML (AVM) */
avaliacaoAvm?: AVMEstimate;
/** Avaliacao por transacoes ITBI reais */
avaliacaoItbi?: ITBIMarketEstimate;
/** Valor final combinado */
valorFinal: FinalValuation;
/** Imoveis comparaveis */
comparaveis?: Record<string, unknown>;
/** Metadados da avaliacao */
metadata: {
processadoEm: string;
fontes: string[];
cidade: string;
};
}
type Cidade = 'sp' | 'bh' | 'recife' | 'poa' | 'fortaleza' | 'curitiba' | 'rj' | 'brasilia';
/**
* Cliente principal para a IPTU API.
*/
/**
* Cliente para interagir com a IPTU API.
*/
declare class IPTUClient {
private readonly apiKey;
private readonly baseUrl;
private readonly timeout;
private readonly retryConfig;
private readonly logger?;
private readonly logRequests;
private readonly logResponses;
private readonly userAgent;
private _rateLimit?;
private _lastRequestId?;
constructor(apiKey: string, options?: IPTUClientOptions);
/** Rate limit info from last request */
get rateLimit(): RateLimitInfo | undefined;
/** Request ID from last request (useful for support) */
get lastRequestId(): string | undefined;
private log;
private readonly config;
private _rateLimitInfo;
private _lastRequestId;
/**
* Cria uma nova instancia do cliente.
*
* @param apiKey - Chave de API para autenticacao
* @param options - Opcoes de configuracao
*/
constructor(apiKey: string, options?: ClientOptions);
/**
* Retorna informacoes do rate limit da ultima requisicao.
*/
get rateLimitInfo(): RateLimitInfo | null;
/**
* Retorna o ID da ultima requisicao.
*/
get lastRequestId(): string | null;
/**
* Executa uma requisicao HTTP com retry.
*/
private makeRequest;
/**
* Atualiza informacoes de rate limit a partir dos headers.
*/
private updateRateLimitInfo;
/**
* Converte resposta HTTP em excecao apropriada.
*/
private handleError;
/**
* Aguarda um tempo em milissegundos.
*/
private sleep;
private calculateDelay;
private extractRateLimit;
private handleErrorResponse;
private request;
/**
* Busca dados de IPTU por endereço.
* Consulta imoveis por endereco.
*
* @param params - Parâmetros da consulta
* @returns Dados do imóvel encontrado
* @throws {NotFoundError} Se o imóvel não for encontrado
* @throws {ValidationError} Se os parâmetros forem inválidos
* @throws {AuthenticationError} Se a API Key for inválida
* @throws {RateLimitError} Se exceder o limite de requisições
* @param logradouro - Nome da rua/avenida
* @param numero - Numero do imovel
* @param cidade - Codigo da cidade (sp, bh, recife)
* @returns Lista de imoveis encontrados
*/
consultaEndereco(params: ConsultaEnderecoParams): Promise<ConsultaEnderecoResult>;
consultaEndereco(logradouro: string, numero?: string, cidade?: Cidade): Promise<ConsultaEnderecoResult>;
consultaEndereco(logradouro: string, numero: string, cidade?: Cidade): Promise<Imovel[]>;
/**
* Busca dados de IPTU por número SQL (contribuinte).
* Consulta imovel por numero SQL/Indice Cadastral.
* Requer plano Starter ou superior.
*
* @param sql - Número SQL do imóvel
* @param cidade - Cidade da consulta
* @param options - Opções adicionais
* @returns Dados completos do imóvel
* @param sql - Numero SQL (SP), Indice Cadastral (BH) ou Sequencial (Recife)
* @param cidade - Codigo da cidade (sp, bh, recife)
* @returns Lista de imoveis encontrados
*/
consultaSQL(sql: string, cidade?: Cidade, options?: {
incluirHistorico?: boolean;
incluirComparaveis?: boolean;
}): Promise<ConsultaSQLResult>;
consultaSQL(sql: string, cidade?: Cidade): Promise<Imovel[]>;
/**
* Busca imóveis por CEP.
* Consulta imoveis por CEP.
*
* @param cep - CEP do imóvel
* @param cidade - Cidade da consulta
* @returns Lista de imóveis no CEP
* @param cep - CEP do endereco
* @param cidade - Codigo da cidade (sp, bh, recife)
* @returns Lista de imoveis encontrados
*/
consultaCEP(cep: string, cidade?: Cidade): Promise<ConsultaEnderecoResult[]>;
consultaCEP(cep: string, cidade?: Cidade): Promise<Imovel[]>;
/**

@@ -275,65 +341,179 @@ * Consulta zoneamento por coordenadas.

* @param longitude - Longitude do ponto
* @returns Dados de zoneamento
* @returns Informacoes de zoneamento
*/
consultaZoneamento(latitude: number, longitude: number): Promise<ZoneamentoResult>;
consultaZoneamento(latitude: number, longitude: number): Promise<Zoneamento>;
/**
* Estima o valor de mercado do imóvel usando ML.
* Disponível apenas para planos Pro e Enterprise.
* Calcula estimativa de valor de mercado.
* Requer plano Pro ou superior.
*
* @param params - Parâmetros do imóvel
* @returns Estimativa de valor
* @throws {ForbiddenError} Se o plano não permitir
* @param params - Parametros da avaliacao
* @returns Avaliacao de mercado
*/
valuationEstimate(params: ValuationParams): Promise<ValuationResult>;
valuationEstimate(params: ValuationParams): Promise<Valuation>;
/**
* Valuation em lote (até 100 imóveis).
* Disponível apenas para plano Enterprise.
* Busca imoveis comparaveis.
* Requer plano Pro ou superior.
*
* @param imoveis - Lista de imóveis para avaliar
* @returns Resultados de valuation para cada imóvel
* @param params - Parametros da busca
* @returns Lista de imoveis comparaveis
*/
valuationBatch(imoveis: ValuationParams[]): Promise<BatchValuationResult>;
valuationComparables(params: ComparablesParams): Promise<Comparavel[]>;
/**
* Busca imóveis comparáveis para análise.
* Avalia imovel por endereco OU SQL.
* Combina dados do modelo AVM (ML) com transacoes ITBI reais.
* Requer plano Pro ou superior.
*
* @param bairro - Nome do bairro
* @param areaMin - Área mínima em m²
* @param areaMax - Área máxima em m²
* @param options - Opções adicionais
* @returns Lista de imóveis comparáveis
* @param params - Parametros da avaliacao (sql OU logradouro+numero)
* @returns Avaliacao completa do imovel
*/
valuationComparables(bairro: string, areaMin: number, areaMax: number, options?: {
tipoUso?: string;
cidade?: Cidade;
limit?: number;
}): Promise<ComparavelItem[]>;
valuationEvaluate(params: EvaluateParams): Promise<PropertyEvaluation>;
/**
* Histórico de valores IPTU de um imóvel.
* Consulta status de transacao ITBI.
*
* @param sql - Número SQL do imóvel
* @param cidade - Cidade da consulta
* @returns Lista com histórico anual
* @param protocolo - Numero do protocolo ITBI
* @param cidade - Codigo da cidade (sp, bh, recife)
* @returns Status da transacao
*/
dadosIPTUHistorico(sql: string, cidade?: Cidade): Promise<HistoricoItem[]>;
itbiStatus(protocolo: string, cidade?: Cidade): Promise<ITBIStatus>;
/**
* Consulta dados de empresa por CNPJ.
* Calcula valor do ITBI.
*
* @param cnpj - CNPJ da empresa
* @returns Dados cadastrais
* @param params - Parametros do calculo
* @returns Calculo do ITBI
*/
dadosCNPJ(cnpj: string): Promise<Record<string, unknown>>;
itbiCalcular(params: ITBICalculoParams): Promise<ITBICalculo>;
/**
* Correção monetária pelo IPCA.
* Consulta historico de transacoes ITBI de um imovel.
* Requer plano Starter ou superior.
*
* @param valor - Valor a corrigir
* @param dataOrigem - Data do valor original (YYYY-MM)
* @param dataDestino - Data destino (default: atual)
* @returns Valor corrigido e fator de correção
* @param sql - Numero SQL do imovel
* @param cidade - Codigo da cidade (sp, bh, recife)
* @returns Lista de transacoes historicas
*/
dadosIPCACorrigir(valor: number, dataOrigem: string, dataDestino?: string): Promise<{
valor_corrigido: number;
fator: number;
}>;
itbiHistorico(sql: string, cidade?: Cidade): Promise<ITBIHistorico[]>;
/**
* Consulta aliquotas ITBI vigentes.
*
* @param cidade - Codigo da cidade (sp, bh, recife)
* @returns Aliquotas vigentes
*/
itbiAliquotas(cidade?: Cidade): Promise<ITBIAliquota>;
/**
* Consulta isencoes ITBI disponiveis.
*
* @param cidade - Codigo da cidade (sp, bh, recife)
* @returns Lista de isencoes disponiveis
*/
itbiIsencoes(cidade?: Cidade): Promise<ITBIIsencao[]>;
/**
* Gera guia de pagamento ITBI.
* Requer plano Starter ou superior.
*
* @param params - Parametros da guia
* @returns Guia de pagamento gerada
*/
itbiGuia(params: ITBIGuiaParams): Promise<ITBIGuia>;
/**
* Valida autenticidade de uma guia ITBI.
*
* @param protocolo - Numero do protocolo da guia
* @param cidade - Codigo da cidade (sp, bh, recife)
* @returns Resultado da validacao
*/
itbiValidarGuia(protocolo: string, cidade?: Cidade): Promise<ITBIValidacao>;
/**
* Simula calculo de ITBI.
*
* @param params - Parametros da simulacao
* @returns Resultado da simulacao
*/
itbiSimular(params: ITBISimularParams): Promise<ITBISimulacao>;
}
export { AuthenticationError, type BatchValuationResult, type Cidade, CidadeEnum, type ComparavelItem, type ConsultaEnderecoParams, type ConsultaEnderecoResult, type ConsultaSQLResult, ForbiddenError, type HistoricoItem, IPTUAPIError, IPTUClient, type IPTUClientOptions, type Logger, NetworkError, NotFoundError, RateLimitError, type RateLimitInfo, type RetryConfig, ServerError, TimeoutError, ValidationError, type ValuationParams, type ValuationResult, type ZoneamentoResult, IPTUClient as default };
/**
* Excecoes customizadas para a IPTU API.
*/
interface ErrorDetails {
error: string;
message: string;
statusCode?: number;
requestId?: string;
retryable: boolean;
[key: string]: unknown;
}
/**
* Excecao base para todos os erros da IPTU API.
*/
declare class IPTUAPIError extends Error {
readonly statusCode?: number;
readonly requestId?: string;
readonly responseData: Record<string, unknown>;
constructor(message: string, statusCode?: number, requestId?: string, responseData?: Record<string, unknown>);
isRetryable(): boolean;
toJSON(): ErrorDetails;
}
/**
* Erro de autenticacao (401). API Key invalida ou ausente.
*/
declare class AuthenticationError extends IPTUAPIError {
constructor(message?: string, requestId?: string);
}
/**
* Erro de autorizacao (403). Plano nao permite acesso ao recurso.
*/
declare class ForbiddenError extends IPTUAPIError {
readonly requiredPlan?: string;
constructor(message?: string, requiredPlan?: string, requestId?: string);
toJSON(): ErrorDetails;
}
/**
* Erro de recurso nao encontrado (404).
*/
declare class NotFoundError extends IPTUAPIError {
readonly resource?: string;
constructor(message?: string, resource?: string, requestId?: string);
toJSON(): ErrorDetails;
}
/**
* Erro de rate limit excedido (429).
*/
declare class RateLimitError extends IPTUAPIError {
readonly retryAfter: number;
constructor(message?: string, retryAfter?: number, requestId?: string);
isRetryable(): boolean;
toJSON(): ErrorDetails;
}
/**
* Erro de validacao de parametros (400, 422).
*/
declare class ValidationError extends IPTUAPIError {
readonly errors: Record<string, string[]>;
constructor(message?: string, errors?: Record<string, string[]>, statusCode?: number, requestId?: string);
toJSON(): ErrorDetails;
}
/**
* Erro interno do servidor (5xx). Retryable.
*/
declare class ServerError extends IPTUAPIError {
constructor(message?: string, statusCode?: number, requestId?: string);
isRetryable(): boolean;
}
/**
* Erro de timeout na requisicao.
*/
declare class TimeoutError extends IPTUAPIError {
readonly timeoutSeconds?: number;
constructor(message?: string, timeoutSeconds?: number, requestId?: string);
isRetryable(): boolean;
toJSON(): ErrorDetails;
}
/**
* Erro de conexao de rede.
*/
declare class NetworkError extends IPTUAPIError {
readonly originalError?: Error;
constructor(message?: string, originalError?: Error);
isRetryable(): boolean;
}
export { type AVMEstimate, AuthenticationError, type Cidade, type ClientConfig, type ClientOptions, type ComparablesParams, type Comparavel, type EvaluateParams, type FinalValuation, ForbiddenError, IPTUAPIError, IPTUClient, type ITBIAliquota, type ITBICalculo, type ITBICalculoParams, type ITBIGuia, type ITBIGuiaParams, type ITBIHistorico, type ITBIIsencao, type ITBIMarketEstimate, type ITBISimulacao, type ITBISimularParams, type ITBIStatus, type ITBIValidacao, type Imovel, NetworkError, NotFoundError, type Pessoa, type PropertyEvaluation, RateLimitError, type RateLimitInfo, type RetryConfig, ServerError, TimeoutError, ValidationError, type Valuation, type ValuationParams, type Zoneamento };
/**
* IPTU API - JavaScript/TypeScript SDK
*
* SDK oficial para integração com a IPTU API.
* Suporta retry automático, logging e rate limit tracking.
*
* @example
* ```typescript
* import { IPTUClient } from 'iptuapi';
*
* const client = new IPTUClient('sua_api_key');
* const resultado = await client.consultaEndereco('Avenida Paulista', '1000');
* console.log(resultado);
* ```
*
* @example
* ```typescript
* // Com configuração customizada
* const client = new IPTUClient('sua_api_key', {
* timeout: 60000,
* retries: 5,
* logger: console,
* });
* ```
* Tipos e interfaces para a IPTU API.
*/
type Cidade = 'sp' | 'bh' | 'recife';
declare const CidadeEnum: {
readonly SAO_PAULO: Cidade;
readonly BELO_HORIZONTE: Cidade;
readonly RECIFE: Cidade;
};
interface RetryConfig {
maxRetries: number;
initialDelay: number;
maxDelay: number;
backoffFactor: number;
retryableStatusCodes: number[];
}
interface ClientConfig {
baseUrl: string;
timeout: number;
retryConfig: RetryConfig;
}
interface ClientOptions {
baseUrl?: string;
timeout?: number;
retryConfig?: Partial<RetryConfig>;
}
interface RateLimitInfo {
limit: number;
remaining: number;
reset: number;
resetDate: Date;
resetAt: Date;
}
interface ConsultaEnderecoParams {
logradouro: string;
numero?: string;
complemento?: string;
cidade?: Cidade;
incluirHistorico?: boolean;
incluirComparaveis?: boolean;
incluirZoneamento?: boolean;
}
interface ConsultaEnderecoResult {
interface Imovel {
sql: string;
logradouro: string;
numero?: string;
complemento?: string;
bairro?: string;
numero: string;
bairro: string;
cep?: string;
area_terreno?: number;
area_construida?: number;
valor_venal_terreno?: number;
valor_venal_construcao?: number;
valor_venal_total?: number;
iptu_valor?: number;
ano_construcao?: number;
tipo_uso?: string;
areaTerreno?: number;
areaConstruida?: number;
valorVenal?: number;
valorVenalTerreno?: number;
valorVenalConstrucao?: number;
anoConstrucao?: number;
uso?: string;
padrao?: string;
testada?: number;
fracaoIdeal?: number;
quantidadePavimentos?: number;
}
interface Zoneamento {
zona: string;
usoPermitido: string;
coeficienteAproveitamento?: number;
taxaOcupacao?: number;
gabarito?: number;
recuoFrontal?: number;
legislacao?: string;
}
interface Valuation {
valorEstimado: number;
valorMinimo: number;
valorMaximo: number;
confianca: number;
valorM2: number;
metodologia: string;
dataReferencia: string;
}
interface ValuationParams {
areaTerreno: number;
areaConstruida: number;
bairro: string;
cidade?: string;
zona?: string;
historico?: HistoricoItem[];
comparaveis?: ComparavelItem[];
zoneamento?: ZoneamentoResult;
tipoUso?: string;
tipoPadrao?: string;
anoConstrucao?: number;
}
interface ConsultaSQLResult {
interface Comparavel {
sql: string;
ano?: number;
valor_venal?: number;
valor_venal_terreno?: number;
valor_venal_construcao?: number;
valor_venal_total?: number;
iptu_valor?: number;
logradouro?: string;
numero?: string;
bairro?: string;
area_terreno?: number;
area_construida?: number;
logradouro: string;
bairro: string;
areaConstruida: number;
valorVenal: number;
valorM2: number;
distanciaKm?: number;
}
interface HistoricoItem {
ano: number;
valor_venal_terreno?: number;
valor_venal_construcao?: number;
valor_venal_total?: number;
iptu_valor?: number;
interface ComparablesParams {
bairro: string;
areaMin: number;
areaMax: number;
cidade?: string;
limit?: number;
}
interface ComparavelItem {
sql?: string;
logradouro?: string;
numero?: string;
bairro?: string;
area_terreno?: number;
area_construida?: number;
valor_venal_total?: number;
distancia_metros?: number;
interface ITBIStatus {
protocolo: string;
status: string;
dataSolicitacao: string;
valorTransacao: number;
valorVenalReferencia: number;
baseCalculo: number;
aliquota: number;
valorITBI: number;
dataAprovacao?: string;
}
interface ZoneamentoResult {
zona?: string;
zona_descricao?: string;
coeficiente_aproveitamento_basico?: number;
coeficiente_aproveitamento_maximo?: number;
taxa_ocupacao_maxima?: number;
gabarito_maximo?: number;
interface ITBICalculo {
sql: string;
valorTransacao: number;
valorVenalReferencia: number;
baseCalculo: number;
aliquota: number;
valorITBI: number;
isencaoAplicavel: boolean;
fundamentacaoLegal: string;
}
interface ValuationParams {
area_terreno: number;
area_construida: number;
bairro: string;
zona: string;
tipo_uso: string;
tipo_padrao: string;
ano_construcao?: number;
cidade?: Cidade;
interface ITBICalculoParams {
sql: string;
valorTransacao: number;
cidade?: string;
}
interface ValuationResult {
valor_estimado: number;
valor_minimo?: number;
valor_maximo?: number;
confianca?: number;
metodo?: string;
comparaveis_utilizados?: number;
data_avaliacao?: string;
interface ITBIHistorico {
protocolo: string;
dataTransacao: string;
tipoTransacao: string;
valorTransacao: number;
valorITBI: number;
}
interface BatchValuationResult {
resultados: ValuationResult[];
total_processados: number;
total_erros: number;
erros?: Array<{
index: number;
error: string;
}>;
interface ITBIAliquota {
cidade: string;
aliquotaPadrao: number;
aliquotaFinanciamentoSFH: number;
valorMinimoIsencao: number;
baseLegal: string;
vigencia: string;
}
declare class IPTUAPIError extends Error {
readonly statusCode?: number;
readonly requestId?: string;
readonly responseBody?: Record<string, unknown>;
constructor(message: string, statusCode?: number, requestId?: string, responseBody?: Record<string, unknown>);
get isRetryable(): boolean;
interface ITBIIsencao {
tipo: string;
descricao: string;
requisitos: string[];
baseLegal: string;
}
declare class AuthenticationError extends IPTUAPIError {
constructor(message?: string, requestId?: string, responseBody?: Record<string, unknown>);
interface Pessoa {
nome: string;
documento: string;
email?: string;
}
declare class ForbiddenError extends IPTUAPIError {
readonly requiredPlan?: string;
constructor(message?: string, requiredPlan?: string, requestId?: string, responseBody?: Record<string, unknown>);
interface ITBIGuiaParams {
sql: string;
valorTransacao: number;
comprador: Pessoa;
vendedor: Pessoa;
cidade?: string;
}
declare class NotFoundError extends IPTUAPIError {
constructor(message?: string, requestId?: string, responseBody?: Record<string, unknown>);
interface ITBIGuia {
protocolo: string;
codigoBarras: string;
linhaDigitavel: string;
dataEmissao: string;
dataVencimento: string;
valorITBI: number;
}
declare class RateLimitError extends IPTUAPIError {
readonly retryAfter?: number;
readonly limit?: number;
readonly remaining?: number;
constructor(message?: string, retryAfter?: number, limit?: number, remaining?: number, requestId?: string, responseBody?: Record<string, unknown>);
get isRetryable(): boolean;
interface ITBIValidacao {
protocolo: string;
valido: boolean;
pago: boolean;
dataPagamento?: string;
valorPago?: number;
}
declare class ValidationError extends IPTUAPIError {
readonly errors?: Array<{
field: string;
message: string;
}>;
constructor(message?: string, errors?: Array<{
field: string;
message: string;
}>, requestId?: string, responseBody?: Record<string, unknown>);
interface ITBISimularParams {
valorTransacao: number;
cidade?: string;
tipoFinanciamento?: 'sfh' | 'nao_sfh';
valorFinanciado?: number;
}
declare class ServerError extends IPTUAPIError {
constructor(message?: string, statusCode?: number, requestId?: string, responseBody?: Record<string, unknown>);
get isRetryable(): boolean;
interface ITBISimulacao {
valorTransacao: number;
valorFinanciado: number;
valorNaoFinanciado: number;
aliquotaSFH: number;
aliquotaPadrao: number;
valorITBIFinanciado: number;
valorITBINaoFinanciado: number;
valorITBITotal: number;
economiaSFH: number;
}
declare class TimeoutError extends IPTUAPIError {
readonly timeoutMs?: number;
constructor(message?: string, timeoutMs?: number);
get isRetryable(): boolean;
interface EvaluateParams {
/** Numero SQL do imovel (alternativa ao endereco) */
sql?: string;
/** Nome da rua/avenida (alternativa ao SQL) */
logradouro?: string;
/** Numero do imovel */
numero?: number;
/** Apartamento, sala, etc. */
complemento?: string;
/** Bairro */
bairro?: string;
/** Codigo da cidade (sp, bh) */
cidade?: string;
/** Incluir estimativa baseada em ITBI */
incluirItbi?: boolean;
/** Incluir lista de imoveis comparaveis */
incluirComparaveis?: boolean;
}
declare class NetworkError extends IPTUAPIError {
readonly originalError?: Error;
constructor(message?: string, originalError?: Error);
get isRetryable(): boolean;
interface AVMEstimate {
/** Valor estimado em R$ */
valorEstimado: number;
/** Valor minimo do intervalo */
valorMinimo: number;
/** Valor maximo do intervalo */
valorMaximo: number;
/** Valor por m2 */
valorM2: number;
/** Nivel de confianca (0-1) */
confianca: number;
/** Versao do modelo */
modeloVersao: string;
}
interface Logger {
debug?(message: string, ...args: unknown[]): void;
info?(message: string, ...args: unknown[]): void;
warn?(message: string, ...args: unknown[]): void;
error?(message: string, ...args: unknown[]): void;
interface ITBIMarketEstimate {
/** Valor estimado em R$ */
valorEstimado: number;
/** Valor minimo da faixa */
faixaMinima: number;
/** Valor maximo da faixa */
faixaMaxima: number;
/** Valor por m2 (mediana) */
valorM2Mediana: number;
/** Total de transacoes analisadas */
totalTransacoes: number;
/** Periodo considerado */
periodo: string;
/** Fonte dos dados */
fonte: string;
}
interface RetryConfig {
/** Maximum number of retry attempts (default: 3) */
maxRetries: number;
/** Initial delay in ms between retries (default: 500) */
initialDelay: number;
/** Maximum delay in ms between retries (default: 10000) */
maxDelay: number;
/** Backoff factor (default: 2) */
backoffFactor: number;
/** Status codes that trigger retry (default: [429, 500, 502, 503, 504]) */
retryableStatuses: number[];
interface FinalValuation {
/** Valor estimado final */
estimado: number;
/** Valor minimo */
minimo: number;
/** Valor maximo */
maximo: number;
/** Metodo utilizado (blend_avm_itbi, avm_only, itbi_only) */
metodo: string;
/** Peso do AVM no calculo (0-1) */
pesoAvm: number;
/** Peso do ITBI no calculo (0-1) */
pesoItbi: number;
/** Nivel de confianca */
confianca: number;
/** Nota explicativa */
nota?: string;
}
interface IPTUClientOptions {
/** Base URL for the API (default: https://iptuapi.com.br/api/v1) */
baseUrl?: string;
/** Request timeout in milliseconds (default: 30000) */
timeout?: number;
/** Retry configuration */
retry?: Partial<RetryConfig>;
/** Logger instance for debugging */
logger?: Logger;
/** Enable request logging (default: false) */
logRequests?: boolean;
/** Enable response logging (default: false) */
logResponses?: boolean;
/** Custom User-Agent header */
userAgent?: string;
interface PropertyEvaluation {
/** Se a avaliacao foi bem sucedida */
success: boolean;
/** Dados cadastrais do imovel */
imovel: Record<string, unknown>;
/** Avaliacao pelo modelo ML (AVM) */
avaliacaoAvm?: AVMEstimate;
/** Avaliacao por transacoes ITBI reais */
avaliacaoItbi?: ITBIMarketEstimate;
/** Valor final combinado */
valorFinal: FinalValuation;
/** Imoveis comparaveis */
comparaveis?: Record<string, unknown>;
/** Metadados da avaliacao */
metadata: {
processadoEm: string;
fontes: string[];
cidade: string;
};
}
type Cidade = 'sp' | 'bh' | 'recife' | 'poa' | 'fortaleza' | 'curitiba' | 'rj' | 'brasilia';
/**
* Cliente principal para a IPTU API.
*/
/**
* Cliente para interagir com a IPTU API.
*/
declare class IPTUClient {
private readonly apiKey;
private readonly baseUrl;
private readonly timeout;
private readonly retryConfig;
private readonly logger?;
private readonly logRequests;
private readonly logResponses;
private readonly userAgent;
private _rateLimit?;
private _lastRequestId?;
constructor(apiKey: string, options?: IPTUClientOptions);
/** Rate limit info from last request */
get rateLimit(): RateLimitInfo | undefined;
/** Request ID from last request (useful for support) */
get lastRequestId(): string | undefined;
private log;
private readonly config;
private _rateLimitInfo;
private _lastRequestId;
/**
* Cria uma nova instancia do cliente.
*
* @param apiKey - Chave de API para autenticacao
* @param options - Opcoes de configuracao
*/
constructor(apiKey: string, options?: ClientOptions);
/**
* Retorna informacoes do rate limit da ultima requisicao.
*/
get rateLimitInfo(): RateLimitInfo | null;
/**
* Retorna o ID da ultima requisicao.
*/
get lastRequestId(): string | null;
/**
* Executa uma requisicao HTTP com retry.
*/
private makeRequest;
/**
* Atualiza informacoes de rate limit a partir dos headers.
*/
private updateRateLimitInfo;
/**
* Converte resposta HTTP em excecao apropriada.
*/
private handleError;
/**
* Aguarda um tempo em milissegundos.
*/
private sleep;
private calculateDelay;
private extractRateLimit;
private handleErrorResponse;
private request;
/**
* Busca dados de IPTU por endereço.
* Consulta imoveis por endereco.
*
* @param params - Parâmetros da consulta
* @returns Dados do imóvel encontrado
* @throws {NotFoundError} Se o imóvel não for encontrado
* @throws {ValidationError} Se os parâmetros forem inválidos
* @throws {AuthenticationError} Se a API Key for inválida
* @throws {RateLimitError} Se exceder o limite de requisições
* @param logradouro - Nome da rua/avenida
* @param numero - Numero do imovel
* @param cidade - Codigo da cidade (sp, bh, recife)
* @returns Lista de imoveis encontrados
*/
consultaEndereco(params: ConsultaEnderecoParams): Promise<ConsultaEnderecoResult>;
consultaEndereco(logradouro: string, numero?: string, cidade?: Cidade): Promise<ConsultaEnderecoResult>;
consultaEndereco(logradouro: string, numero: string, cidade?: Cidade): Promise<Imovel[]>;
/**
* Busca dados de IPTU por número SQL (contribuinte).
* Consulta imovel por numero SQL/Indice Cadastral.
* Requer plano Starter ou superior.
*
* @param sql - Número SQL do imóvel
* @param cidade - Cidade da consulta
* @param options - Opções adicionais
* @returns Dados completos do imóvel
* @param sql - Numero SQL (SP), Indice Cadastral (BH) ou Sequencial (Recife)
* @param cidade - Codigo da cidade (sp, bh, recife)
* @returns Lista de imoveis encontrados
*/
consultaSQL(sql: string, cidade?: Cidade, options?: {
incluirHistorico?: boolean;
incluirComparaveis?: boolean;
}): Promise<ConsultaSQLResult>;
consultaSQL(sql: string, cidade?: Cidade): Promise<Imovel[]>;
/**
* Busca imóveis por CEP.
* Consulta imoveis por CEP.
*
* @param cep - CEP do imóvel
* @param cidade - Cidade da consulta
* @returns Lista de imóveis no CEP
* @param cep - CEP do endereco
* @param cidade - Codigo da cidade (sp, bh, recife)
* @returns Lista de imoveis encontrados
*/
consultaCEP(cep: string, cidade?: Cidade): Promise<ConsultaEnderecoResult[]>;
consultaCEP(cep: string, cidade?: Cidade): Promise<Imovel[]>;
/**

@@ -275,65 +341,179 @@ * Consulta zoneamento por coordenadas.

* @param longitude - Longitude do ponto
* @returns Dados de zoneamento
* @returns Informacoes de zoneamento
*/
consultaZoneamento(latitude: number, longitude: number): Promise<ZoneamentoResult>;
consultaZoneamento(latitude: number, longitude: number): Promise<Zoneamento>;
/**
* Estima o valor de mercado do imóvel usando ML.
* Disponível apenas para planos Pro e Enterprise.
* Calcula estimativa de valor de mercado.
* Requer plano Pro ou superior.
*
* @param params - Parâmetros do imóvel
* @returns Estimativa de valor
* @throws {ForbiddenError} Se o plano não permitir
* @param params - Parametros da avaliacao
* @returns Avaliacao de mercado
*/
valuationEstimate(params: ValuationParams): Promise<ValuationResult>;
valuationEstimate(params: ValuationParams): Promise<Valuation>;
/**
* Valuation em lote (até 100 imóveis).
* Disponível apenas para plano Enterprise.
* Busca imoveis comparaveis.
* Requer plano Pro ou superior.
*
* @param imoveis - Lista de imóveis para avaliar
* @returns Resultados de valuation para cada imóvel
* @param params - Parametros da busca
* @returns Lista de imoveis comparaveis
*/
valuationBatch(imoveis: ValuationParams[]): Promise<BatchValuationResult>;
valuationComparables(params: ComparablesParams): Promise<Comparavel[]>;
/**
* Busca imóveis comparáveis para análise.
* Avalia imovel por endereco OU SQL.
* Combina dados do modelo AVM (ML) com transacoes ITBI reais.
* Requer plano Pro ou superior.
*
* @param bairro - Nome do bairro
* @param areaMin - Área mínima em m²
* @param areaMax - Área máxima em m²
* @param options - Opções adicionais
* @returns Lista de imóveis comparáveis
* @param params - Parametros da avaliacao (sql OU logradouro+numero)
* @returns Avaliacao completa do imovel
*/
valuationComparables(bairro: string, areaMin: number, areaMax: number, options?: {
tipoUso?: string;
cidade?: Cidade;
limit?: number;
}): Promise<ComparavelItem[]>;
valuationEvaluate(params: EvaluateParams): Promise<PropertyEvaluation>;
/**
* Histórico de valores IPTU de um imóvel.
* Consulta status de transacao ITBI.
*
* @param sql - Número SQL do imóvel
* @param cidade - Cidade da consulta
* @returns Lista com histórico anual
* @param protocolo - Numero do protocolo ITBI
* @param cidade - Codigo da cidade (sp, bh, recife)
* @returns Status da transacao
*/
dadosIPTUHistorico(sql: string, cidade?: Cidade): Promise<HistoricoItem[]>;
itbiStatus(protocolo: string, cidade?: Cidade): Promise<ITBIStatus>;
/**
* Consulta dados de empresa por CNPJ.
* Calcula valor do ITBI.
*
* @param cnpj - CNPJ da empresa
* @returns Dados cadastrais
* @param params - Parametros do calculo
* @returns Calculo do ITBI
*/
dadosCNPJ(cnpj: string): Promise<Record<string, unknown>>;
itbiCalcular(params: ITBICalculoParams): Promise<ITBICalculo>;
/**
* Correção monetária pelo IPCA.
* Consulta historico de transacoes ITBI de um imovel.
* Requer plano Starter ou superior.
*
* @param valor - Valor a corrigir
* @param dataOrigem - Data do valor original (YYYY-MM)
* @param dataDestino - Data destino (default: atual)
* @returns Valor corrigido e fator de correção
* @param sql - Numero SQL do imovel
* @param cidade - Codigo da cidade (sp, bh, recife)
* @returns Lista de transacoes historicas
*/
dadosIPCACorrigir(valor: number, dataOrigem: string, dataDestino?: string): Promise<{
valor_corrigido: number;
fator: number;
}>;
itbiHistorico(sql: string, cidade?: Cidade): Promise<ITBIHistorico[]>;
/**
* Consulta aliquotas ITBI vigentes.
*
* @param cidade - Codigo da cidade (sp, bh, recife)
* @returns Aliquotas vigentes
*/
itbiAliquotas(cidade?: Cidade): Promise<ITBIAliquota>;
/**
* Consulta isencoes ITBI disponiveis.
*
* @param cidade - Codigo da cidade (sp, bh, recife)
* @returns Lista de isencoes disponiveis
*/
itbiIsencoes(cidade?: Cidade): Promise<ITBIIsencao[]>;
/**
* Gera guia de pagamento ITBI.
* Requer plano Starter ou superior.
*
* @param params - Parametros da guia
* @returns Guia de pagamento gerada
*/
itbiGuia(params: ITBIGuiaParams): Promise<ITBIGuia>;
/**
* Valida autenticidade de uma guia ITBI.
*
* @param protocolo - Numero do protocolo da guia
* @param cidade - Codigo da cidade (sp, bh, recife)
* @returns Resultado da validacao
*/
itbiValidarGuia(protocolo: string, cidade?: Cidade): Promise<ITBIValidacao>;
/**
* Simula calculo de ITBI.
*
* @param params - Parametros da simulacao
* @returns Resultado da simulacao
*/
itbiSimular(params: ITBISimularParams): Promise<ITBISimulacao>;
}
export { AuthenticationError, type BatchValuationResult, type Cidade, CidadeEnum, type ComparavelItem, type ConsultaEnderecoParams, type ConsultaEnderecoResult, type ConsultaSQLResult, ForbiddenError, type HistoricoItem, IPTUAPIError, IPTUClient, type IPTUClientOptions, type Logger, NetworkError, NotFoundError, RateLimitError, type RateLimitInfo, type RetryConfig, ServerError, TimeoutError, ValidationError, type ValuationParams, type ValuationResult, type ZoneamentoResult, IPTUClient as default };
/**
* Excecoes customizadas para a IPTU API.
*/
interface ErrorDetails {
error: string;
message: string;
statusCode?: number;
requestId?: string;
retryable: boolean;
[key: string]: unknown;
}
/**
* Excecao base para todos os erros da IPTU API.
*/
declare class IPTUAPIError extends Error {
readonly statusCode?: number;
readonly requestId?: string;
readonly responseData: Record<string, unknown>;
constructor(message: string, statusCode?: number, requestId?: string, responseData?: Record<string, unknown>);
isRetryable(): boolean;
toJSON(): ErrorDetails;
}
/**
* Erro de autenticacao (401). API Key invalida ou ausente.
*/
declare class AuthenticationError extends IPTUAPIError {
constructor(message?: string, requestId?: string);
}
/**
* Erro de autorizacao (403). Plano nao permite acesso ao recurso.
*/
declare class ForbiddenError extends IPTUAPIError {
readonly requiredPlan?: string;
constructor(message?: string, requiredPlan?: string, requestId?: string);
toJSON(): ErrorDetails;
}
/**
* Erro de recurso nao encontrado (404).
*/
declare class NotFoundError extends IPTUAPIError {
readonly resource?: string;
constructor(message?: string, resource?: string, requestId?: string);
toJSON(): ErrorDetails;
}
/**
* Erro de rate limit excedido (429).
*/
declare class RateLimitError extends IPTUAPIError {
readonly retryAfter: number;
constructor(message?: string, retryAfter?: number, requestId?: string);
isRetryable(): boolean;
toJSON(): ErrorDetails;
}
/**
* Erro de validacao de parametros (400, 422).
*/
declare class ValidationError extends IPTUAPIError {
readonly errors: Record<string, string[]>;
constructor(message?: string, errors?: Record<string, string[]>, statusCode?: number, requestId?: string);
toJSON(): ErrorDetails;
}
/**
* Erro interno do servidor (5xx). Retryable.
*/
declare class ServerError extends IPTUAPIError {
constructor(message?: string, statusCode?: number, requestId?: string);
isRetryable(): boolean;
}
/**
* Erro de timeout na requisicao.
*/
declare class TimeoutError extends IPTUAPIError {
readonly timeoutSeconds?: number;
constructor(message?: string, timeoutSeconds?: number, requestId?: string);
isRetryable(): boolean;
toJSON(): ErrorDetails;
}
/**
* Erro de conexao de rede.
*/
declare class NetworkError extends IPTUAPIError {
readonly originalError?: Error;
constructor(message?: string, originalError?: Error);
isRetryable(): boolean;
}
export { type AVMEstimate, AuthenticationError, type Cidade, type ClientConfig, type ClientOptions, type ComparablesParams, type Comparavel, type EvaluateParams, type FinalValuation, ForbiddenError, IPTUAPIError, IPTUClient, type ITBIAliquota, type ITBICalculo, type ITBICalculoParams, type ITBIGuia, type ITBIGuiaParams, type ITBIHistorico, type ITBIIsencao, type ITBIMarketEstimate, type ITBISimulacao, type ITBISimularParams, type ITBIStatus, type ITBIValidacao, type Imovel, NetworkError, NotFoundError, type Pessoa, type PropertyEvaluation, RateLimitError, type RateLimitInfo, type RetryConfig, ServerError, TimeoutError, ValidationError, type Valuation, type ValuationParams, type Zoneamento };

@@ -24,3 +24,2 @@ "use strict";

AuthenticationError: () => AuthenticationError,
CidadeEnum: () => CidadeEnum,
ForbiddenError: () => ForbiddenError,

@@ -34,16 +33,12 @@ IPTUAPIError: () => IPTUAPIError,

TimeoutError: () => TimeoutError,
ValidationError: () => ValidationError,
default: () => index_default
ValidationError: () => ValidationError
});
module.exports = __toCommonJS(index_exports);
var CidadeEnum = {
SAO_PAULO: "sp",
BELO_HORIZONTE: "bh",
RECIFE: "recife"
};
// src/errors.ts
var IPTUAPIError = class _IPTUAPIError extends Error {
statusCode;
requestId;
responseBody;
constructor(message, statusCode, requestId, responseBody) {
responseData;
constructor(message, statusCode, requestId, responseData) {
super(message);

@@ -53,12 +48,21 @@ this.name = "IPTUAPIError";

this.requestId = requestId;
this.responseBody = responseBody;
this.responseData = responseData || {};
Object.setPrototypeOf(this, _IPTUAPIError.prototype);
}
get isRetryable() {
return this.statusCode ? [429, 500, 502, 503, 504].includes(this.statusCode) : false;
isRetryable() {
return false;
}
toJSON() {
return {
error: this.name,
message: this.message,
statusCode: this.statusCode,
requestId: this.requestId,
retryable: this.isRetryable()
};
}
};
var AuthenticationError = class _AuthenticationError extends IPTUAPIError {
constructor(message = "API Key inv\xE1lida ou expirada", requestId, responseBody) {
super(message, 401, requestId, responseBody);
constructor(message = "API Key invalida ou ausente", requestId) {
super(message, 401, requestId);
this.name = "AuthenticationError";

@@ -70,4 +74,4 @@ Object.setPrototypeOf(this, _AuthenticationError.prototype);

requiredPlan;
constructor(message = "Plano n\xE3o autorizado para este recurso", requiredPlan, requestId, responseBody) {
super(message, 403, requestId, responseBody);
constructor(message = "Acesso negado", requiredPlan, requestId) {
super(message, 403, requestId);
this.name = "ForbiddenError";

@@ -77,42 +81,64 @@ this.requiredPlan = requiredPlan;

}
toJSON() {
return {
...super.toJSON(),
requiredPlan: this.requiredPlan
};
}
};
var NotFoundError = class _NotFoundError extends IPTUAPIError {
constructor(message = "Recurso n\xE3o encontrado", requestId, responseBody) {
super(message, 404, requestId, responseBody);
resource;
constructor(message = "Recurso nao encontrado", resource, requestId) {
super(message, 404, requestId);
this.name = "NotFoundError";
this.resource = resource;
Object.setPrototypeOf(this, _NotFoundError.prototype);
}
toJSON() {
return {
...super.toJSON(),
resource: this.resource
};
}
};
var RateLimitError = class _RateLimitError extends IPTUAPIError {
retryAfter;
limit;
remaining;
constructor(message = "Limite de requisi\xE7\xF5es excedido", retryAfter, limit, remaining, requestId, responseBody) {
super(message, 429, requestId, responseBody);
constructor(message = "Rate limit excedido", retryAfter = 60, requestId) {
super(message, 429, requestId);
this.name = "RateLimitError";
this.retryAfter = retryAfter;
this.limit = limit;
this.remaining = remaining;
Object.setPrototypeOf(this, _RateLimitError.prototype);
}
get isRetryable() {
isRetryable() {
return true;
}
toJSON() {
return {
...super.toJSON(),
retryAfter: this.retryAfter
};
}
};
var ValidationError = class _ValidationError extends IPTUAPIError {
errors;
constructor(message = "Par\xE2metros inv\xE1lidos", errors, requestId, responseBody) {
super(message, 400, requestId, responseBody);
constructor(message = "Parametros invalidos", errors, statusCode = 422, requestId) {
super(message, statusCode, requestId);
this.name = "ValidationError";
this.errors = errors;
this.errors = errors || {};
Object.setPrototypeOf(this, _ValidationError.prototype);
}
toJSON() {
return {
...super.toJSON(),
validationErrors: this.errors
};
}
};
var ServerError = class _ServerError extends IPTUAPIError {
constructor(message = "Erro interno do servidor", statusCode = 500, requestId, responseBody) {
super(message, statusCode, requestId, responseBody);
constructor(message = "Erro interno do servidor", statusCode = 500, requestId) {
super(message, statusCode, requestId);
this.name = "ServerError";
Object.setPrototypeOf(this, _ServerError.prototype);
}
get isRetryable() {
isRetryable() {
return true;

@@ -122,17 +148,23 @@ }

var TimeoutError = class _TimeoutError extends IPTUAPIError {
timeoutMs;
constructor(message = "Timeout na requisi\xE7\xE3o", timeoutMs) {
super(message, 408);
timeoutSeconds;
constructor(message = "Timeout na requisicao", timeoutSeconds, requestId) {
super(message, 408, requestId);
this.name = "TimeoutError";
this.timeoutMs = timeoutMs;
this.timeoutSeconds = timeoutSeconds;
Object.setPrototypeOf(this, _TimeoutError.prototype);
}
get isRetryable() {
isRetryable() {
return true;
}
toJSON() {
return {
...super.toJSON(),
timeoutSeconds: this.timeoutSeconds
};
}
};
var NetworkError = class _NetworkError extends IPTUAPIError {
originalError;
constructor(message = "Erro de conex\xE3o com a API", originalError) {
super(message);
constructor(message = "Erro de conexao", originalError) {
super(message, void 0, void 0);
this.name = "NetworkError";

@@ -142,195 +174,139 @@ this.originalError = originalError;

}
get isRetryable() {
isRetryable() {
return true;
}
};
// src/client.ts
var DEFAULT_RETRY_CONFIG = {
maxRetries: 3,
initialDelay: 500,
maxDelay: 1e4,
initialDelay: 1e3,
maxDelay: 3e4,
backoffFactor: 2,
retryableStatuses: [429, 500, 502, 503, 504]
retryableStatusCodes: [429, 500, 502, 503, 504]
};
var DEFAULT_CONFIG = {
baseUrl: "https://iptuapi.com.br/api/v1",
timeout: 3e4,
retryConfig: DEFAULT_RETRY_CONFIG
};
function toCamelCase(obj) {
const result = {};
for (const [key, value] of Object.entries(obj)) {
const camelKey = key.replace(
/_([a-z])/g,
(_, letter) => letter.toUpperCase()
);
if (value !== null && typeof value === "object" && !Array.isArray(value)) {
result[camelKey] = toCamelCase(value);
} else if (Array.isArray(value)) {
result[camelKey] = value.map(
(item) => typeof item === "object" && item !== null ? toCamelCase(item) : item
);
} else {
result[camelKey] = value;
}
}
return result;
}
function toSnakeCase(obj) {
const result = {};
for (const [key, value] of Object.entries(obj)) {
const snakeKey = key.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
if (value !== null && typeof value === "object" && !Array.isArray(value)) {
result[snakeKey] = toSnakeCase(value);
} else if (Array.isArray(value)) {
result[snakeKey] = value.map(
(item) => typeof item === "object" && item !== null ? toSnakeCase(item) : item
);
} else {
result[snakeKey] = value;
}
}
return result;
}
var IPTUClient = class {
apiKey;
baseUrl;
timeout;
retryConfig;
logger;
logRequests;
logResponses;
userAgent;
_rateLimit;
_lastRequestId;
constructor(apiKey, options = {}) {
if (!apiKey) {
throw new Error("API Key \xE9 obrigat\xF3ria");
}
config;
_rateLimitInfo = null;
_lastRequestId = null;
/**
* Cria uma nova instancia do cliente.
*
* @param apiKey - Chave de API para autenticacao
* @param options - Opcoes de configuracao
*/
constructor(apiKey, options) {
this.apiKey = apiKey;
this.baseUrl = options.baseUrl || "https://iptuapi.com.br/api/v1";
this.timeout = options.timeout || 3e4;
this.retryConfig = { ...DEFAULT_RETRY_CONFIG, ...options.retry };
this.logger = options.logger;
this.logRequests = options.logRequests || false;
this.logResponses = options.logResponses || false;
this.userAgent = options.userAgent || "iptuapi-js/2.0.0";
this.config = {
baseUrl: options?.baseUrl || DEFAULT_CONFIG.baseUrl,
timeout: options?.timeout || DEFAULT_CONFIG.timeout,
retryConfig: {
...DEFAULT_RETRY_CONFIG,
...options?.retryConfig
}
};
}
// ===========================================================================
// Properties
// ===========================================================================
/** Rate limit info from last request */
get rateLimit() {
return this._rateLimit;
/**
* Retorna informacoes do rate limit da ultima requisicao.
*/
get rateLimitInfo() {
return this._rateLimitInfo;
}
/** Request ID from last request (useful for support) */
/**
* Retorna o ID da ultima requisicao.
*/
get lastRequestId() {
return this._lastRequestId;
}
// ===========================================================================
// Private Methods
// ===========================================================================
log(level, message, ...args) {
if (this.logger && this.logger[level]) {
this.logger[level](message, ...args);
}
}
sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
calculateDelay(attempt) {
const delay = this.retryConfig.initialDelay * Math.pow(this.retryConfig.backoffFactor, attempt);
return Math.min(delay, this.retryConfig.maxDelay);
}
extractRateLimit(headers) {
const limit = headers.get("X-RateLimit-Limit");
const remaining = headers.get("X-RateLimit-Remaining");
const reset = headers.get("X-RateLimit-Reset");
if (limit && remaining && reset) {
const resetTimestamp = parseInt(reset, 10);
return {
limit: parseInt(limit, 10),
remaining: parseInt(remaining, 10),
reset: resetTimestamp,
resetDate: new Date(resetTimestamp * 1e3)
};
}
return void 0;
}
async handleErrorResponse(response, requestId) {
let body = {};
try {
body = await response.json();
} catch {
body = { detail: response.statusText };
}
let message;
const detail = body.detail;
if (detail && typeof detail === "object") {
const detailObj = detail;
message = detailObj.error || detailObj.detail || detailObj.message || JSON.stringify(detail);
} else {
message = detail || `HTTP ${response.status}`;
}
switch (response.status) {
case 400:
case 422:
throw new ValidationError(
message,
body.errors,
requestId,
body
);
case 401:
throw new AuthenticationError(message, requestId, body);
case 403:
throw new ForbiddenError(
message,
body.required_plan,
requestId,
body
);
case 404:
throw new NotFoundError(message, requestId, body);
case 429:
const retryAfter = response.headers.get("Retry-After");
throw new RateLimitError(
message,
retryAfter ? parseInt(retryAfter, 10) : void 0,
this._rateLimit?.limit,
this._rateLimit?.remaining,
requestId,
body
);
case 500:
case 502:
case 503:
case 504:
throw new ServerError(message, response.status, requestId, body);
default:
throw new IPTUAPIError(message, response.status, requestId, body);
}
}
async request(method, endpoint, params, body) {
const url = new URL(`${this.baseUrl}${endpoint}`);
/**
* Executa uma requisicao HTTP com retry.
*/
async makeRequest(method, endpoint, params, body) {
const url = new URL(`${this.config.baseUrl}/${endpoint.replace(/^\//, "")}`);
if (params) {
Object.entries(params).forEach(([key, value]) => {
if (value !== void 0 && value !== null && value !== "") {
for (const [key, value] of Object.entries(params)) {
if (value !== void 0 && value !== null) {
url.searchParams.append(key, String(value));
}
});
}
}
const headers = {
"X-API-Key": this.apiKey,
"Content-Type": "application/json",
Accept: "application/json",
"User-Agent": this.userAgent
};
let lastError;
let attempt = 0;
while (attempt <= this.retryConfig.maxRetries) {
const { maxRetries, initialDelay, maxDelay, backoffFactor } = this.config.retryConfig;
let delay = initialDelay;
for (let attempt = 0; attempt <= maxRetries; attempt++) {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
const timeoutId = setTimeout(
() => controller.abort(),
this.config.timeout
);
try {
if (this.logRequests) {
this.log(
"debug",
`Request: ${method} ${url}`,
params ? { params } : {},
body ? { body } : {}
);
}
const startTime = Date.now();
const response = await fetch(url.toString(), {
method,
headers,
body: body ? JSON.stringify(body) : void 0,
headers: {
"X-API-Key": this.apiKey,
"Content-Type": "application/json",
Accept: "application/json",
"User-Agent": "iptuapi-js/1.0.0"
},
body: body ? JSON.stringify(toSnakeCase(body)) : void 0,
signal: controller.signal
});
clearTimeout(timeoutId);
const elapsedMs = Date.now() - startTime;
this._rateLimit = this.extractRateLimit(response.headers);
this._lastRequestId = response.headers.get("X-Request-ID") || void 0;
if (this.logResponses) {
this.log(
"debug",
`Response: ${response.status} ${url} (${elapsedMs}ms)`
);
this.updateRateLimitInfo(response.headers);
this._lastRequestId = response.headers.get("X-Request-ID");
if (!response.ok) {
await this.handleError(response);
}
if (response.ok) {
return await response.json();
}
if (this.retryConfig.retryableStatuses.includes(response.status) && attempt < this.retryConfig.maxRetries) {
const delay = this.calculateDelay(attempt);
this.log(
"warn",
`Request failed with ${response.status}, retrying in ${delay}ms (attempt ${attempt + 1}/${this.retryConfig.maxRetries})`
);
await this.sleep(delay);
attempt++;
continue;
}
await this.handleErrorResponse(response, this._lastRequestId);
const data = await response.json();
return toCamelCase(data.data || data);
} catch (error) {
clearTimeout(timeoutId);
if (error instanceof IPTUAPIError) {
if (error.isRetryable() && attempt < maxRetries && this.config.retryConfig.retryableStatusCodes.includes(
error.statusCode || 0
)) {
await this.sleep(delay);
delay = Math.min(delay * backoffFactor, maxDelay);
continue;
}
throw error;

@@ -340,84 +316,140 @@ }

if (error.name === "AbortError") {
lastError = new TimeoutError(
`Timeout ap\xF3s ${this.timeout}ms`,
this.timeout
if (attempt < maxRetries) {
await this.sleep(delay);
delay = Math.min(delay * backoffFactor, maxDelay);
continue;
}
throw new TimeoutError(
`Timeout apos ${this.config.timeout}ms`,
this.config.timeout / 1e3
);
} else if (error.message.includes("fetch") || error.message.includes("network")) {
lastError = new NetworkError(
`Erro de conex\xE3o: ${error.message}`,
error
);
} else {
lastError = error;
}
if (attempt < this.retryConfig.maxRetries) {
const delay = this.calculateDelay(attempt);
this.log(
"warn",
`Request failed: ${error.message}, retrying in ${delay}ms (attempt ${attempt + 1}/${this.retryConfig.maxRetries})`
);
if (attempt < maxRetries) {
await this.sleep(delay);
attempt++;
delay = Math.min(delay * backoffFactor, maxDelay);
continue;
}
throw new NetworkError(`Erro de conexao: ${error.message}`, error);
}
throw lastError || error;
throw new NetworkError("Erro desconhecido");
}
}
throw lastError || new IPTUAPIError("Max retries exceeded");
throw new NetworkError("Maximo de tentativas excedido");
}
async consultaEndereco(paramsOrLogradouro, numero, cidade) {
let params;
if (typeof paramsOrLogradouro === "string") {
params = {
logradouro: paramsOrLogradouro,
numero,
cidade: cidade || "sp"
/**
* Atualiza informacoes de rate limit a partir dos headers.
*/
updateRateLimitInfo(headers) {
const limit = headers.get("X-RateLimit-Limit");
const remaining = headers.get("X-RateLimit-Remaining");
const reset = headers.get("X-RateLimit-Reset");
if (limit && remaining && reset) {
this._rateLimitInfo = {
limit: parseInt(limit, 10),
remaining: parseInt(remaining, 10),
resetAt: new Date(parseInt(reset, 10) * 1e3)
};
} else {
params = {
logradouro: paramsOrLogradouro.logradouro,
numero: paramsOrLogradouro.numero,
complemento: paramsOrLogradouro.complemento,
cidade: paramsOrLogradouro.cidade || "sp",
incluir_historico: paramsOrLogradouro.incluirHistorico,
incluir_comparaveis: paramsOrLogradouro.incluirComparaveis,
incluir_zoneamento: paramsOrLogradouro.incluirZoneamento
};
}
return this.request(
"GET",
"/consulta/endereco",
params
);
}
/**
* Busca dados de IPTU por número SQL (contribuinte).
* Converte resposta HTTP em excecao apropriada.
*/
async handleError(response) {
const requestId = response.headers.get("X-Request-ID") || void 0;
let data = {};
let message = "Erro desconhecido";
try {
data = await response.json();
message = data.detail || data.message || message;
} catch {
message = response.statusText || message;
}
switch (response.status) {
case 401:
throw new AuthenticationError(message, requestId);
case 403:
throw new ForbiddenError(
message,
data.required_plan,
requestId
);
case 404:
throw new NotFoundError(
message,
data.resource,
requestId
);
case 429: {
const retryAfter = parseInt(
response.headers.get("Retry-After") || "60",
10
);
throw new RateLimitError(message, retryAfter, requestId);
}
case 400:
case 422:
throw new ValidationError(
message,
data.errors,
response.status,
requestId
);
default:
if (response.status >= 500) {
throw new ServerError(message, response.status, requestId);
}
throw new IPTUAPIError(message, response.status, requestId, data);
}
}
/**
* Aguarda um tempo em milissegundos.
*/
sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
// ==================== CONSULTAS IPTU ====================
/**
* Consulta imoveis por endereco.
*
* @param sql - Número SQL do imóvel
* @param cidade - Cidade da consulta
* @param options - Opções adicionais
* @returns Dados completos do imóvel
* @param logradouro - Nome da rua/avenida
* @param numero - Numero do imovel
* @param cidade - Codigo da cidade (sp, bh, recife)
* @returns Lista de imoveis encontrados
*/
async consultaSQL(sql, cidade = "sp", options) {
return this.request("GET", `/consulta/sql/${sql}`, {
cidade,
incluir_historico: options?.incluirHistorico,
incluir_comparaveis: options?.incluirComparaveis
async consultaEndereco(logradouro, numero, cidade = "sp") {
const response = await this.makeRequest("GET", "/consulta/endereco", {
logradouro,
numero,
cidade
});
return Array.isArray(response) ? response : [];
}
/**
* Busca imóveis por CEP.
* Consulta imovel por numero SQL/Indice Cadastral.
* Requer plano Starter ou superior.
*
* @param cep - CEP do imóvel
* @param cidade - Cidade da consulta
* @returns Lista de imóveis no CEP
* @param sql - Numero SQL (SP), Indice Cadastral (BH) ou Sequencial (Recife)
* @param cidade - Codigo da cidade (sp, bh, recife)
* @returns Lista de imoveis encontrados
*/
async consultaSQL(sql, cidade = "sp") {
const response = await this.makeRequest("GET", "/consulta/sql", {
sql,
cidade
});
return Array.isArray(response) ? response : [];
}
/**
* Consulta imoveis por CEP.
*
* @param cep - CEP do endereco
* @param cidade - Codigo da cidade (sp, bh, recife)
* @returns Lista de imoveis encontrados
*/
async consultaCEP(cep, cidade = "sp") {
const cleanCep = cep.replace(/\D/g, "");
return this.request(
"GET",
`/consulta/cep/${cleanCep}`,
{ cidade }
);
const response = await this.makeRequest("GET", "/consulta/cep", {
cep,
cidade
});
return Array.isArray(response) ? response : [];
}

@@ -429,127 +461,193 @@ /**

* @param longitude - Longitude do ponto
* @returns Dados de zoneamento
* @returns Informacoes de zoneamento
*/
async consultaZoneamento(latitude, longitude) {
return this.request("GET", "/consulta/zoneamento", {
latitude,
longitude
return this.makeRequest("GET", "/consulta/zoneamento", {
lat: latitude,
lng: longitude
});
}
// ===========================================================================
// Valuation Endpoints (Pro+)
// ===========================================================================
// ==================== VALUATION ====================
/**
* Estima o valor de mercado do imóvel usando ML.
* Disponível apenas para planos Pro e Enterprise.
* Calcula estimativa de valor de mercado.
* Requer plano Pro ou superior.
*
* @param params - Parâmetros do imóvel
* @returns Estimativa de valor
* @throws {ForbiddenError} Se o plano não permitir
* @param params - Parametros da avaliacao
* @returns Avaliacao de mercado
*/
async valuationEstimate(params) {
return this.request(
"POST",
"/valuation/estimate",
void 0,
return this.makeRequest("GET", "/valuation/estimate", {
area_terreno: params.areaTerreno,
area_construida: params.areaConstruida,
bairro: params.bairro,
cidade: params.cidade || "sp",
zona: params.zona,
tipo_uso: params.tipoUso,
tipo_padrao: params.tipoPadrao,
ano_construcao: params.anoConstrucao
});
}
/**
* Busca imoveis comparaveis.
* Requer plano Pro ou superior.
*
* @param params - Parametros da busca
* @returns Lista de imoveis comparaveis
*/
async valuationComparables(params) {
const response = await this.makeRequest(
"GET",
"/valuation/comparables",
{
area_terreno: params.area_terreno,
area_construida: params.area_construida,
bairro: params.bairro,
zona: params.zona,
tipo_uso: params.tipo_uso,
tipo_padrao: params.tipo_padrao,
ano_construcao: params.ano_construcao,
cidade: params.cidade || "sp"
area_min: params.areaMin,
area_max: params.areaMax,
cidade: params.cidade || "sp",
limit: params.limit || 10
}
);
return Array.isArray(response) ? response : [];
}
/**
* Valuation em lote (até 100 imóveis).
* Disponível apenas para plano Enterprise.
* Avalia imovel por endereco OU SQL.
* Combina dados do modelo AVM (ML) com transacoes ITBI reais.
* Requer plano Pro ou superior.
*
* @param imoveis - Lista de imóveis para avaliar
* @returns Resultados de valuation para cada imóvel
* @param params - Parametros da avaliacao (sql OU logradouro+numero)
* @returns Avaliacao completa do imovel
*/
async valuationBatch(imoveis) {
return this.request(
async valuationEvaluate(params) {
const body = {
cidade: params.cidade || "sp",
incluirItbi: params.incluirItbi ?? true,
incluirComparaveis: params.incluirComparaveis ?? true
};
if (params.sql) {
body.sql = params.sql;
} else {
if (params.logradouro) body.logradouro = params.logradouro;
if (params.numero !== void 0) body.numero = params.numero;
if (params.complemento) body.complemento = params.complemento;
if (params.bairro) body.bairro = params.bairro;
}
return this.makeRequest(
"POST",
"/valuation/estimate/batch",
"/valuation/evaluate",
void 0,
{ imoveis }
body
);
}
// ==================== ITBI ====================
/**
* Busca imóveis comparáveis para análise.
* Consulta status de transacao ITBI.
*
* @param bairro - Nome do bairro
* @param areaMin - Área mínima em m²
* @param areaMax - Área máxima em m²
* @param options - Opções adicionais
* @returns Lista de imóveis comparáveis
* @param protocolo - Numero do protocolo ITBI
* @param cidade - Codigo da cidade (sp, bh, recife)
* @returns Status da transacao
*/
async valuationComparables(bairro, areaMin, areaMax, options) {
return this.request("GET", "/valuation/comparables", {
bairro,
area_min: areaMin,
area_max: areaMax,
tipo_uso: options?.tipoUso,
cidade: options?.cidade || "sp",
limit: options?.limit || 10
async itbiStatus(protocolo, cidade = "sp") {
return this.makeRequest("GET", "/itbi/status", {
protocolo,
cidade
});
}
// ===========================================================================
// Dados Endpoints
// ===========================================================================
/**
* Histórico de valores IPTU de um imóvel.
* Calcula valor do ITBI.
*
* @param sql - Número SQL do imóvel
* @param cidade - Cidade da consulta
* @returns Lista com histórico anual
* @param params - Parametros do calculo
* @returns Calculo do ITBI
*/
async dadosIPTUHistorico(sql, cidade = "sp") {
return this.request(
"GET",
`/dados/iptu/historico/${sql}`,
{ cidade }
);
async itbiCalcular(params) {
return this.makeRequest("POST", "/itbi/calcular", void 0, {
sql: params.sql,
valorTransacao: params.valorTransacao,
cidade: params.cidade || "sp"
});
}
/**
* Consulta dados de empresa por CNPJ.
* Consulta historico de transacoes ITBI de um imovel.
* Requer plano Starter ou superior.
*
* @param cnpj - CNPJ da empresa
* @returns Dados cadastrais
* @param sql - Numero SQL do imovel
* @param cidade - Codigo da cidade (sp, bh, recife)
* @returns Lista de transacoes historicas
*/
async dadosCNPJ(cnpj) {
const cleanCnpj = cnpj.replace(/\D/g, "");
return this.request(
async itbiHistorico(sql, cidade = "sp") {
const response = await this.makeRequest(
"GET",
`/dados/cnpj/${cleanCnpj}`
"/itbi/historico",
{ sql, cidade }
);
return Array.isArray(response) ? response : [];
}
/**
* Correção monetária pelo IPCA.
* Consulta aliquotas ITBI vigentes.
*
* @param valor - Valor a corrigir
* @param dataOrigem - Data do valor original (YYYY-MM)
* @param dataDestino - Data destino (default: atual)
* @returns Valor corrigido e fator de correção
* @param cidade - Codigo da cidade (sp, bh, recife)
* @returns Aliquotas vigentes
*/
async dadosIPCACorrigir(valor, dataOrigem, dataDestino) {
return this.request(
async itbiAliquotas(cidade = "sp") {
return this.makeRequest("GET", "/itbi/aliquotas", { cidade });
}
/**
* Consulta isencoes ITBI disponiveis.
*
* @param cidade - Codigo da cidade (sp, bh, recife)
* @returns Lista de isencoes disponiveis
*/
async itbiIsencoes(cidade = "sp") {
const response = await this.makeRequest(
"GET",
"/dados/ipca/corrigir",
{
valor,
data_origem: dataOrigem,
data_destino: dataDestino
}
"/itbi/isencoes",
{ cidade }
);
return Array.isArray(response) ? response : [];
}
/**
* Gera guia de pagamento ITBI.
* Requer plano Starter ou superior.
*
* @param params - Parametros da guia
* @returns Guia de pagamento gerada
*/
async itbiGuia(params) {
return this.makeRequest("POST", "/itbi/guia", void 0, {
sql: params.sql,
valorTransacao: params.valorTransacao,
comprador: params.comprador,
vendedor: params.vendedor,
cidade: params.cidade || "sp"
});
}
/**
* Valida autenticidade de uma guia ITBI.
*
* @param protocolo - Numero do protocolo da guia
* @param cidade - Codigo da cidade (sp, bh, recife)
* @returns Resultado da validacao
*/
async itbiValidarGuia(protocolo, cidade = "sp") {
return this.makeRequest("GET", "/itbi/validar", {
protocolo,
cidade
});
}
/**
* Simula calculo de ITBI.
*
* @param params - Parametros da simulacao
* @returns Resultado da simulacao
*/
async itbiSimular(params) {
return this.makeRequest("POST", "/itbi/simular", void 0, {
valorTransacao: params.valorTransacao,
cidade: params.cidade || "sp",
tipoFinanciamento: params.tipoFinanciamento,
valorFinanciado: params.valorFinanciado
});
}
};
var index_default = IPTUClient;
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
AuthenticationError,
CidadeEnum,
ForbiddenError,

@@ -556,0 +654,0 @@ IPTUAPIError,

@@ -1,12 +0,7 @@

// src/index.ts
var CidadeEnum = {
SAO_PAULO: "sp",
BELO_HORIZONTE: "bh",
RECIFE: "recife"
};
// src/errors.ts
var IPTUAPIError = class _IPTUAPIError extends Error {
statusCode;
requestId;
responseBody;
constructor(message, statusCode, requestId, responseBody) {
responseData;
constructor(message, statusCode, requestId, responseData) {
super(message);

@@ -16,12 +11,21 @@ this.name = "IPTUAPIError";

this.requestId = requestId;
this.responseBody = responseBody;
this.responseData = responseData || {};
Object.setPrototypeOf(this, _IPTUAPIError.prototype);
}
get isRetryable() {
return this.statusCode ? [429, 500, 502, 503, 504].includes(this.statusCode) : false;
isRetryable() {
return false;
}
toJSON() {
return {
error: this.name,
message: this.message,
statusCode: this.statusCode,
requestId: this.requestId,
retryable: this.isRetryable()
};
}
};
var AuthenticationError = class _AuthenticationError extends IPTUAPIError {
constructor(message = "API Key inv\xE1lida ou expirada", requestId, responseBody) {
super(message, 401, requestId, responseBody);
constructor(message = "API Key invalida ou ausente", requestId) {
super(message, 401, requestId);
this.name = "AuthenticationError";

@@ -33,4 +37,4 @@ Object.setPrototypeOf(this, _AuthenticationError.prototype);

requiredPlan;
constructor(message = "Plano n\xE3o autorizado para este recurso", requiredPlan, requestId, responseBody) {
super(message, 403, requestId, responseBody);
constructor(message = "Acesso negado", requiredPlan, requestId) {
super(message, 403, requestId);
this.name = "ForbiddenError";

@@ -40,42 +44,64 @@ this.requiredPlan = requiredPlan;

}
toJSON() {
return {
...super.toJSON(),
requiredPlan: this.requiredPlan
};
}
};
var NotFoundError = class _NotFoundError extends IPTUAPIError {
constructor(message = "Recurso n\xE3o encontrado", requestId, responseBody) {
super(message, 404, requestId, responseBody);
resource;
constructor(message = "Recurso nao encontrado", resource, requestId) {
super(message, 404, requestId);
this.name = "NotFoundError";
this.resource = resource;
Object.setPrototypeOf(this, _NotFoundError.prototype);
}
toJSON() {
return {
...super.toJSON(),
resource: this.resource
};
}
};
var RateLimitError = class _RateLimitError extends IPTUAPIError {
retryAfter;
limit;
remaining;
constructor(message = "Limite de requisi\xE7\xF5es excedido", retryAfter, limit, remaining, requestId, responseBody) {
super(message, 429, requestId, responseBody);
constructor(message = "Rate limit excedido", retryAfter = 60, requestId) {
super(message, 429, requestId);
this.name = "RateLimitError";
this.retryAfter = retryAfter;
this.limit = limit;
this.remaining = remaining;
Object.setPrototypeOf(this, _RateLimitError.prototype);
}
get isRetryable() {
isRetryable() {
return true;
}
toJSON() {
return {
...super.toJSON(),
retryAfter: this.retryAfter
};
}
};
var ValidationError = class _ValidationError extends IPTUAPIError {
errors;
constructor(message = "Par\xE2metros inv\xE1lidos", errors, requestId, responseBody) {
super(message, 400, requestId, responseBody);
constructor(message = "Parametros invalidos", errors, statusCode = 422, requestId) {
super(message, statusCode, requestId);
this.name = "ValidationError";
this.errors = errors;
this.errors = errors || {};
Object.setPrototypeOf(this, _ValidationError.prototype);
}
toJSON() {
return {
...super.toJSON(),
validationErrors: this.errors
};
}
};
var ServerError = class _ServerError extends IPTUAPIError {
constructor(message = "Erro interno do servidor", statusCode = 500, requestId, responseBody) {
super(message, statusCode, requestId, responseBody);
constructor(message = "Erro interno do servidor", statusCode = 500, requestId) {
super(message, statusCode, requestId);
this.name = "ServerError";
Object.setPrototypeOf(this, _ServerError.prototype);
}
get isRetryable() {
isRetryable() {
return true;

@@ -85,17 +111,23 @@ }

var TimeoutError = class _TimeoutError extends IPTUAPIError {
timeoutMs;
constructor(message = "Timeout na requisi\xE7\xE3o", timeoutMs) {
super(message, 408);
timeoutSeconds;
constructor(message = "Timeout na requisicao", timeoutSeconds, requestId) {
super(message, 408, requestId);
this.name = "TimeoutError";
this.timeoutMs = timeoutMs;
this.timeoutSeconds = timeoutSeconds;
Object.setPrototypeOf(this, _TimeoutError.prototype);
}
get isRetryable() {
isRetryable() {
return true;
}
toJSON() {
return {
...super.toJSON(),
timeoutSeconds: this.timeoutSeconds
};
}
};
var NetworkError = class _NetworkError extends IPTUAPIError {
originalError;
constructor(message = "Erro de conex\xE3o com a API", originalError) {
super(message);
constructor(message = "Erro de conexao", originalError) {
super(message, void 0, void 0);
this.name = "NetworkError";

@@ -105,195 +137,139 @@ this.originalError = originalError;

}
get isRetryable() {
isRetryable() {
return true;
}
};
// src/client.ts
var DEFAULT_RETRY_CONFIG = {
maxRetries: 3,
initialDelay: 500,
maxDelay: 1e4,
initialDelay: 1e3,
maxDelay: 3e4,
backoffFactor: 2,
retryableStatuses: [429, 500, 502, 503, 504]
retryableStatusCodes: [429, 500, 502, 503, 504]
};
var DEFAULT_CONFIG = {
baseUrl: "https://iptuapi.com.br/api/v1",
timeout: 3e4,
retryConfig: DEFAULT_RETRY_CONFIG
};
function toCamelCase(obj) {
const result = {};
for (const [key, value] of Object.entries(obj)) {
const camelKey = key.replace(
/_([a-z])/g,
(_, letter) => letter.toUpperCase()
);
if (value !== null && typeof value === "object" && !Array.isArray(value)) {
result[camelKey] = toCamelCase(value);
} else if (Array.isArray(value)) {
result[camelKey] = value.map(
(item) => typeof item === "object" && item !== null ? toCamelCase(item) : item
);
} else {
result[camelKey] = value;
}
}
return result;
}
function toSnakeCase(obj) {
const result = {};
for (const [key, value] of Object.entries(obj)) {
const snakeKey = key.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
if (value !== null && typeof value === "object" && !Array.isArray(value)) {
result[snakeKey] = toSnakeCase(value);
} else if (Array.isArray(value)) {
result[snakeKey] = value.map(
(item) => typeof item === "object" && item !== null ? toSnakeCase(item) : item
);
} else {
result[snakeKey] = value;
}
}
return result;
}
var IPTUClient = class {
apiKey;
baseUrl;
timeout;
retryConfig;
logger;
logRequests;
logResponses;
userAgent;
_rateLimit;
_lastRequestId;
constructor(apiKey, options = {}) {
if (!apiKey) {
throw new Error("API Key \xE9 obrigat\xF3ria");
}
config;
_rateLimitInfo = null;
_lastRequestId = null;
/**
* Cria uma nova instancia do cliente.
*
* @param apiKey - Chave de API para autenticacao
* @param options - Opcoes de configuracao
*/
constructor(apiKey, options) {
this.apiKey = apiKey;
this.baseUrl = options.baseUrl || "https://iptuapi.com.br/api/v1";
this.timeout = options.timeout || 3e4;
this.retryConfig = { ...DEFAULT_RETRY_CONFIG, ...options.retry };
this.logger = options.logger;
this.logRequests = options.logRequests || false;
this.logResponses = options.logResponses || false;
this.userAgent = options.userAgent || "iptuapi-js/2.0.0";
this.config = {
baseUrl: options?.baseUrl || DEFAULT_CONFIG.baseUrl,
timeout: options?.timeout || DEFAULT_CONFIG.timeout,
retryConfig: {
...DEFAULT_RETRY_CONFIG,
...options?.retryConfig
}
};
}
// ===========================================================================
// Properties
// ===========================================================================
/** Rate limit info from last request */
get rateLimit() {
return this._rateLimit;
/**
* Retorna informacoes do rate limit da ultima requisicao.
*/
get rateLimitInfo() {
return this._rateLimitInfo;
}
/** Request ID from last request (useful for support) */
/**
* Retorna o ID da ultima requisicao.
*/
get lastRequestId() {
return this._lastRequestId;
}
// ===========================================================================
// Private Methods
// ===========================================================================
log(level, message, ...args) {
if (this.logger && this.logger[level]) {
this.logger[level](message, ...args);
}
}
sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
calculateDelay(attempt) {
const delay = this.retryConfig.initialDelay * Math.pow(this.retryConfig.backoffFactor, attempt);
return Math.min(delay, this.retryConfig.maxDelay);
}
extractRateLimit(headers) {
const limit = headers.get("X-RateLimit-Limit");
const remaining = headers.get("X-RateLimit-Remaining");
const reset = headers.get("X-RateLimit-Reset");
if (limit && remaining && reset) {
const resetTimestamp = parseInt(reset, 10);
return {
limit: parseInt(limit, 10),
remaining: parseInt(remaining, 10),
reset: resetTimestamp,
resetDate: new Date(resetTimestamp * 1e3)
};
}
return void 0;
}
async handleErrorResponse(response, requestId) {
let body = {};
try {
body = await response.json();
} catch {
body = { detail: response.statusText };
}
let message;
const detail = body.detail;
if (detail && typeof detail === "object") {
const detailObj = detail;
message = detailObj.error || detailObj.detail || detailObj.message || JSON.stringify(detail);
} else {
message = detail || `HTTP ${response.status}`;
}
switch (response.status) {
case 400:
case 422:
throw new ValidationError(
message,
body.errors,
requestId,
body
);
case 401:
throw new AuthenticationError(message, requestId, body);
case 403:
throw new ForbiddenError(
message,
body.required_plan,
requestId,
body
);
case 404:
throw new NotFoundError(message, requestId, body);
case 429:
const retryAfter = response.headers.get("Retry-After");
throw new RateLimitError(
message,
retryAfter ? parseInt(retryAfter, 10) : void 0,
this._rateLimit?.limit,
this._rateLimit?.remaining,
requestId,
body
);
case 500:
case 502:
case 503:
case 504:
throw new ServerError(message, response.status, requestId, body);
default:
throw new IPTUAPIError(message, response.status, requestId, body);
}
}
async request(method, endpoint, params, body) {
const url = new URL(`${this.baseUrl}${endpoint}`);
/**
* Executa uma requisicao HTTP com retry.
*/
async makeRequest(method, endpoint, params, body) {
const url = new URL(`${this.config.baseUrl}/${endpoint.replace(/^\//, "")}`);
if (params) {
Object.entries(params).forEach(([key, value]) => {
if (value !== void 0 && value !== null && value !== "") {
for (const [key, value] of Object.entries(params)) {
if (value !== void 0 && value !== null) {
url.searchParams.append(key, String(value));
}
});
}
}
const headers = {
"X-API-Key": this.apiKey,
"Content-Type": "application/json",
Accept: "application/json",
"User-Agent": this.userAgent
};
let lastError;
let attempt = 0;
while (attempt <= this.retryConfig.maxRetries) {
const { maxRetries, initialDelay, maxDelay, backoffFactor } = this.config.retryConfig;
let delay = initialDelay;
for (let attempt = 0; attempt <= maxRetries; attempt++) {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
const timeoutId = setTimeout(
() => controller.abort(),
this.config.timeout
);
try {
if (this.logRequests) {
this.log(
"debug",
`Request: ${method} ${url}`,
params ? { params } : {},
body ? { body } : {}
);
}
const startTime = Date.now();
const response = await fetch(url.toString(), {
method,
headers,
body: body ? JSON.stringify(body) : void 0,
headers: {
"X-API-Key": this.apiKey,
"Content-Type": "application/json",
Accept: "application/json",
"User-Agent": "iptuapi-js/1.0.0"
},
body: body ? JSON.stringify(toSnakeCase(body)) : void 0,
signal: controller.signal
});
clearTimeout(timeoutId);
const elapsedMs = Date.now() - startTime;
this._rateLimit = this.extractRateLimit(response.headers);
this._lastRequestId = response.headers.get("X-Request-ID") || void 0;
if (this.logResponses) {
this.log(
"debug",
`Response: ${response.status} ${url} (${elapsedMs}ms)`
);
this.updateRateLimitInfo(response.headers);
this._lastRequestId = response.headers.get("X-Request-ID");
if (!response.ok) {
await this.handleError(response);
}
if (response.ok) {
return await response.json();
}
if (this.retryConfig.retryableStatuses.includes(response.status) && attempt < this.retryConfig.maxRetries) {
const delay = this.calculateDelay(attempt);
this.log(
"warn",
`Request failed with ${response.status}, retrying in ${delay}ms (attempt ${attempt + 1}/${this.retryConfig.maxRetries})`
);
await this.sleep(delay);
attempt++;
continue;
}
await this.handleErrorResponse(response, this._lastRequestId);
const data = await response.json();
return toCamelCase(data.data || data);
} catch (error) {
clearTimeout(timeoutId);
if (error instanceof IPTUAPIError) {
if (error.isRetryable() && attempt < maxRetries && this.config.retryConfig.retryableStatusCodes.includes(
error.statusCode || 0
)) {
await this.sleep(delay);
delay = Math.min(delay * backoffFactor, maxDelay);
continue;
}
throw error;

@@ -303,84 +279,140 @@ }

if (error.name === "AbortError") {
lastError = new TimeoutError(
`Timeout ap\xF3s ${this.timeout}ms`,
this.timeout
if (attempt < maxRetries) {
await this.sleep(delay);
delay = Math.min(delay * backoffFactor, maxDelay);
continue;
}
throw new TimeoutError(
`Timeout apos ${this.config.timeout}ms`,
this.config.timeout / 1e3
);
} else if (error.message.includes("fetch") || error.message.includes("network")) {
lastError = new NetworkError(
`Erro de conex\xE3o: ${error.message}`,
error
);
} else {
lastError = error;
}
if (attempt < this.retryConfig.maxRetries) {
const delay = this.calculateDelay(attempt);
this.log(
"warn",
`Request failed: ${error.message}, retrying in ${delay}ms (attempt ${attempt + 1}/${this.retryConfig.maxRetries})`
);
if (attempt < maxRetries) {
await this.sleep(delay);
attempt++;
delay = Math.min(delay * backoffFactor, maxDelay);
continue;
}
throw new NetworkError(`Erro de conexao: ${error.message}`, error);
}
throw lastError || error;
throw new NetworkError("Erro desconhecido");
}
}
throw lastError || new IPTUAPIError("Max retries exceeded");
throw new NetworkError("Maximo de tentativas excedido");
}
async consultaEndereco(paramsOrLogradouro, numero, cidade) {
let params;
if (typeof paramsOrLogradouro === "string") {
params = {
logradouro: paramsOrLogradouro,
numero,
cidade: cidade || "sp"
/**
* Atualiza informacoes de rate limit a partir dos headers.
*/
updateRateLimitInfo(headers) {
const limit = headers.get("X-RateLimit-Limit");
const remaining = headers.get("X-RateLimit-Remaining");
const reset = headers.get("X-RateLimit-Reset");
if (limit && remaining && reset) {
this._rateLimitInfo = {
limit: parseInt(limit, 10),
remaining: parseInt(remaining, 10),
resetAt: new Date(parseInt(reset, 10) * 1e3)
};
} else {
params = {
logradouro: paramsOrLogradouro.logradouro,
numero: paramsOrLogradouro.numero,
complemento: paramsOrLogradouro.complemento,
cidade: paramsOrLogradouro.cidade || "sp",
incluir_historico: paramsOrLogradouro.incluirHistorico,
incluir_comparaveis: paramsOrLogradouro.incluirComparaveis,
incluir_zoneamento: paramsOrLogradouro.incluirZoneamento
};
}
return this.request(
"GET",
"/consulta/endereco",
params
);
}
/**
* Busca dados de IPTU por número SQL (contribuinte).
* Converte resposta HTTP em excecao apropriada.
*/
async handleError(response) {
const requestId = response.headers.get("X-Request-ID") || void 0;
let data = {};
let message = "Erro desconhecido";
try {
data = await response.json();
message = data.detail || data.message || message;
} catch {
message = response.statusText || message;
}
switch (response.status) {
case 401:
throw new AuthenticationError(message, requestId);
case 403:
throw new ForbiddenError(
message,
data.required_plan,
requestId
);
case 404:
throw new NotFoundError(
message,
data.resource,
requestId
);
case 429: {
const retryAfter = parseInt(
response.headers.get("Retry-After") || "60",
10
);
throw new RateLimitError(message, retryAfter, requestId);
}
case 400:
case 422:
throw new ValidationError(
message,
data.errors,
response.status,
requestId
);
default:
if (response.status >= 500) {
throw new ServerError(message, response.status, requestId);
}
throw new IPTUAPIError(message, response.status, requestId, data);
}
}
/**
* Aguarda um tempo em milissegundos.
*/
sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
// ==================== CONSULTAS IPTU ====================
/**
* Consulta imoveis por endereco.
*
* @param sql - Número SQL do imóvel
* @param cidade - Cidade da consulta
* @param options - Opções adicionais
* @returns Dados completos do imóvel
* @param logradouro - Nome da rua/avenida
* @param numero - Numero do imovel
* @param cidade - Codigo da cidade (sp, bh, recife)
* @returns Lista de imoveis encontrados
*/
async consultaSQL(sql, cidade = "sp", options) {
return this.request("GET", `/consulta/sql/${sql}`, {
cidade,
incluir_historico: options?.incluirHistorico,
incluir_comparaveis: options?.incluirComparaveis
async consultaEndereco(logradouro, numero, cidade = "sp") {
const response = await this.makeRequest("GET", "/consulta/endereco", {
logradouro,
numero,
cidade
});
return Array.isArray(response) ? response : [];
}
/**
* Busca imóveis por CEP.
* Consulta imovel por numero SQL/Indice Cadastral.
* Requer plano Starter ou superior.
*
* @param cep - CEP do imóvel
* @param cidade - Cidade da consulta
* @returns Lista de imóveis no CEP
* @param sql - Numero SQL (SP), Indice Cadastral (BH) ou Sequencial (Recife)
* @param cidade - Codigo da cidade (sp, bh, recife)
* @returns Lista de imoveis encontrados
*/
async consultaSQL(sql, cidade = "sp") {
const response = await this.makeRequest("GET", "/consulta/sql", {
sql,
cidade
});
return Array.isArray(response) ? response : [];
}
/**
* Consulta imoveis por CEP.
*
* @param cep - CEP do endereco
* @param cidade - Codigo da cidade (sp, bh, recife)
* @returns Lista de imoveis encontrados
*/
async consultaCEP(cep, cidade = "sp") {
const cleanCep = cep.replace(/\D/g, "");
return this.request(
"GET",
`/consulta/cep/${cleanCep}`,
{ cidade }
);
const response = await this.makeRequest("GET", "/consulta/cep", {
cep,
cidade
});
return Array.isArray(response) ? response : [];
}

@@ -392,126 +424,192 @@ /**

* @param longitude - Longitude do ponto
* @returns Dados de zoneamento
* @returns Informacoes de zoneamento
*/
async consultaZoneamento(latitude, longitude) {
return this.request("GET", "/consulta/zoneamento", {
latitude,
longitude
return this.makeRequest("GET", "/consulta/zoneamento", {
lat: latitude,
lng: longitude
});
}
// ===========================================================================
// Valuation Endpoints (Pro+)
// ===========================================================================
// ==================== VALUATION ====================
/**
* Estima o valor de mercado do imóvel usando ML.
* Disponível apenas para planos Pro e Enterprise.
* Calcula estimativa de valor de mercado.
* Requer plano Pro ou superior.
*
* @param params - Parâmetros do imóvel
* @returns Estimativa de valor
* @throws {ForbiddenError} Se o plano não permitir
* @param params - Parametros da avaliacao
* @returns Avaliacao de mercado
*/
async valuationEstimate(params) {
return this.request(
"POST",
"/valuation/estimate",
void 0,
return this.makeRequest("GET", "/valuation/estimate", {
area_terreno: params.areaTerreno,
area_construida: params.areaConstruida,
bairro: params.bairro,
cidade: params.cidade || "sp",
zona: params.zona,
tipo_uso: params.tipoUso,
tipo_padrao: params.tipoPadrao,
ano_construcao: params.anoConstrucao
});
}
/**
* Busca imoveis comparaveis.
* Requer plano Pro ou superior.
*
* @param params - Parametros da busca
* @returns Lista de imoveis comparaveis
*/
async valuationComparables(params) {
const response = await this.makeRequest(
"GET",
"/valuation/comparables",
{
area_terreno: params.area_terreno,
area_construida: params.area_construida,
bairro: params.bairro,
zona: params.zona,
tipo_uso: params.tipo_uso,
tipo_padrao: params.tipo_padrao,
ano_construcao: params.ano_construcao,
cidade: params.cidade || "sp"
area_min: params.areaMin,
area_max: params.areaMax,
cidade: params.cidade || "sp",
limit: params.limit || 10
}
);
return Array.isArray(response) ? response : [];
}
/**
* Valuation em lote (até 100 imóveis).
* Disponível apenas para plano Enterprise.
* Avalia imovel por endereco OU SQL.
* Combina dados do modelo AVM (ML) com transacoes ITBI reais.
* Requer plano Pro ou superior.
*
* @param imoveis - Lista de imóveis para avaliar
* @returns Resultados de valuation para cada imóvel
* @param params - Parametros da avaliacao (sql OU logradouro+numero)
* @returns Avaliacao completa do imovel
*/
async valuationBatch(imoveis) {
return this.request(
async valuationEvaluate(params) {
const body = {
cidade: params.cidade || "sp",
incluirItbi: params.incluirItbi ?? true,
incluirComparaveis: params.incluirComparaveis ?? true
};
if (params.sql) {
body.sql = params.sql;
} else {
if (params.logradouro) body.logradouro = params.logradouro;
if (params.numero !== void 0) body.numero = params.numero;
if (params.complemento) body.complemento = params.complemento;
if (params.bairro) body.bairro = params.bairro;
}
return this.makeRequest(
"POST",
"/valuation/estimate/batch",
"/valuation/evaluate",
void 0,
{ imoveis }
body
);
}
// ==================== ITBI ====================
/**
* Busca imóveis comparáveis para análise.
* Consulta status de transacao ITBI.
*
* @param bairro - Nome do bairro
* @param areaMin - Área mínima em m²
* @param areaMax - Área máxima em m²
* @param options - Opções adicionais
* @returns Lista de imóveis comparáveis
* @param protocolo - Numero do protocolo ITBI
* @param cidade - Codigo da cidade (sp, bh, recife)
* @returns Status da transacao
*/
async valuationComparables(bairro, areaMin, areaMax, options) {
return this.request("GET", "/valuation/comparables", {
bairro,
area_min: areaMin,
area_max: areaMax,
tipo_uso: options?.tipoUso,
cidade: options?.cidade || "sp",
limit: options?.limit || 10
async itbiStatus(protocolo, cidade = "sp") {
return this.makeRequest("GET", "/itbi/status", {
protocolo,
cidade
});
}
// ===========================================================================
// Dados Endpoints
// ===========================================================================
/**
* Histórico de valores IPTU de um imóvel.
* Calcula valor do ITBI.
*
* @param sql - Número SQL do imóvel
* @param cidade - Cidade da consulta
* @returns Lista com histórico anual
* @param params - Parametros do calculo
* @returns Calculo do ITBI
*/
async dadosIPTUHistorico(sql, cidade = "sp") {
return this.request(
"GET",
`/dados/iptu/historico/${sql}`,
{ cidade }
);
async itbiCalcular(params) {
return this.makeRequest("POST", "/itbi/calcular", void 0, {
sql: params.sql,
valorTransacao: params.valorTransacao,
cidade: params.cidade || "sp"
});
}
/**
* Consulta dados de empresa por CNPJ.
* Consulta historico de transacoes ITBI de um imovel.
* Requer plano Starter ou superior.
*
* @param cnpj - CNPJ da empresa
* @returns Dados cadastrais
* @param sql - Numero SQL do imovel
* @param cidade - Codigo da cidade (sp, bh, recife)
* @returns Lista de transacoes historicas
*/
async dadosCNPJ(cnpj) {
const cleanCnpj = cnpj.replace(/\D/g, "");
return this.request(
async itbiHistorico(sql, cidade = "sp") {
const response = await this.makeRequest(
"GET",
`/dados/cnpj/${cleanCnpj}`
"/itbi/historico",
{ sql, cidade }
);
return Array.isArray(response) ? response : [];
}
/**
* Correção monetária pelo IPCA.
* Consulta aliquotas ITBI vigentes.
*
* @param valor - Valor a corrigir
* @param dataOrigem - Data do valor original (YYYY-MM)
* @param dataDestino - Data destino (default: atual)
* @returns Valor corrigido e fator de correção
* @param cidade - Codigo da cidade (sp, bh, recife)
* @returns Aliquotas vigentes
*/
async dadosIPCACorrigir(valor, dataOrigem, dataDestino) {
return this.request(
async itbiAliquotas(cidade = "sp") {
return this.makeRequest("GET", "/itbi/aliquotas", { cidade });
}
/**
* Consulta isencoes ITBI disponiveis.
*
* @param cidade - Codigo da cidade (sp, bh, recife)
* @returns Lista de isencoes disponiveis
*/
async itbiIsencoes(cidade = "sp") {
const response = await this.makeRequest(
"GET",
"/dados/ipca/corrigir",
{
valor,
data_origem: dataOrigem,
data_destino: dataDestino
}
"/itbi/isencoes",
{ cidade }
);
return Array.isArray(response) ? response : [];
}
/**
* Gera guia de pagamento ITBI.
* Requer plano Starter ou superior.
*
* @param params - Parametros da guia
* @returns Guia de pagamento gerada
*/
async itbiGuia(params) {
return this.makeRequest("POST", "/itbi/guia", void 0, {
sql: params.sql,
valorTransacao: params.valorTransacao,
comprador: params.comprador,
vendedor: params.vendedor,
cidade: params.cidade || "sp"
});
}
/**
* Valida autenticidade de uma guia ITBI.
*
* @param protocolo - Numero do protocolo da guia
* @param cidade - Codigo da cidade (sp, bh, recife)
* @returns Resultado da validacao
*/
async itbiValidarGuia(protocolo, cidade = "sp") {
return this.makeRequest("GET", "/itbi/validar", {
protocolo,
cidade
});
}
/**
* Simula calculo de ITBI.
*
* @param params - Parametros da simulacao
* @returns Resultado da simulacao
*/
async itbiSimular(params) {
return this.makeRequest("POST", "/itbi/simular", void 0, {
valorTransacao: params.valorTransacao,
cidade: params.cidade || "sp",
tipoFinanciamento: params.tipoFinanciamento,
valorFinanciado: params.valorFinanciado
});
}
};
var index_default = IPTUClient;
export {
AuthenticationError,
CidadeEnum,
ForbiddenError,

@@ -525,4 +623,3 @@ IPTUAPIError,

TimeoutError,
ValidationError,
index_default as default
ValidationError
};
{
"name": "iptuapi",
"version": "2.0.3",
"description": "SDK oficial para a IPTU API - Dados de IPTU de São Paulo, Belo Horizonte e Recife",
"version": "2.1.0",
"description": "SDK oficial para a IPTU API - Dados de IPTU e ITBI de Sao Paulo, Belo Horizonte e Recife",
"main": "dist/index.js",

@@ -10,17 +10,19 @@ "module": "dist/index.mjs",

".": {
"types": "./dist/index.d.ts",
"require": "./dist/index.js",
"import": "./dist/index.mjs",
"require": "./dist/index.js"
"types": "./dist/index.d.ts"
}
},
"files": [
"dist"
"dist",
"README.md",
"LICENSE"
],
"scripts": {
"build": "tsup src/index.ts --format cjs,esm --dts",
"build": "tsup src/index.ts --format cjs,esm --dts --clean",
"test": "vitest run",
"test:watch": "vitest",
"test:coverage": "vitest run --coverage",
"lint": "eslint src --ext .ts",
"typecheck": "tsc --noEmit",
"lint": "eslint src tests",
"prepublishOnly": "npm run build"

@@ -30,34 +32,34 @@ },

"iptu",
"itbi",
"api",
"são paulo",
"belo horizonte",
"recife",
"imóveis",
"dados",
"real estate",
"property",
"typescript",
"sdk"
"imoveis",
"real-estate",
"brazil",
"sao-paulo",
"belo-horizonte",
"recife"
],
"author": "IPTU API <contato@iptuapi.com.br>",
"license": "UNLICENSED",
"author": "IPTU API <suporte@iptuapi.com.br>",
"license": "SEE LICENSE IN LICENSE",
"repository": {
"type": "git",
"url": "https://github.com/iptuapi/iptuapi-js"
"url": "git+https://github.com/raphaeltorquat0/iptuapi-js.git"
},
"homepage": "https://iptuapi.com.br",
"bugs": {
"url": "https://github.com/iptuapi/iptuapi-js/issues"
"url": "https://github.com/raphaeltorquat0/iptuapi-js/issues"
},
"homepage": "https://iptuapi.com.br",
"engines": {
"node": ">=18.0.0"
},
"devDependencies": {
"@types/node": "^20.10.0",
"@vitest/coverage-v8": "^1.0.0",
"msw": "^2.0.0",
"eslint": "^8.55.0",
"@typescript-eslint/eslint-plugin": "^6.13.0",
"@typescript-eslint/parser": "^6.13.0",
"tsup": "^8.0.0",
"typescript": "^5.3.0",
"vitest": "^1.0.0"
},
"engines": {
"node": ">=18"
"vitest": "^1.0.0",
"@vitest/coverage-v8": "^1.0.0"
}
}
+497
-125
# IPTU API - JavaScript/TypeScript SDK
SDK oficial JavaScript/TypeScript para integracao com a IPTU API. Acesso a dados de IPTU de Sao Paulo, Belo Horizonte e Recife.
SDK oficial para integracao com a IPTU API. Acesso a dados de IPTU e ITBI de Sao Paulo, Belo Horizonte e Recife.
[![npm version](https://badge.fury.io/js/iptuapi.svg)](https://www.npmjs.com/package/iptuapi)
[![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue)](https://www.typescriptlang.org/)
[![npm version](https://img.shields.io/npm/v/iptuapi)](https://www.npmjs.com/package/iptuapi)
[![TypeScript](https://img.shields.io/badge/TypeScript-5.0%2B-blue)](https://www.typescriptlang.org/)
[![License](https://img.shields.io/badge/license-Proprietary-red)](LICENSE)

@@ -13,8 +13,21 @@

npm install iptuapi
# ou
```
ou com yarn:
```bash
yarn add iptuapi
# ou
```
ou com pnpm:
```bash
pnpm add iptuapi
```
## Requisitos
- Node.js 18+
- TypeScript 5.0+ (opcional, para tipagem)
## Uso Rapido

@@ -28,9 +41,20 @@

// Consulta por endereco
const resultado = await client.consultaEndereco('Avenida Paulista', '1000');
console.log(resultado);
const imoveis = await client.consultaEndereco('Avenida Paulista', '1000', 'sp');
for (const imovel of imoveis) {
console.log(`SQL: ${imovel.sql}`);
console.log(`Valor Venal: R$ ${imovel.valorVenal?.toLocaleString('pt-BR')}`);
}
// Consulta por SQL (Starter+)
const dados = await client.consultaSQL('100-01-001-001');
const dados = await client.consultaSQL('008.045.0123-4', 'sp');
```
### CommonJS
```javascript
const { IPTUClient } = require('iptuapi');
const client = new IPTUClient('sua_api_key');
```
## Configuracao

@@ -49,84 +73,153 @@

```typescript
import { IPTUClient, ClientConfig, RetryConfig } from 'iptuapi';
import { IPTUClient } from 'iptuapi';
const retryConfig: RetryConfig = {
maxRetries: 5,
initialDelayMs: 1000,
maxDelayMs: 30000,
backoffFactor: 2.0,
retryableStatuses: [429, 500, 502, 503, 504]
};
const config: ClientConfig = {
const client = new IPTUClient('sua_api_key', {
baseUrl: 'https://iptuapi.com.br/api/v1',
timeout: 60000,
retryConfig,
logger: console // ou seu logger customizado
};
const client = new IPTUClient('sua_api_key', config);
timeout: 60000, // 60 segundos
retryConfig: {
maxRetries: 5,
initialDelay: 1000, // ms
maxDelay: 30000, // ms
backoffFactor: 2.0,
retryableStatusCodes: [429, 500, 502, 503, 504],
},
});
```
### Logging Customizado
---
## Endpoints de Consulta IPTU
### Consulta por Endereco
Busca dados de IPTU por logradouro e numero. Disponivel em **todos os planos**.
```typescript
import { IPTUClient, Logger } from 'iptuapi';
const imoveis = await client.consultaEndereco('Avenida Paulista', '1000', 'sp');
const customLogger: Logger = {
debug: (msg, meta) => console.debug(`[IPTU] ${msg}`, meta),
info: (msg, meta) => console.info(`[IPTU] ${msg}`, meta),
warn: (msg, meta) => console.warn(`[IPTU] ${msg}`, meta),
error: (msg, meta) => console.error(`[IPTU] ${msg}`, meta)
};
for (const imovel of imoveis) {
console.log(`SQL: ${imovel.sql}`);
console.log(`Bairro: ${imovel.bairro}`);
console.log(`Area Terreno: ${imovel.areaTerreno} m2`);
console.log(`Area Construida: ${imovel.areaConstruida} m2`);
console.log(`Valor Venal: R$ ${imovel.valorVenal?.toLocaleString('pt-BR')}`);
}
```
const client = new IPTUClient('sua_api_key', { logger: customLogger });
**Parametros:**
| Parametro | Tipo | Obrigatorio | Descricao |
|-----------|------|-------------|-----------|
| logradouro | string | Sim | Nome da rua/avenida |
| numero | string | Sim | Numero do imovel |
| cidade | Cidade | Nao | Codigo da cidade (sp, bh, recife). Default: sp |
**Tipo Imovel:**
```typescript
interface Imovel {
sql: string;
logradouro: string;
numero: string;
bairro: string;
cep?: string;
areaTerreno?: number;
areaConstruida?: number;
valorVenal?: number;
valorVenalTerreno?: number;
valorVenalConstrucao?: number;
anoConstrucao?: number;
uso?: string;
padrao?: string;
}
```
## Endpoints da API
---
### Consultas (Todos os Planos)
### Consulta por SQL/Indice Cadastral
Busca por identificador unico do imovel. Disponivel a partir do plano **Starter**.
```typescript
// Consulta por endereco
const resultado = await client.consultaEndereco('Avenida Paulista', '1000', 'sp');
// Sao Paulo - numero SQL
const imoveis = await client.consultaSQL('008.045.0123-4', 'sp');
// Consulta por CEP
const resultado = await client.consultaCEP('01310-100', 'sp');
// Belo Horizonte - indice cadastral
const imoveisBH = await client.consultaSQL('007028 005 0086', 'bh');
// Consulta por coordenadas (zoneamento)
const resultado = await client.consultaZoneamento(-23.5505, -46.6333);
// Recife - sequencial
const imoveisRecife = await client.consultaSQL('123456', 'recife');
```
### Consultas Avancadas (Starter+)
---
### Consulta por CEP
Busca todos os imoveis de um CEP. Disponivel em **todos os planos**.
```typescript
// Consulta por numero SQL
const resultado = await client.consultaSQL('100-01-001-001', 'sp');
const imoveis = await client.consultaCEP('01310-100', 'sp');
console.log(`Encontrados: ${imoveis.length} imoveis`);
```
// Historico de valores IPTU
const historico = await client.dadosIPTUHistorico('100-01-001-001', 'sp');
---
// Consulta CNPJ
const empresa = await client.dadosCNPJ('12345678000100');
### Consulta Zoneamento
// Correcao monetaria IPCA
const corrigido = await client.dadosIPCACorrigir(100000, '2020-01', '2024-01');
Retorna informacoes de zoneamento por coordenadas. Disponivel em **todos os planos**.
```typescript
const zoneamento = await client.consultaZoneamento(-23.5505, -46.6333);
console.log(`Zona: ${zoneamento.zona}`);
console.log(`Uso Permitido: ${zoneamento.usoPermitido}`);
console.log(`Coeficiente: ${zoneamento.coeficienteAproveitamento}`);
```
### Valuation (Pro+)
---
## Endpoints de Valuation
### Estimativa de Valor de Mercado
Calcula valor estimado de mercado. Disponivel a partir do plano **Pro**.
```typescript
// Estimativa de valor de mercado
const avaliacao = await client.valuationEstimate({
area_terreno: 250,
area_construida: 180,
areaTerreno: 250,
areaConstruida: 180,
bairro: 'Pinheiros',
cidade: 'sp',
zona: 'ZM',
tipo_uso: 'Residencial',
tipo_padrao: 'Medio',
ano_construcao: 2010
tipoUso: 'Residencial',
tipoPadrao: 'Medio',
anoConstrucao: 2010,
});
console.log(`Valor estimado: R$ ${avaliacao.valor_estimado.toLocaleString()}`);
// Buscar comparaveis
console.log(`Valor Estimado: R$ ${avaliacao.valorEstimado.toLocaleString('pt-BR')}`);
console.log(`Confianca: ${(avaliacao.confianca * 100).toFixed(1)}%`);
console.log(`Faixa: R$ ${avaliacao.valorMinimo.toLocaleString('pt-BR')} - R$ ${avaliacao.valorMaximo.toLocaleString('pt-BR')}`);
```
**Tipo Valuation:**
```typescript
interface Valuation {
valorEstimado: number;
valorMinimo: number;
valorMaximo: number;
confianca: number;
valorM2: number;
metodologia: string;
dataReferencia: string;
}
```
---
### Buscar Comparaveis
Retorna imoveis similares para comparacao. Disponivel a partir do plano **Pro**.
```typescript
const comparaveis = await client.valuationComparables({

@@ -137,17 +230,192 @@ bairro: 'Pinheiros',

cidade: 'sp',
limit: 10
limit: 10,
});
for (const comp of comparaveis) {
console.log(`SQL: ${comp.sql}`);
console.log(`Area: ${comp.areaConstruida} m2`);
console.log(`Valor: R$ ${comp.valorVenal.toLocaleString('pt-BR')}`);
}
```
### Batch Operations (Enterprise)
---
## Endpoints de ITBI
### Status da Transacao ITBI
Consulta status de uma transacao ITBI. Disponivel em **todos os planos**.
```typescript
// Valuation em lote (ate 100 imoveis)
const imoveis = [
{ area_terreno: 250, area_construida: 180, bairro: 'Pinheiros' },
{ area_terreno: 300, area_construida: 200, bairro: 'Moema' }
];
const resultados = await client.valuationBatch(imoveis);
const status = await client.itbiStatus('ITBI-2024-123456', 'sp');
console.log(`Protocolo: ${status.protocolo}`);
console.log(`Status: ${status.status}`);
console.log(`Valor Transacao: R$ ${status.valorTransacao.toLocaleString('pt-BR')}`);
console.log(`Valor ITBI: R$ ${status.valorITBI.toLocaleString('pt-BR')}`);
```
**Tipo ITBIStatus:**
```typescript
interface ITBIStatus {
protocolo: string;
status: string;
dataSolicitacao: string;
valorTransacao: number;
valorVenalReferencia: number;
baseCalculo: number;
aliquota: number;
valorITBI: number;
dataAprovacao?: string;
}
```
---
### Calculo de ITBI
Calcula valor do ITBI para uma transacao. Disponivel em **todos os planos**.
```typescript
const calculo = await client.itbiCalcular({
sql: '008.045.0123-4',
valorTransacao: 500000,
cidade: 'sp',
});
console.log(`Base de Calculo: R$ ${calculo.baseCalculo.toLocaleString('pt-BR')}`);
console.log(`Aliquota: ${(calculo.aliquota * 100).toFixed(1)}%`);
console.log(`Valor ITBI: R$ ${calculo.valorITBI.toLocaleString('pt-BR')}`);
```
---
### Historico de Transacoes ITBI
Retorna historico de transacoes de um imovel. Disponivel a partir do plano **Starter**.
```typescript
const historico = await client.itbiHistorico('008.045.0123-4', 'sp');
for (const tx of historico) {
console.log(`${tx.dataTransacao} - R$ ${tx.valorTransacao.toLocaleString('pt-BR')} (${tx.tipoTransacao})`);
}
```
---
### Aliquotas ITBI
Retorna aliquotas vigentes por cidade. Disponivel em **todos os planos**.
```typescript
const aliquotas = await client.itbiAliquotas('sp');
console.log(`Aliquota Padrao: ${(aliquotas.aliquotaPadrao * 100).toFixed(1)}%`);
console.log(`Aliquota SFH: ${(aliquotas.aliquotaFinanciamentoSFH * 100).toFixed(2)}%`);
console.log(`Base Legal: ${aliquotas.baseLegal}`);
```
---
### Isencoes ITBI
Verifica isencoes aplicaveis. Disponivel em **todos os planos**.
```typescript
const isencoes = await client.itbiIsencoes('sp');
for (const isencao of isencoes) {
console.log(`- ${isencao.tipo}: ${isencao.descricao}`);
console.log(` Requisitos: ${isencao.requisitos.join(', ')}`);
}
```
---
### Guia ITBI
Gera guia de pagamento do ITBI. Disponivel a partir do plano **Starter**.
```typescript
const guia = await client.itbiGuia({
sql: '008.045.0123-4',
valorTransacao: 500000,
comprador: {
nome: 'Joao da Silva',
documento: '123.456.789-00',
email: 'joao@email.com',
},
vendedor: {
nome: 'Maria Santos',
documento: '987.654.321-00',
},
cidade: 'sp',
});
console.log(`Protocolo: ${guia.protocolo}`);
console.log(`Codigo de Barras: ${guia.codigoBarras}`);
console.log(`Vencimento: ${guia.dataVencimento}`);
console.log(`Valor: R$ ${guia.valorITBI.toLocaleString('pt-BR')}`);
```
---
### Validar Guia ITBI
Valida autenticidade de uma guia. Disponivel em **todos os planos**.
```typescript
const validacao = await client.itbiValidarGuia('ITBI-2024-789012', 'sp');
if (validacao.valido) {
console.log('Guia valida!');
if (validacao.pago) {
console.log(`Pago em: ${validacao.dataPagamento}`);
console.log(`Valor pago: R$ ${validacao.valorPago?.toLocaleString('pt-BR')}`);
}
} else {
console.log('Guia invalida!');
}
```
---
### Simular ITBI
Simula calculo sem gerar guia. Disponivel em **todos os planos**.
```typescript
const simulacao = await client.itbiSimular({
valorTransacao: 500000,
cidade: 'sp',
tipoFinanciamento: 'sfh',
valorFinanciado: 400000,
});
console.log(`Valor ITBI Total: R$ ${simulacao.valorITBITotal.toLocaleString('pt-BR')}`);
console.log(` - Parte financiada (SFH): R$ ${simulacao.valorITBIFinanciado.toLocaleString('pt-BR')}`);
console.log(` - Parte nao financiada: R$ ${simulacao.valorITBINaoFinanciado.toLocaleString('pt-BR')}`);
console.log(`Economia com SFH: R$ ${simulacao.economiaSFH.toLocaleString('pt-BR')}`);
```
**Tipo ITBISimulacao:**
```typescript
interface ITBISimulacao {
valorTransacao: number;
valorFinanciado: number;
valorNaoFinanciado: number;
aliquotaSFH: number;
aliquotaPadrao: number;
valorITBIFinanciado: number;
valorITBINaoFinanciado: number;
valorITBITotal: number;
economiaSFH: number;
}
```
---
## Tratamento de Erros

@@ -166,3 +434,3 @@

TimeoutError,
NetworkError
NetworkError,
} from 'iptuapi';

@@ -173,22 +441,26 @@

try {
const resultado = await client.consultaEndereco('Rua Teste', '100');
const imoveis = await client.consultaEndereco('Rua Teste', '100');
} catch (error) {
if (error instanceof AuthenticationError) {
console.log('API Key invalida');
console.log(`API Key invalida: ${error.message}`);
} else if (error instanceof ForbiddenError) {
console.log(`Plano nao autorizado. Requer: ${error.requiredPlan}`);
} else if (error instanceof NotFoundError) {
console.log('Imovel nao encontrado');
console.log(`Imovel nao encontrado: ${error.resource}`);
} else if (error instanceof RateLimitError) {
console.log(`Rate limit excedido. Retry em ${error.retryAfter}s`);
} else if (error instanceof ValidationError) {
console.log('Parametros invalidos:', error.errors);
console.log('Parametros invalidos:');
for (const [field, messages] of Object.entries(error.errors)) {
console.log(` ${field}: ${messages.join(', ')}`);
}
} else if (error instanceof ServerError) {
console.log('Erro no servidor (retryable)');
console.log(`Erro no servidor (retryable): ${error.message}`);
} else if (error instanceof TimeoutError) {
console.log(`Timeout apos ${error.timeoutMs}ms`);
console.log(`Timeout apos ${error.timeoutSeconds}s`);
} else if (error instanceof NetworkError) {
console.log('Erro de conexao');
console.log(`Erro de conexao: ${error.message}`);
} else if (error instanceof IPTUAPIError) {
console.log(`Erro: ${error.message}, Request ID: ${error.requestId}`);
console.log(`Erro: ${error.message}`);
console.log(`Request ID: ${error.requestId}`);
}

@@ -202,3 +474,3 @@ }

try {
const resultado = await client.consultaEndereco('Rua Teste', '100');
const imoveis = await client.consultaEndereco('Rua Teste', '100');
} catch (error) {

@@ -208,3 +480,7 @@ if (error instanceof IPTUAPIError) {

console.log(`Request ID: ${error.requestId}`);
console.log(`Retryable: ${error.isRetryable}`);
console.log(`Retryable: ${error.isRetryable() ? 'Sim' : 'Nao'}`);
// Converter para JSON
const errorData = error.toJSON();
console.log(errorData);
}

@@ -214,2 +490,35 @@ }

### Verificar Tipo de Erro
```typescript
try {
const imoveis = await client.consultaEndereco('Rua Teste', '100');
} catch (error) {
if (error instanceof IPTUAPIError && error.isRetryable()) {
const waitTime = error instanceof RateLimitError ? error.retryAfter : 5;
console.log(`Aguardando ${waitTime}s antes de tentar novamente...`);
await new Promise(resolve => setTimeout(resolve, waitTime * 1000));
const imoveis = await client.consultaEndereco('Rua Teste', '100');
}
}
```
---
## Hierarquia de Excecoes
```
IPTUAPIError (base)
├── AuthenticationError (401)
├── ForbiddenError (403)
├── NotFoundError (404)
├── RateLimitError (429) - retryable
├── ValidationError (400, 422)
├── ServerError (5xx) - retryable
├── TimeoutError (408) - retryable
└── NetworkError - retryable
```
---
## Rate Limiting

@@ -219,77 +528,137 @@

// Verificar rate limit apos requisicao
const rateLimit = client.getRateLimitInfo();
if (rateLimit) {
console.log(`Limite: ${rateLimit.limit}`);
console.log(`Restantes: ${rateLimit.remaining}`);
console.log(`Reset em: ${new Date(rateLimit.reset * 1000)}`);
const rateLimitInfo = client.rateLimitInfo;
if (rateLimitInfo) {
console.log(`Limite: ${rateLimitInfo.limit}`);
console.log(`Restantes: ${rateLimitInfo.remaining}`);
console.log(`Reset em: ${rateLimitInfo.resetAt.toISOString()}`);
}
// ID da ultima requisicao (util para suporte)
console.log(`Request ID: ${client.getLastRequestId()}`);
console.log(`Request ID: ${client.lastRequestId}`);
```
## Tipos TypeScript
### Limites por Plano
| Plano | Requisicoes/mes | Requisicoes/minuto |
|-------|-----------------|-------------------|
| Free | 100 | 10 |
| Starter | 5.000 | 60 |
| Pro | 50.000 | 300 |
| Enterprise | Ilimitado | 1.000 |
---
## Cidades Suportadas
| Codigo | Cidade | Identificador | Registros |
|--------|--------|---------------|-----------|
| sp | Sao Paulo | Numero SQL | 4.5M+ |
| bh | Belo Horizonte | Indice Cadastral | 800K+ |
| recife | Recife | Sequencial | 400K+ |
---
## Exemplo Completo
```typescript
import type {
ClientConfig,
RetryConfig,
RateLimitInfo,
PropertyData,
ValuationParams,
ValuationResult,
ComparableProperty,
ZoningInfo,
IPTUHistoryItem
} from 'iptuapi';
import { IPTUClient, RateLimitError, IPTUAPIError } from 'iptuapi';
// Exemplo de uso com tipos
const config: ClientConfig = {
timeout: 30000
};
async function main() {
const client = new IPTUClient(process.env.IPTU_API_KEY!, {
timeout: 30000,
retryConfig: {
maxRetries: 3,
},
});
const params: ValuationParams = {
area_terreno: 250,
area_construida: 180,
bairro: 'Pinheiros'
};
// Lista de enderecos para consultar
const enderecos = [
{ logradouro: 'Avenida Paulista', numero: '1000' },
{ logradouro: 'Rua Augusta', numero: '500' },
{ logradouro: 'Avenida Faria Lima', numero: '3000' },
];
const resultado: ValuationResult = await client.valuationEstimate(params);
```
for (const endereco of enderecos) {
try {
const imoveis = await client.consultaEndereco(
endereco.logradouro,
endereco.numero,
'sp'
);
## Browser Support
for (const imovel of imoveis) {
console.log(`SQL: ${imovel.sql}, Valor Venal: R$ ${imovel.valorVenal?.toLocaleString('pt-BR')}`);
}
O SDK funciona tanto em Node.js quanto em browsers modernos:
// Verificar rate limit
const rateLimitInfo = client.rateLimitInfo;
if (rateLimitInfo && rateLimitInfo.remaining < 10) {
console.log(`Atencao: Apenas ${rateLimitInfo.remaining} requisicoes restantes`);
}
} catch (error) {
if (error instanceof RateLimitError) {
console.log(`Rate limit atingido. Aguardando ${error.retryAfter}s...`);
await new Promise(resolve => setTimeout(resolve, error.retryAfter * 1000));
} else if (error instanceof IPTUAPIError) {
console.log(`Erro ao consultar ${endereco.logradouro}: ${error.message}`);
}
}
}
```html
<script type="module">
import { IPTUClient } from 'https://unpkg.com/iptuapi@latest/dist/browser.js';
// Exemplo ITBI
console.log('\n--- Simulacao ITBI ---');
try {
const simulacao = await client.itbiSimular({
valorTransacao: 800000,
cidade: 'sp',
tipoFinanciamento: 'sfh',
valorFinanciado: 600000,
});
console.log(`Valor ITBI: R$ ${simulacao.valorITBITotal.toLocaleString('pt-BR')}`);
console.log(`Economia com SFH: R$ ${simulacao.economiaSFH.toLocaleString('pt-BR')}`);
} catch (error) {
if (error instanceof IPTUAPIError) {
console.log(`Erro na simulacao ITBI: ${error.message}`);
}
}
}
const client = new IPTUClient('sua_api_key');
const resultado = await client.consultaEndereco('Avenida Paulista', '1000');
console.log(resultado);
</script>
main();
```
---
## Testes
```bash
# Instalar dependencias
npm install
# Rodar testes
npm test
# Com coverage
npm run test:coverage
# Watch mode
npm run test:watch
```
# Coverage
npm run test:coverage
---
## Build
```bash
# Compilar TypeScript
npm run build
# Type check
npm run typecheck
# Lint
npm run lint
```
## Cidades Suportadas
---
| Codigo | Cidade |
|--------|--------|
| sp | Sao Paulo |
| bh | Belo Horizonte |
| recife | Recife |
## Licenca

@@ -301,2 +670,4 @@

---
## Links

@@ -307,1 +678,2 @@

- [Portal do Desenvolvedor](https://iptuapi.com.br/dashboard)
- [Suporte](mailto:suporte@iptuapi.com.br)
IPTU API - PROPRIETARY LICENSE
Copyright (c) 2025-2026 IPTU API. All rights reserved.
This software and associated documentation files (the "Software") are the
exclusive property of IPTU API. The Software is licensed, not sold.
GRANT OF LICENSE:
Subject to the terms of this license and your compliance with the IPTU API
Terms of Service (https://iptuapi.com.br/termos), you are granted a limited,
non-exclusive, non-transferable license to use the Software solely for the
purpose of accessing the IPTU API services.
RESTRICTIONS:
You may NOT:
- Copy, modify, or distribute the Software
- Reverse engineer, decompile, or disassemble the Software
- Sublicense, rent, lease, or lend the Software
- Use the Software for any purpose other than accessing IPTU API services
- Remove or alter any proprietary notices
TERMINATION:
This license is effective until terminated. It will terminate automatically
if you fail to comply with any term of this license or the IPTU API Terms
of Service.
DISCLAIMER:
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED. IN NO EVENT SHALL IPTU API BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY ARISING FROM THE USE OF THE SOFTWARE.
For questions, contact: contato@iptuapi.com.br