# Como consumir API de CPF em Supabase Edge Functions com Deno

> Aprenda a criar uma Supabase Edge Function em Deno que consome a API de CPF da CPFHub.io com fetch nativo e integração com banco de dados Supabase.

**Publicado:** 22/09/2026
**Autor:** Redação CPFHub.io
**URL:** https://www.cpfhub.io/blog/como-consumir-api-cpf-supabase-edge-functions-deno

---


Para consumir a API de CPF da CPFHub.io em Supabase Edge Functions, crie uma função Deno que recebe o CPF via POST, consulta o endpoint `https://api.cpfhub.io/cpf/{CPF}` com o header `x-api-key` e retorna os dados ao frontend — mantendo a chave de API segura no servidor. A integração com o banco PostgreSQL do Supabase permite implementar cache nativo sem Redis, armazenando resultados por 24 horas. Consulte a [documentação oficial do Supabase](https://supabase.com/docs/guides/functions) para detalhes sobre deploy e variáveis de ambiente no Deno Deploy.

---

## Configuração inicial

Primeiro, instale o Supabase CLI e inicialize o projeto:

```bash
# Instalar Supabase CLI
npm install -g supabase

# Iniciar projeto (se ainda nao existir)
supabase init

# Criar a Edge Function
supabase functions new validar-cpf
```

Isso cria a estrutura:

```
supabase/
 functions/
 validar-cpf/
 index.ts
```

---

## Implementação da Edge Function

A Edge Function recebe requisições HTTP e consulta a API da CPFHub.io:

```typescript
// supabase/functions/validar-cpf/index.ts
import { serve } from "https://deno.land/std@0.208.0/http/server.ts";
import { createClient } from "https://esm.sh/@supabase/supabase-js@2.39.0";

interface CPFApiResponse {
 success: boolean;
 data?: {
 cpf: string;
 name: string;
 nameUpper: string;
 gender: string;
 birthDate: string;
 day: number;
 month: number;
 year: number;
 };
}

const CPFHUB_API_KEY = Deno.env.get("CPFHUB_API_KEY") ?? "";
const SUPABASE_URL = Deno.env.get("SUPABASE_URL") ?? "";
const SUPABASE_SERVICE_KEY = Deno.env.get("SUPABASE_SERVICE_ROLE_KEY") ?? "";
const TIMEOUT_MS = 10000;

const corsHeaders = {
 "Access-Control-Allow-Origin": "*",
 "Access-Control-Allow-Methods": "POST, OPTIONS",
 "Access-Control-Allow-Headers": "authorization, x-client-info, apikey, content-type",
};

function jsonResponse(body: object, status = 200): Response {
 return new Response(JSON.stringify(body), {
 status,
 headers: { ...corsHeaders, "Content-Type": "application/json" },
 });
}

async function consultarCPFHub(cpf: string): Promise<CPFApiResponse> {
 const controller = new AbortController();
 const timeoutId = setTimeout(() => controller.abort(), TIMEOUT_MS);

 try {
 const response = await fetch(`https://api.cpfhub.io/cpf/${cpf}`, {
 method: "GET",
 headers: {
 "x-api-key": CPFHUB_API_KEY,
 "Accept": "application/json",
 },
 signal: controller.signal,
 });

 clearTimeout(timeoutId);

 if (!response.ok) {
 throw new Error(`API retornou status ${response.status}`);
 }

 return await response.json();
 } catch (error) {
 clearTimeout(timeoutId);
 throw error;
 }
}

async function verificarCache(
 supabase: ReturnType<typeof createClient>,
 cpf: string
) {
 const { data, error } = await supabase
 .from("cpf_cache")
 .select("*")
 .eq("cpf", cpf)
 .gt("expires_at", new Date().toISOString())
 .single();

 if (error || !data) return null;
 return data;
}

async function salvarCache(
 supabase: ReturnType<typeof createClient>,
 cpf: string,
 dados: object
) {
 const expiresAt = new Date();
 expiresAt.setHours(expiresAt.getHours() + 24);

 await supabase.from("cpf_cache").upsert({
 cpf,
 dados,
 expires_at: expiresAt.toISOString(),
 updated_at: new Date().toISOString(),
 });
}

serve(async (req: Request) => {
 // Tratar preflight CORS
 if (req.method === "OPTIONS") {
 return new Response("ok", { headers: corsHeaders });
 }

 if (req.method !== "POST") {
 return jsonResponse({ erro: "Use POST com body { cpf: '...' }" }, 405);
 }

 try {
 const body = await req.json();
 const cpfRaw = body.cpf ?? "";
 const cpf = cpfRaw.replace(/\D/g, "");

 if (cpf.length !== 11) {
 return jsonResponse({ erro: "CPF deve conter 11 digitos" }, 400);
 }

 // Inicializar cliente Supabase
 const supabase = createClient(SUPABASE_URL, SUPABASE_SERVICE_KEY);

 // Verificar cache primeiro
 const cached = await verificarCache(supabase, cpf);
 if (cached) {
 return jsonResponse({
 valido: true,
 dados: cached.dados,
 fonte: "cache",
 });
 }

 // Consultar API CPFHub.io
 const resultado = await consultarCPFHub(cpf);

 if (!resultado.success || !resultado.data) {
 return jsonResponse({ erro: "CPF nao encontrado" }, 404);
 }

 const dadosFormatados = {
 nome: resultado.data.name,
 cpf: resultado.data.cpf,
 genero: resultado.data.gender,
 dataNascimento: resultado.data.birthDate,
 };

 // Salvar no cache
 await salvarCache(supabase, cpf, dadosFormatados);

 return jsonResponse({
 valido: true,
 dados: dadosFormatados,
 fonte: "api",
 });
 } catch (error) {
 const mensagem = error instanceof DOMException && error.name === "AbortError"
 ? "Timeout na consulta de CPF"
 : `Erro: ${(error as Error).message}`;

 return jsonResponse({ erro: mensagem }, 500);
 }
});
```

---

## Tabela de cache no Supabase

Crie a tabela de cache no banco de dados Supabase para evitar consultas repetidas:

```sql
-- Migration: criar tabela de cache de CPF
CREATE TABLE IF NOT EXISTS cpf_cache (
 id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
 cpf VARCHAR(11) UNIQUE NOT NULL,
 dados JSONB NOT NULL,
 expires_at TIMESTAMPTZ NOT NULL,
 updated_at TIMESTAMPTZ DEFAULT NOW(),
 created_at TIMESTAMPTZ DEFAULT NOW()
);

-- Indice para buscas por CPF
CREATE INDEX idx_cpf_cache_cpf ON cpf_cache(cpf);

-- Indice para limpeza de cache expirado
CREATE INDEX idx_cpf_cache_expires ON cpf_cache(expires_at);

-- RLS: apenas service role pode acessar
ALTER TABLE cpf_cache ENABLE ROW LEVEL SECURITY;

-- Funcao para limpar cache expirado (executar via cron)
CREATE OR REPLACE FUNCTION limpar_cache_cpf_expirado()
RETURNS void AS $$
BEGIN
 DELETE FROM cpf_cache WHERE expires_at < NOW();
END;
$$ LANGUAGE plpgsql;
```

---

## Configuração de segredos

Armazene a chave de API como segredo do Supabase:

```bash
# Definir segredo para a Edge Function
supabase secrets set CPFHUB_API_KEY=sua_chave_aqui

# Verificar segredos configurados
supabase secrets list
```

Os segredos ficam disponíveis como variaveis de ambiente via `Deno.env.get()` dentro da Edge Function.

---

## Deploy e teste

Deploy da Edge Function:

```bash
# Deploy
supabase functions deploy validar-cpf

# Teste local antes do deploy
supabase functions serve validar-cpf --env-file .env.local
```

Teste com curl:

```bash
curl -X POST \
 "https://SEU_PROJETO.supabase.co/functions/v1/validar-cpf" \
 -H "Authorization: Bearer SEU_ANON_KEY" \
 -H "Content-Type: application/json" \
 -d '{"cpf": "12345678901"}'
```

---

## Integração com o frontend Supabase

No frontend, chame a Edge Function usando o cliente Supabase:

```typescript
// No frontend (React, Vue, Svelte, etc.)
import { createClient } from "@supabase/supabase-js";

const supabase = createClient(
 "https://SEU_PROJETO.supabase.co",
 "SUA_ANON_KEY"
);

async function validarCPF(cpf: string) {
 const { data, error } = await supabase.functions.invoke("validar-cpf", {
 body: { cpf },
 });

 if (error) {
 console.error("Erro na validacao:", error.message);
 return null;
 }

 return data;
}
```

Essa abordagem mantem a chave de API da [**CPFHub.io**](https://www.cpfhub.io/)

---

## Vantagens da arquitetura Supabase

A combinação de Edge Functions + banco PostgreSQL do Supabase oferece beneficios únicos:

* **Ecossistema unificado** -- Banco, autenticação, storage e funções serverless em uma única plataforma.
* **Cache nativo** -- O banco PostgreSQL serve como cache sem necessidade de Redis ou Memcached.
* **RLS (Row Level Security)** -- Controle granular de acesso aos dados de CPF cacheados.
* **Edge global** -- As Edge Functions executam em servidores distribuidos, minimizando latência.
* **Open source** -- Possibilidade de self-hosting para requisitos de compliance mais rigorosos.

---

## Perguntas frequentes

### Como a chave de API fica protegida em uma Supabase Edge Function?

A chave é armazenada como segredo via `supabase secrets set` e acessada exclusivamente pelo runtime Deno no servidor — nunca exposta no bundle do frontend. O cliente Supabase no navegador só tem acesso à `anon key` pública, que não carrega permissão para chamar a API de CPF diretamente.

### O que acontece se a API de CPF demorar mais do que o esperado?

A função usa `AbortController` com timeout de 10 segundos. Se a resposta não chegar nesse prazo, o fetch é cancelado e a Edge Function retorna um erro `Timeout na consulta de CPF` com status 500 — sem travar a requisição indefinidamente. A latência típica da CPFHub.io é de aproximadamente 900ms.

### A CPFHub.io bloqueia requisições quando o limite do plano é atingido?

Não. O plano gratuito inclui 50 consultas por mês sem cartão de crédito. Ao ultrapassar o limite, a API continua respondendo normalmente e cobra R$0,15 por consulta adicional — sem retornar erro de limite nem interromper o serviço. O plano Pro oferece 1.000 consultas mensais por R$149.

### Como evitar consultas duplicadas desnecessárias à API?

A arquitetura apresentada usa a tabela `cpf_cache` do PostgreSQL para armazenar resultados por 24 horas. Antes de cada consulta à API, a função verifica se há um registro válido no cache. Essa estratégia reduz o consumo de cota e melhora o tempo de resposta para CPFs consultados com frequência. Veja mais em [Como implementar cache inteligente em respostas de API de CPF](https://cpfhub.io/blog/como-implementar-cache-inteligente-respostas-api-cpf).

### Leia também

- [API de CPF grátis para desenvolvedores: como começar em 5 minutos](https://cpfhub.io/blog/api-cpf-gratis-desenvolvedores-comecar-5-minutos)
- [Como implementar cache inteligente em respostas de API de CPF](https://cpfhub.io/blog/como-implementar-cache-inteligente-respostas-api-cpf)
- [Como implementar retry e backoff exponencial em consultas de API de CPF](https://cpfhub.io/blog/como-implementar-retry-backoff-exponencial-consultas-api-cpf)
- [SLA de API de CPF: níveis de disponibilidade](https://cpfhub.io/blog/sla-api-cpf-niveis-disponibilidade)

---

## Conclusão

Supabase Edge Functions oferecem uma forma elegante de integrar a validação de CPF em aplicações que ja utilizam o ecossistema Supabase. A combinação de Deno runtime, banco PostgreSQL para cache e segredos gerenciados cria uma solução completa sem infraestrutura adicional. A API da [**CPFHub.io**](https://www.cpfhub.io/)

Cadastre-se em [cpfhub.io](https://www.cpfhub.io/)

