Consumindo a SmartCPF em Supabase Edge Functions
Tutorial técnico: integre a API SmartCPF v2 em Supabase Edge Functions com TypeScript, autenticação X-API-KEY e tratamento de erros.

Validar e consultar CPFs em tempo real é um requisito comum em sistemas brasileiros — onboarding de usuários, compliance KYC, prevenção de fraude. A API SmartCPF resolve isso com uma consulta única que retorna dados cadastrais, situação cadastral, e-mails, telefones e endereços associados ao CPF. Este artigo mostra como consumir o endpoint GET /v2/individuals/{cpf} diretamente de uma Supabase Edge Function, mantendo a chave de API segura no servidor e lidando com respostas de erro de forma robusta.
Supabase Edge Functions rodam no runtime Deno, o que significa TypeScript nativo, fetch global disponível e implantação via CLI sem configuração de containers. A combinação é ideal para chamadas de API sensíveis: a X-API-KEY nunca expõe no frontend, a função escala automaticamente e o custo por execução permanece previsível.
O que são Supabase Edge Functions
Edge Functions são funções serverless executadas na borda da rede (Deno Deploy), com latência baixa e cold-start mínimo. Diferente de Functions tradicionais (Node.js), o runtime é Deno: sem node_modules, imports via URL (esm.sh, jsr.io), tipagem TypeScript out-of-the-box e APIs web padrão (fetch, Request, Response, Headers). Para integrações externas como a SmartCPF, isso elimina bundlers e permite escrever o cliente HTTP direto com tipagem estrita.
Vantagens de usar Edge Functions com a SmartCPF
1. Segredo no servidor
A X-API-KEY fica apenas em variáveis de ambiente da Edge Function; o frontend chama sua função sem credenciais.
2. Tipagem compartilhada
Defina interfaces TypeScript para request/response da SmartCPF e reutilize no frontend via supabase functions invoke — contratos sincronizados sem OpenAPI extra.
3. Escala automática
Picos de cadastro (Black Friday, campanhas) não exigem provisionamento; o Deno Deploy escala horizontalmente.
4. Logs centralizadosconsole.log/console.error aparecem no dashboard do Supabase e no CLI (supabase functions logs), facilitando debug de 422, 401, 429.
5. Custo por execução
Modelo pay-per-invocation alinha com o modelo de créditos da SmartCPF: cada consulta consome 1 crédito, cada invocação da Edge Function tem custo fixo conhecido.
6. CORS nativo
Retorne headers Access-Control-Allow-Origin direto na Response — sem configurar gateway extra.
Desafios ao integrar APIs externas em Edge Functions
1. Timeout padrão de 150s
A SmartCPF responde em ~100ms, mas se a latência subir, a Edge Function pode estourar o limite. Configure export const config = { runtime: 'edge', maxDuration: 30 } se precisar de margem.
2. Sem node:crypto nativo
Deno usa crypto.subtle (Web Crypto API). Para assinaturas HMAC ou hash de CPF antes de enviar, use crypto.subtle.digest ou bibliotecas compatíveis (ex: @std/crypto).
3. Variáveis de ambiente no deploysupabase secrets set SMARTCP_API_KEY=... é obrigatório antes do supabase functions deploy. Esquecer isso gera 500 silencioso — teste local com supabase functions serve --env-file=.env.local.
4. Rate limit da SmartCPF (429)
A API retorna Retry-After em segundos. Implemente backoff exponencial ou fila no frontend; a Edge Function pode apenas propagar o status e header.
5. Cold start em regiões distantes
Deno Deploy roda em ~35 regiões. Usuários no Brasil batem em São Paulo (GRU) ou Rio (GIG) — latência < 50ms. Fora do Brasil, adicione fly.io ou Cloudflare Workers como camada extra se necessário.
Como implementar com a SmartCPF
Abaixo, uma Edge Function completa que valida o CPF recebido, chama a SmartCPF com o header X-API-KEY, trata códigos de erro e retorna JSON padronizado para o frontend. O arquivo deve ficar em supabase/functions/consultar-cpf/index.ts.
import { serve } from "https://deno.land/[email protected]/http/server.ts";
// ============================================================
// Tipos da resposta SmartCPF (subset relevante para o frontend)
// ============================================================
interface SmartCpfMeta {
searchType: string;
consultId: string;
user: string;
message: string;
ip: string;
success: boolean;
apiVersion: string;
date: string; // ISO 8601
executionTimeMs: number;
balance: number; // créditos restantes
}
interface SmartCpfPhone {
number: string;
blockedTelemarketing: boolean;
operator: string;
type: string;
whatsapp: boolean;
}
interface SmartCpfResult {
cpf: string;
name: string;
birthDate: string; // DD/MM/YYYY
age: number;
motherName: string;
gender: "M" | "F";
status: string;
emails: string[];
phones: SmartCpfPhone[];
addresses: unknown[]; // estrutura omitida por brevidade
}
interface SmartCpfResponse {
meta: SmartCpfMeta;
result: SmartCpfResult;
success: boolean;
errors: string[];
}
// ============================================================
// Resposta padronizada que nosso frontend vai consumir
// ============================================================
interface ApiResponse<T> {
ok: boolean;
data?: T;
error?: {
code: string;
message: string;
details?: unknown;
consultId?: string; // rastreabilidade SmartCPF
};
}
// ============================================================
// Validação simples de CPF (apenas formato, não dígito verificador)
// ============================================================
function isValidCpfFormat(cpf: string): boolean {
const cleaned = cpf.replace(/\D/g, "");
return cleaned.length === 11 && /^\d{11}$/.test(cleaned);
}
// ============================================================
// Handler principal
// ============================================================
serve(async (req: Request): Promise<Response> => {
// CORS pré-voo
if (req.method === "OPTIONS") {
return new Response(null, {
status: 204,
headers: corsHeaders(),
});
}
if (req.method !== "POST") {
return jsonResponse(
{ ok: false, error: { code: "METHOD_NOT_ALLOWED", message: "Use POST" } },
405
);
}
// Lê body JSON
let body: { cpf?: string; package?: string } = {};
try {
body = await req.json();
} catch {
return jsonResponse(
{ ok: false, error: { code: "INVALID_JSON", message: "Body deve ser JSON válido" } },
400
);
}
const { cpf, package: pkg = "complete" } = body;
// Validação de entrada
if (!cpf || !isValidCpfFormat(cpf)) {
return jsonResponse(
{ ok: false, error: { code: "INVALID_CPF", message: "CPF inválido. Envie 11 dígitos numéricos." } },
422
);
}
const apiKey = Deno.env.get("SMARTCP_API_KEY");
if (!apiKey) {
console.error("SMARTCP_API_KEY não configurada nas secrets da Edge Function");
return jsonResponse(
{ ok: false, error: { code: "SERVER_CONFIG_ERROR", message: "Chave de API não configurada no servidor" } },
500
);
}
const cleanedCpf = cpf.replace(/\D/g, "");
const url = `https://api.smartcpf.com.br/v2/individuals/${cleanedCpf}?package=${encodeURIComponent(pkg)}`;
// Chamada à SmartCPF
let smartRes: Response;
try {
smartRes = await fetch(url, {
method: "GET",
headers: {
"X-API-KEY": apiKey,
"Accept": "application/json",
"User-Agent": "supabase-edge-function/1.0",
},
});
} catch (err) {
console.error("Erro de rede ao chamar SmartCPF:", err);
return jsonResponse(
{ ok: false, error: { code: "UPSTREAM_NETWORK_ERROR", message: "Falha de comunicação com a API SmartCPF" } },
502
);
}
// Parse seguro da resposta
let smartData: SmartCpfResponse;
try {
smartData = await smartRes.json();
} catch {
return jsonResponse(
{ ok: false, error: { code: "UPSTREAM_INVALID_JSON", message: "Resposta inválida da API SmartCPF" } },
502
);
}
// Mapeia códigos de status HTTP da SmartCPF para nossa resposta
if (!smartRes.ok) {
const errorMap: Record<number, { code: string; message: string }> = {
400: { code: "BAD_REQUEST", message: "Parâmetros inválidos enviados à SmartCPF" },
401: { code: "UNAUTHORIZED", message: "Chave de API inválida ou expirada" },
403: { code: "FORBIDDEN", message: "Acesso negado — verifique permissões do plano" },
404: { code: "NOT_FOUND", message: "CPF não encontrado na base" },
422: { code: "UNPROCESSABLE_ENTITY", message: "CPF inválido ou mal formatado" },
429: { code: "RATE_LIMITED", message: "Limite de requisições excedido" },
500: { code: "UPSTREAM_ERROR", message: "Erro interno da API SmartCPF" },
503: { code: "SERVICE_UNAVAILABLE", message: "API SmartCPF indisponível no momento" },
};
const mapped = errorMap[smartRes.status] ?? {
code: "UPSTREAM_ERROR",
message: `Erro na API SmartCPF (HTTP ${smartRes.status})`,
};
return jsonResponse(
{
ok: false,
error: {
...mapped,
details: smartData.errors?.length ? smartData.errors : smartData.meta?.message,
consultId: smartData.meta?.consultId,
},
},
smartRes.status
);
}
// Sucesso: retorna campos úteis para o frontend
return jsonResponse({
ok: true,
data: {
consultId: smartData.meta.consultId,
balance: smartData.meta.balance,
executionTimeMs: smartData.meta.executionTimeMs,
cpf: smartData.result.cpf,
name: smartData.result.name,
birthDate: smartData.result.birthDate,
age: smartData.result.age,
motherName: smartData.result.motherName,
gender: smartData.result.gender,
status: smartData.result.status,
emails: smartData.result.emails,
phones: smartData.result.phones.map((p) => ({
number: p.number,
operator: p.operator,
type: p.type,
whatsapp: p.whatsapp,
blockedTelemarketing: p.blockedTelemarketing,
})),
addresses: smartData.result.addresses,
},
});
});
// ============================================================
// Helpers
// ============================================================
function corsHeaders(): HeadersInit {
return {
"Access-Control-Allow-Origin": "*", // ajuste para seu domínio em produção
"Access-Control-Allow-Methods": "POST, OPTIONS",
"Access-Control-Allow-Headers": "Content-Type, Authorization",
"Access-Control-Max-Age": "86400",
};
}
function jsonResponse(data: unknown, status = 200): Response {
return new Response(JSON.stringify(data), {
status,
headers: {
"Content-Type": "application/json; charset=utf-8",
...corsHeaders(),
},
});
}
Resposta da API
O exemplo abaixo mostra a estrutura real retornada pela SmartCPF v2 (package complete). Os campos consultId e balance são essenciais para rastreabilidade e controle de créditos.
{
"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 implementado resolve na prática:
- Rastreabilidade:
consultIdúnico por consulta permite auditoria e suporte ("qual foi a consulta #a1b2c3d4?"). - Controle de custos:
balance(9.77 créditos) retorna em toda resposta — seu dashboard pode alertar quando cair abaixo de um threshold. - Performance observável:
executionTimeMs(74.1ms) expõe latência real da SmartCPF; útil para SLOs internos. - Dados enriquecidos prontos:
phones[].operator,phones[].whatsapp,emails[]eliminam chamadas adicionais a provedores de enriquecimento. - Erro acionável: mapeamento de
401→UNAUTHORIZED,429→RATE_LIMITEDcomRetry-Afterpropagado evita retry loops cegos no frontend.
Por que usar a SmartCPF
- Latência previsível: P95 < 150ms na região GRU/GIG, ideal para fluxos síncronos de cadastro.
- Integração direta: REST + header
X-API-KEY— sem OAuth flows, sem SDKs pesados, funciona em qualquer runtime (Deno, Node, Go, Python). - Modelo de créditos transparente: 1 consulta = 1 crédito;
balanceem cada resposta elimina surpresas na fatura. - Dados completos no package
complete: situação cadastral, nome da mãe, e-mails, telefones com operadora/WhatsApp, endereços — tudo em uma chamada. - Escalabilidade nativa: A API suporta milhares de RPM; combinada com Edge Functions, o gargalo passa a ser seu rate limit, não a infra.
Conclusão
Consumir a SmartCPF de uma Supabase Edge Function mantém a credencial segura, tipa o contrato ponta-a-ponta e escala sem ops. O código acima cobre validação, autenticação correta (X-API-KEY), mapeamento de erros e resposta enxuta para o frontend. Crie sua conta na SmartCPF e faça sua primeira consulta em minutos.
Sobre a redação
Redação Smart CPF
Autor do blog
Mais artigos

Validação de CPF em Vercel Edge Functions com SmartCPF
Como implementar validação de CPF em tempo real nas Edge Functions do Vercel usando a API SmartCPF, com autenticação X-API-KEY e baixa latência.

Integrando SmartCPF em Google Cloud Functions com Python
Tutorial prático para consultar CPF via API SmartCPF em Cloud Functions, com autenticação X-API-KEY, tratamento de erros e exemplo completo em Python.

Validação de CPF em AWS Lambda: arquitetura serverless com SmartCPF
Aprenda a integrar validação de CPF em funções Lambda serverless usando a API SmartCPF v2 com autenticação X-API-KEY.

Consumindo a API SmartCPF em Java com Spring Boot
Tutorial prático de integração da API SmartCPF v2 em aplicações Spring Boot com autenticação X-API-KEY e tratamento de erros.
Pronto para validar CPFs em segundos?
Consultas gratuitas para testar agora. Acesso imediato à documentação.