Como integrar a API de CPF em uma aplicação Phoenix

Aprenda a integrar a API de consulta de CPF em uma aplicação Phoenix com controllers, contexts e LiveView.

Redação CPFHub.io
Redação CPFHub.io
··6 min de leitura
Como integrar a API de CPF em uma aplicação Phoenix

O Phoenix é o framework web mais popular do ecossistema Elixir, e integrar a API de consulta de CPF do CPFHub.io nele é direto: crie um context dedicado, configure o Tesla como cliente HTTP e exponha um endpoint REST ou um LiveView. Em menos de uma tarde, sua aplicação Phoenix estará validando e enriquecendo dados de CPF em tempo real com latência de ~900ms por consulta.

Introdução

O Phoenix é o framework web mais popular do ecossistema Elixir, conhecido por sua performance excepcional e escalabilidade. Integrar a API de consulta de CPF do CPFHub.io em uma aplicação Phoenix permite oferecer validação e enriquecimento de dados de forma eficiente.


Configurando o projeto Phoenix

Crie uma nova aplicação Phoenix e adicione as dependências:

# mix.exs
defp deps do
    [
    {:phoenix, "~> 1.7"},
    {:phoenix_live_view, "~> 0.20"},
    {:tesla, "~> 1.8"},
    {:hackney, "~> 1.20"},
    {:jason, "~> 1.4"}
    ]
end

Adicione a configuração da API no config/config.exs:

# config/config.exs
config :minha_app, :cpfhub,
    base_url: "https://api.cpfhub.io",
    api_key: System.get_env("CPFHUB_API_KEY")

Criando o context de CPF

Seguindo o padrão de contexts do Phoenix, crie um módulo dedicado à lógica de CPF:

defmodule MinhaApp.Cpf do
    @moduledoc """
    Context para operações relacionadas a CPF.
    """

    alias MinhaApp.Cpf.ApiClient

    def consultar(cpf) do
    cpf_limpo = String.replace(cpf, ~r/\D/, "")

    with :ok <- validar_formato(cpf_limpo),
    {:ok, dados} <- ApiClient.consultar(cpf_limpo) do
    {:ok, dados}
    end
    end

    def validar_formato(cpf) when byte_size(cpf) == 11 do
    digitos = cpf
    |> String.graphemes()
    |> Enum.map(&String.to_integer/1)

    if Enum.uniq(digitos) |> length() == 1 do
    {:error, :digitos_repetidos}
    else
    :ok
    end
    end

    def validar_formato(_cpf), do: {:error, :formato_invalido}
end

Implementando o cliente da API

Utilize Tesla com middlewares para criar um cliente robusto:

defmodule MinhaApp.Cpf.ApiClient do
    use Tesla

    @config Application.compile_env(:minha_app, :cpfhub, [])

    plug Tesla.Middleware.BaseUrl, @config[:base_url] || "https://api.cpfhub.io"
    plug Tesla.Middleware.JSON
    plug Tesla.Middleware.Headers, [{"x-api-key", @config[:api_key] || ""}]
    plug Tesla.Middleware.Timeout, timeout: 10_000
    plug Tesla.Middleware.Retry, delay: 500, max_retries: 2

    def consultar(cpf) do
    case get("/cpf/#{cpf}") do
    {:ok, %Tesla.Env{status: 200, body: %{"success" => true, "data" => data}}} ->
    {:ok, parse_data(data)}

    {:ok, %Tesla.Env{status: 404}} ->
    {:error, :cpf_nao_encontrado}

    {:ok, %Tesla.Env{status: 401}} ->
    {:error, :chave_invalida}

    {:ok, %Tesla.Env{status: status}} ->
    {:error, {:status_inesperado, status}}

    {:error, reason} ->
    {:error, {:falha_conexao, reason}}
    end
    end

    defp parse_data(data) do
    %{
    cpf: data["cpf"],
    nome: data["name"],
    nome_upper: data["nameUpper"],
    genero: data["gender"],
    data_nascimento: data["birthDate"],
    dia: data["day"],
    mes: data["month"],
    ano: data["year"]
    }
    end
end

Criando o controller

Exponha um endpoint REST para consulta de CPF:

defmodule MinhaAppWeb.CpfController do
    use MinhaAppWeb, :controller

    alias MinhaApp.Cpf

    def show(conn, %{"cpf" => cpf}) do
    case Cpf.consultar(cpf) do
    {:ok, dados} ->
    conn
    |> put_status(:ok)
    |> json(%{success: true, data: dados})

    {:error, :cpf_nao_encontrado} ->
    conn
    |> put_status(:not_found)
    |> json(%{success: false, message: "CPF não encontrado"})

    {:error, :formato_invalido} ->
    conn
    |> put_status(:bad_request)
    |> json(%{success: false, message: "Formato de CPF inválido"})

    {:error, _reason} ->
    conn
    |> put_status(:bad_gateway)
    |> json(%{success: false, message: "Erro ao consultar API externa"})
    end
    end
end
RotaMétodoControllerAction
/api/cpf/:cpfGETCpfControllershow
Resposta 200-JSON com dadosSucesso
Resposta 404-JSON com mensagemNão encontrado
Resposta 400-JSON com mensagemFormato inválido

Integrando com Phoenix LiveView

Para uma experiência interativa sem JavaScript, utilize LiveView:

defmodule MinhaAppWeb.CpfLive do
    use MinhaAppWeb, :live_view

    alias MinhaApp.Cpf

    def mount(_params, _session, socket) do
    {:ok, assign(socket, cpf: "", resultado: nil, loading: false, erro: nil)}
    end

    def handle_event("consultar", %{"cpf" => cpf}, socket) do
    socket = assign(socket, loading: true, erro: nil, resultado: nil)

    case Cpf.consultar(cpf) do
    {:ok, dados} ->
    {:noreply, assign(socket, resultado: dados, loading: false)}

    {:error, reason} ->
    mensagem = mensagem_erro(reason)
    {:noreply, assign(socket, erro: mensagem, loading: false)}
    end
    end

    defp mensagem_erro(:cpf_nao_encontrado), do: "CPF não encontrado na base"
    defp mensagem_erro(:formato_invalido), do: "Formato de CPF inválido"
    defp mensagem_erro(:chave_invalida), do: "Chave de API inválida"
    defp mensagem_erro(_), do: "Erro ao consultar o serviço"
end

Perguntas frequentes

Por que usar Tesla em vez de HTTPoison para integrar a API de CPF no Phoenix?

Tesla utiliza um modelo de middleware componível que permite empilhar comportamentos — autenticação, timeout, retry e logging — sem alterar o cliente base. Para integrações com a API CPFHub.io em Phoenix, isso significa adicionar Tesla.Middleware.Retry para lidar com falhas transitórias e Tesla.Middleware.Timeout para garantir que nenhuma consulta trave o processo, sem duplicar lógica no controller. A documentação do Tesla está disponível em hexdocs.pm/tesla.

Como estruturar o context de CPF para seguir os padrões do Phoenix?

O context MinhaApp.Cpf deve encapsular toda a lógica de domínio — validação de formato, chamada à API e transformação de dados — deixando o controller apenas com responsabilidades de HTTP. Isso facilita testes unitários do context sem depender de HTTP e permite substituir o client HTTP por um mock em testes.

A API CPFHub.io retorna HTTP 429 quando o limite de consultas é atingido?

Não. A CPFHub.io não bloqueia requisições ao atingir o limite do plano: consultas excedentes são cobradas a R$ 0,15 cada. O plano gratuito oferece 50 consultas mensais sem cartão de crédito; o plano Pro inclui 1.000 consultas por R$ 149/mês com o mesmo modelo de excedente.

Como testar a integração com a API de CPF em aplicações Phoenix?

Use Mox para criar um mock do ApiClient e isolar os testes do context de CPF. Defina um behaviour com consultar/1 e configure o mock para retornar tuplas de sucesso ou erro. Isso garante testes rápidos e determinísticos sem depender de rede ou quota da API.


Conclusão

Integrar a API de CPF em uma aplicação Phoenix resulta em um sistema bem estruturado, com separação clara entre contexts, controllers e views. O LiveView adiciona interatividade sem a complexidade de JavaScript frontend.

Cadastre-se em cpfhub.io — 50 consultas mensais gratuitas, sem cartão de crédito — e comece a construir sua integração Phoenix com dados cadastrais reais em minutos.

CPFHub.io

Pronto para integrar a API?

50 consultas gratuitas para testar agora. Sem cartão de crédito. Acesso imediato à documentação.

Redação CPFHub.io

Sobre a redação

Redação CPFHub.io

Time editorial especializado em APIs de CPF, identidade digital e compliance no mercado brasileiro. Produzimos guias técnicos, análises regulatórias e tutoriais sobre LGPD e KYC para desenvolvedores e líderes de produto.

WhatsAppFale conosco via WhatsApp