Pular para o conteúdo principal

Boas Práticas de Integração

Um guia rápido para garantir que sua integração seja segura, resiliente e pronta para produção.

Segurança

Armazenamento de credenciais

Nunca coloque ACCESS_TOKEN ou SECRET_KEY diretamente no código-fonte. Use variáveis de ambiente:

// Correto
const accessToken = process.env.FROTA_ACCESS_TOKEN;
const secretKey = process.env.FROTA_SECRET_KEY;

// Errado — nunca faça isso
const accessToken = 'meu_token_fixo'; // ❌

Em produção, prefira um secret manager (AWS Secrets Manager, HashiCorp Vault, etc.).

Use HTTPS sempre

Todas as requisições devem usar HTTPS. O ambiente de homologação e produção já exigem HTTPS.

Não exponha credenciais em logs

// Correto — logar sem expor a chave
console.log('Chamando API:', { url, method });

// Errado — expõe credenciais
console.log('Headers:', { authorization: headers.authorization }); // ❌

Resiliência

Implemente retry com backoff

Para erros temporários (HTTP 5xx), tente novamente com espera crescente:

async function chamarComRetry(url, opcoes, tentativas = 3) {
for (let i = 0; i < tentativas; i++) {
const resposta = await fetch(url, opcoes);

if (resposta.ok) return resposta;

// Erros 4xx não devem ter retry (exceto 429)
if (resposta.status >= 400 && resposta.status < 500 && resposta.status !== 429) {
throw new Error(`Erro HTTP ${resposta.status}`);
}

// Espera: 1s, 2s, 4s
const espera = Math.pow(2, i) * 1000;
await new Promise(r => setTimeout(r, espera));
}

throw new Error('Número máximo de tentativas atingido');
}

Respeite o header Retry-After

Se receber HTTP 429, aguarde o tempo indicado antes de tentar novamente:

if (resposta.status === 429) {
const espera = parseInt(resposta.headers.get('Retry-After') || '60');
await new Promise(r => setTimeout(r, espera * 1000));
}

Performance

Use paginação adequada

Não busque todos os registros de uma vez. Use páginas menores e processe em lotes:

const PAGINA_TAMANHO = 50;
let pagina = 1;

while (true) {
const dados = await buscarPagina(pagina, PAGINA_TAMANHO);
await processarLote(dados.data);

if (pagina >= dados.pagination.totalPages) break;
pagina++;
}

Prefira webhooks para atualizações em tempo real

Em vez de fazer polling (verificar periodicamente se há novidades), configure webhooks para receber eventos conforme acontecem. Isso reduz o número de requisições e garante resposta mais rápida.

Veja Webhooks.

Cache de dados estáticos

Dados como listas de empresas, divisões e grupos de usuários mudam raramente. Armazene em cache para evitar chamadas desnecessárias:

let empresasCache = null;
let cacheTimestamp = 0;
const CACHE_TTL = 5 * 60 * 1000; // 5 minutos

async function obterEmpresas() {
if (empresasCache && Date.now() - cacheTimestamp < CACHE_TTL) {
return empresasCache;
}

empresasCache = await buscarEmpresas();
cacheTimestamp = Date.now();
return empresasCache;
}

Viagens e indicação de condutores

Prefira viagens à indicação manual

O endpoint de indicação manual (/key/tickets/indicate-driver) é útil para casos pontuais. Para fluxos regulares, use viagens: ao registrar a viagem com o condutor e o intervalo, todas as multas e notificações do período são vinculadas automaticamente.

Feche viagens abertas

Viagens sem endDate continuam vinculando novos eventos ao condutor indefinidamente. Sempre defina a data de fim ao encerrar uma viagem, ou atualize via PUT /key/trips/{id}.

Checklist de integração

Antes de ir para produção, verifique:

  • Credenciais armazenadas em variáveis de ambiente
  • HMAC calculado corretamente em todas as requisições
  • Retry com backoff para erros 5xx
  • Respeito ao Retry-After em erros 429
  • Webhook cadastrado para eventos relevantes
  • Endpoint de webhook responde HTTP 200 em até 5s
  • Endpoint de webhook valida a assinatura HMAC recebida
  • Endpoint de webhook trata entregas duplicadas via campo id
  • Testado no ambiente de homologação

Dúvidas ou problemas? Entre em contato em suporte@frota162.com.br.