Integrando a SmartCPF em runtime Bun: guia rápido

Como consumir a API SmartCPF v2 com Bun nativo: autenticação X-API-KEY, tratamento de erro e parsing de resposta.

Redação Smart CPFRedação Smart CPF
·· 7 min de leitura
Integrando a SmartCPF em runtime Bun: guia rápido

Validar CPFs em tempo real é um requisito comum em onboarding, compliance e prevenção a fraude. A API SmartCPF resolve isso com uma consulta única que retorna dados cadastrais, situação cadastral, contatos e endereços — tudo via endpoint REST simples. Este guia mostra como integrar a versão 2 da API usando o runtime Bun, que já traz fetch nativo, TypeScript e performance superior a Node.js sem dependências extras.

O Bun elimina a necessidade de bibliotecas HTTP como axios ou node-fetch: o fetch global segue o padrão Web APIs e roda direto no JavaScriptCore. Isso reduz o bundle, acelera o cold start e simplifica o código de produção. Abaixo, você verá a chamada autenticada, o tratamento de códigos de status e a extração dos campos mais usados no retorno.

Como a autenticação funciona na SmartCPF v2

Toda requisição exige o header X-API-KEY com sua chave privada — não use Authorization: Bearer, query string api_key nem cookies. O endpoint base é https://api.smartcpf.com.br/v2/individuals/{cpf} e aceita o parâmetro opcional package para escolher o pacote de dados (ex: package=X para o retorno completo). O CPF na URL pode vir com ou sem formatação (pontos e hífen); a API normaliza internamente.

Erros comuns: 401 (chave inválida ou ausente), 403 (plano sem acesso ao pacote), 404 (CPF não encontrado na base), 422 (CPF malformado), 429 (rate limit excedido). O corpo de erro segue o padrão { "success": false, "errors": [{ "code": "...", "message": "..." }] }.

Vantagens de usar Bun para essa integração

1. Fetch nativo sem polyfill
O fetch global do Bun é compatível com a especificação WHATWG e não precisa de undici ou node-fetch — o código roda idêntico no browser e no servidor.

2. TypeScript direto
Arquivos .ts executam sem etapa de build (bun run script.ts). Tipagem da resposta da API melhora a manutenção e evita erros de runtime.

3. Cold start mínimo
Bun inicia em milissegundos, ideal para serverless functions, edge workers ou CLI tools que consultam a API sob demanda.

4. Gerenciamento de dependências integrado
bun add instala pacotes mais rápido que npm/yarn e o lockfile (bun.lockb) é determinístico — útil em pipelines de CI/CD.

5. Testes built-in
bun test roda suites sem configurar Jest/Vitest; você pode validar a integração com mocks do fetch nativo.

6. Compatibilidade Node.js
APIs como process.env, Buffer, path funcionam; migração de scripts legados é direta.

O que considerar antes de implementar

1. Chave de API em variável de ambiente
Nunca commite a X-API-KEY no repositório. Use .env local e segredos do provedor de cloud (Vercel, AWS Secrets Manager, Cloudflare Workers KV).

2. Rate limits por plano
Planos gratuitos têm limite baixo de requisições/minuto. Implemente backoff exponencial e fila se o volume for alto.

3. Formato do CPF na URL
Embora a API aceite 111.111.111-11 ou 11111111111, remova formatação no cliente para evitar double-encoding em proxies/CDNs.

4. Tratamento de balance
O campo meta.balance indica créditos restantes. Monitore-o para alertar antes de zerar — a API retorna 403 sem créditos.

5. Dados sensíveis no retorno
O response traz nome, data de nascimento, e-mail, telefone e endereços. Aplique LGPD: logue apenas consultId e cpf mascarado, nunca o payload completo.

Como implementar com a SmartCPF

O exemplo abaixo usa Bun nativo, lê a chave do ambiente, valida o CPF de entrada, faz a requisição com X-API-KEY, trata códigos de erro e retorna um objeto tipado com os campos essenciais. Salve como smartcpf.ts e rode com bun run smartcpf.ts.

smartcpf.ts
// smartcpf.ts — Consulta CPF na SmartCPF v2 usando Bun nativo
// Rode: bun run smartcpf.ts

interface SmartCPFResponse {
  meta: {
    searchType: string;
    consultId: string;
    user: string;
    message: string;
    ip: string;
    success: boolean;
    apiVersion: string;
    date: string;
    executionTimeMs: number;
    balance: number;
  };
  result: {
    cpf: string;
    name: string;
    birthDate: string;
    age: number;
    motherName: string;
    gender: string;
    status: string;
    emails: string[];
    phones: Array<{
      number: string;
      blockedTelemarketing: boolean;
      operator: string;
      type: string;
      whatsapp: boolean;
    }>;
    addresses: Array<{
      zipCode: string;
      street: string;
      number: string;
      complement: string;
      neighborhood: string;
      city: string;
      state: string;
    }>;
  };
  success: boolean;
  errors: Array<{ code: string; message: string }>;
}

interface ConsultaCPFResultado {
  ok: boolean;
  consultId?: string;
  balance?: number;
  cpf?: string;
  name?: string;
  status?: string;
  emails?: string[];
  phones?: string[];
  error?: string;
}

const API_BASE = 'https://api.smartcpf.com.br/v2/individuals';

function limparCPF(cpf: string): string {
  return cpf.replace(/\D/g, '');
}

function validarCPF(cpf: string): boolean {
  const numeros = limparCPF(cpf);
  if (numeros.length !== 11 || /^(\d)\1+$/.test(numeros)) return false;
  let soma = 0;
  for (let i = 0; i < 9; i++) soma += parseInt(numeros[i]) * (10 - i);
  let digito = 11 - (soma % 11);
  if (digito > 9) digito = 0;
  if (digito !== parseInt(numeros[9])) return false;
  soma = 0;
  for (let i = 0; i < 10; i++) soma += parseInt(numeros[i]) * (11 - i);
  digito = 11 - (soma % 11);
  if (digito > 9) digito = 0;
  return digito === parseInt(numeros[10]);
}

async function consultarCPF(cpf: string, apiKey: string, pkg = 'X'): Promise<ConsultaCPFResultado> {
  const cpfLimpo = limparCPF(cpf);
  if (!validarCPF(cpfLimpo)) {
    return { ok: false, error: 'CPF inválido (formato ou dígitos verificadores)' };
  }

  const url = `${API_BASE}/${cpfLimpo}?package=${pkg}`;

  try {
    const response = await fetch(url, {
      method: 'GET',
      headers: {
        'X-API-KEY': apiKey,
        'Accept': 'application/json',
        'User-Agent': 'smartcpf-bun-example/1.0',
      },
    });

    const data: SmartCPFResponse = await response.json();

    if (!response.ok) {
      const msg = data.errors?.[0]?.message || `HTTP ${response.status}`;
      return { ok: false, error: msg };
    }

    if (!data.success) {
      const msg = data.errors?.[0]?.message || 'Erro desconhecido na resposta';
      return { ok: false, error: msg };
    }

    return {
      ok: true,
      consultId: data.meta.consultId,
      balance: data.meta.balance,
      cpf: data.result.cpf,
      name: data.result.name,
      status: data.result.status,
      emails: data.result.emails,
      phones: data.result.phones.map(p => p.number),
    };
  } catch (err) {
    const message = err instanceof Error ? err.message : 'Erro de rede/desconhecido';
    return { ok: false, error: `Falha na requisição: ${message}` };
  }
}

// Exemplo de uso
async function main() {
  const apiKey = process.env.SMARTCPF_API_KEY;
  if (!apiKey) {
    console.error('Defina SMARTCPF_API_KEY no ambiente (.env ou variável de sistema)');
    process.exit(1);
  }

  const cpfTeste = '111.111.111-11'; // CPF de exemplo — substitua pelo real
  const resultado = await consultarCPF(cpfTeste, apiKey);

  if (resultado.ok) {
    console.log('✅ Consulta bem-sucedida');
    console.log(`   ConsultId: ${resultado.consultId}`);
    console.log(`   Saldo restante: ${resultado.balance}`);
    console.log(`   CPF: ${resultado.cpf}`);
    console.log(`   Nome: ${resultado.name}`);
    console.log(`   Status: ${resultado.status}`);
    console.log(`   E-mails: ${resultado.emails?.join(', ') || '—'}`);
    console.log(`   Telefones: ${resultado.phones?.join(', ') || '—'}`);
  } else {
    console.error('❌ Falha:', resultado.error);
  }
}

main();

Resposta da API

response.json
{
  "meta": {
    "searchType": "CPF G",
    "consultId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "user": "Fulano de Tal",
    "message": "CPF encontrado com sucesso",
    "ip": "127.0.0.1",
    "success": true,
    "apiVersion": "v2",
    "date": "2026-08-17T14:32:10.123Z",
    "executionTimeMs": 74.1,
    "balance": 9.77
  },
  "result": {
    "cpf": "111.111.111-11",
    "name": "João da Silva",
    "birthDate": "10/09/1992",
    "age": 33,
    "motherName": "Maria da Silva",
    "gender": "M",
    "status": "Regular",
    "emails": ["[email protected]"],
    "phones": [
      {
        "number": "(55) 99999-9999",
        "blockedTelemarketing": false,
        "operator": "VIVO",
        "type": "CELULAR",
        "whatsapp": false
      }
    ],
    "addresses": []
  },
  "success": true,
  "errors": []
}

O fluxo acima resolve na prática:

  • Validação local do CPF antes de gastar crédito (função validarCPF com dígitos verificadores).
  • Autenticação correta via header X-API-KEY lido de variável de ambiente — zero segredo no código.
  • Tratamento granular de HTTP 401/403/404/422/429 via response.ok e inspeção de data.errors.
  • Extração tipada dos campos críticos: consultId para auditoria/rastreio, balance para monitoramento de créditos, status (Regular/Pendente/Irregular) para decisão de negócio, e contatos (emails, phones) para comunicação.
  • Resiliência com try/catch capturando falhas de rede, DNS, timeout ou JSON malformado.

Por que usar a SmartCPF

  • Latência baixa: média de 50–100 ms por consulta (campo executionTimeMs no retorno).
  • Integração direta: REST + JSON padrão, sem SDK obrigatório — funciona em qualquer runtime (Bun, Node, Deno, Cloudflare Workers, edge functions).
  • Modelo por créditos: paga apenas o que consome; balance no retorno permite alerta proativo.
  • Dados enriquecidos: além do status cadastral, traz e-mails, telefones com operadora/tipo/WhatsApp e endereços completos.
  • Escalabilidade: a API suporta picos de milhares de req/s; o rate limit é por conta, não por IP.

Conclusão

Com Bun, a integração fica enxuta: zero dependências, TypeScript nativo e fetch padrão web. O exemplo acima cobre validação, autenticação correta, tratamento de erro e extração dos campos decisórios — base suficiente para colocar em produção hoje. Crie sua conta na SmartCPF e faça sua primeira consulta em minutos.

Redação Smart CPF

Sobre a redação

Redação Smart CPF

Autor do blog

Pronto para validar CPFs em segundos?

Consultas gratuitas para testar agora. Acesso imediato à documentação.