logo
IntegracaoBoas Praticas
Integracao

Boas Práticas

Recomendações de paginação, tratamento de erros, retry com backoff exponencial, rate limiting e checklist de produção para a Keyspot Partner API.

Paginação

Todas as listagens da API usam paginação offset-based com os parâmetros page e limit.

ParâmetroTipoPadrãoMínimoMáximo
pageinteger11
limitinteger201100

A resposta inclui metadados de paginação no campo meta:

{
  "data": [...],
  "meta": {
    "page": 1,
    "limit": 20,
    "total": 150,
    "totalPages": 8
  }
}

Percorrendo todas as páginas

async function fetchAllProperties(token: string, fields: string): Promise<any[]> {
  const allData: any[] = [];
  let page = 1;
  let totalPages = 1;

  do {
    const response = await fetch(
      `https://partner-api.keyspot.com.br/v1/properties?fields=${fields}&page=${page}&limit=100`,
      { headers: { Authorization: `Bearer ${token}` } }
    );

    const { data, meta } = await response.json();
    allData.push(...data);
    totalPages = meta.totalPages;
    page++;
  } while (page <= totalPages);

  return allData;
}

Use limit=100 (máximo) para reduzir o número de requisições ao percorrer grandes conjuntos de dados.

Tratamento de erros

A API retorna erros no formato padronizado { "error": "...", "code": "..." }. Sempre verifique o status HTTP e o code da resposta.

Códigos HTTP

StatusSignificadoAção recomendada
200SucessoProcessar resposta normalmente
201CriadoLead criado com sucesso
400Parâmetros inválidosCorrigir os parâmetros da requisição
401Não autenticadoRenovar o token JWT
403Acesso bloqueadoVerificar IP ou status da API com a Keyspot
404Não encontradoVerificar o URL do endpoint
429Rate limit excedidoAguardar Retry-After segundos
500Erro do servidorRetry com backoff exponencial

Códigos de erro programáticos

Retry com backoff exponencial

Para erros 429 e 5xx, implemente retry com backoff exponencial:

async function fetchWithRetry(
  url: string,
  options: RequestInit,
  maxRetries = 3
): Promise<Response> {
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    const response = await fetch(url, options);

    if (response.status === 429) {
      const retryAfter = Number(response.headers.get("Retry-After") || 60);
      await new Promise((r) => setTimeout(r, retryAfter * 1000));
      continue;
    }

    if (response.status >= 500 && attempt < maxRetries) {
      const delay = Math.pow(2, attempt) * 1000; // 1s, 2s, 4s
      await new Promise((r) => setTimeout(r, delay));
      continue;
    }

    return response;
  }

  throw new Error("Max retries exceeded");
}

Nunca faça retry de erros 400 (validação) ou 401/403 (autenticação) — esses erros exigem correção no código ou nas credenciais.

Rate limiting

A API impõe um limite de requisições por minuto (sliding window de 60 segundos). O limite é configurado por cliente.

Headers de rate limit

Toda resposta de rotas protegidas inclui:

HeaderDescrição
X-RateLimit-LimitLimite máximo de requisições por minuto
X-RateLimit-RemainingRequisições restantes na janela atual
Retry-AfterSegundos para aguardar (apenas quando exceder)

Monitorar o consumo

const response = await fetch(url, { headers: { Authorization: `Bearer ${token}` } });

const limit = Number(response.headers.get("X-RateLimit-Limit"));
const remaining = Number(response.headers.get("X-RateLimit-Remaining"));

if (remaining < 10) {
  console.warn(`Rate limit baixo: ${remaining}/${limit} restantes`);
}

Renovação de token

O token JWT expira em 1 hora. Renove-o proativamente antes de expirar para evitar erros 401 durante requisições.

// Renove a cada 50 minutos (antes dos 60 de expiração)
const TOKEN_REFRESH_INTERVAL = 50 * 60 * 1000;

Veja mais detalhes em Autenticação.

Valores e datas

  • Valores monetários: sempre em reais (BRL), sem formatação. Ex: 450000 (não "R$ 450.000,00")
  • Áreas: sempre em m². Ex: 120.5
  • Datas: sempre em ISO 8601 com timezone UTC. Ex: 2026-03-13T10:30:00.000Z
  • Filtros de data: use createdAfter, createdBefore, updatedAfter, updatedBefore em formato ISO 8601

Seleção de campos

Solicite apenas os campos que você precisa:

# Apenas dados básicos para listagem
GET /v1/properties?fields=code,title,status,pricing

# Dados para exibição de card
GET /v1/properties?fields=code,title,address,pricing,photos&limit=10

Sincronização incremental

Para manter seus dados atualizados sem re-consultar todo o catálogo, use filtros de data:

# Imóveis atualizados nas últimas 24 horas
GET /v1/properties?fields=code,title,status,pricing,updatedAt&updatedAfter=2026-03-12T00:00:00Z

Armazene o timestamp da última sincronização e use-o como updatedAfter na próxima consulta.

Checklist de produção

Antes de ir para produção, verifique se sua integração atende a todos os critérios:

  • Autenticação: renovação automática de token antes da expiração
  • Paginação: percorre todas as páginas quando necessário
  • Tratamento de erros: lida com todos os códigos HTTP (400, 401, 403, 429, 500)
  • Retry: backoff exponencial para erros 429 e 5xx
  • Rate limiting: monitora headers e respeita os limites
  • Seleção de campos: solicita apenas campos necessários
  • Credenciais: armazenadas com segurança (variáveis de ambiente)
  • HTTPS: todas as requisições usam HTTPS
  • Logs: registra erros e requisições para debug
  • Sincronização: usa filtros de data para atualizações incrementais

Próximos passos