# Como consumir API de CPF em Zig para aplicações de alta performance

> Aprenda a consumir a API de CPF da CPFHub.io em Zig usando std.http.Client para aplicações de alta performance e baixa latência.

**Publicado:** 22/07/2026
**Autor:** Redação CPFHub.io
**URL:** https://cpfhub.io/blog/como-consumir-api-de-cpf-em-zig-para-aplicacoes-de-alta-performance

---


O **Zig** é uma linguagem de sistemas sem garbage collector que oferece controle manual de memória, excelente interoperabilidade com C e compilação para binários enxutos — características ideais para aplicações de alta performance que precisam validar CPF com latência previsível. Para consumir a API da CPFHub.io em Zig, use `std.http.Client` com um `GET https://api.cpfhub.io/cpf/{CPF}` autenticado pelo header `x-api-key`; a resposta chega em ~900ms e traz nome, data de nascimento e status do documento. Consulte a [documentação oficial do Zig](https://ziglang.org/documentation/master/) para instalar o toolchain antes de começar.

---

## 1. Pré-requisitos

* **Zig 0.13+** instalado.

* Uma conta gratuita na [**CPFHub.io**](https://www.cpfhub.io/)

---

## 2. Estrutura do projeto

Crie a estrutura básica do projeto Zig:

```
cpf-validator-zig/
├── build.zig
├── build.zig.zon
└── src/
 ├── main.zig
 ├── cpfhub.zig
 └── json_parser.zig
```

---

## 3. Configure o build.zig

```zig
// build.zig
const std = @import("std");

pub fn build(b: *std.Build) void {
 const target = b.standardTargetOptions(.{});
 const optimize = b.standardOptimizeOption(.{});

 const exe = b.addExecutable(.{
 .name = "cpf-validator",
 .root_source_file = b.path("src/main.zig"),
 .target = target,
 .optimize = optimize,
 });

 b.installArtifact(exe);

 const run_cmd = b.addRunArtifact(exe);
 run_cmd.step.dependOn(b.getInstallStep());

 const run_step = b.step("run", "Run the application");
 run_step.dependOn(&run_cmd.step);
}
```

---

## 4. Implemente o cliente HTTP

Crie o módulo de consulta de CPF usando `std.http.Client`:

```zig
// src/cpfhub.zig
const std = @import("std");
const http = std.http;
const mem = std.mem;
const json = std.json;

pub const CpfData = struct {
 cpf: []const u8 = "",
 name: []const u8 = "",
 nameUpper: []const u8 = "",
 gender: []const u8 = "",
 birthDate: []const u8 = "",
 day: u32 = 0,
 month: u32 = 0,
 year: u32 = 0,
};

pub const CpfError = error{
 InvalidCpf,
 NotFound,
 Unauthorized,
 RateLimited,
 Timeout,
 ConnectionError,
 ParseError,
 ApiError,
};

pub const Config = struct {
 api_key: []const u8,
 base_url: []const u8 = "https://api.cpfhub.io",
 timeout_ns: u64 = 5 * std.time.ns_per_s,
};

/// Remove caracteres não numéricos do CPF.
pub fn limparCpf(cpf: []const u8, buf: []u8) ![]u8 {
 var len: usize = 0;
 for (cpf) |c| {
 if (c >= '0' and c <= '9') {
 if (len >= buf.len) return error.BufferTooSmall;
 buf[len] = c;
 len += 1;
 }
 }
 return buf[0..len];
}

/// Consulta dados de um CPF na API da CPFHub.io.
pub fn consultarCpf(
 allocator: mem.Allocator,
 config: Config,
 cpf: []const u8,
) !CpfData {
 // Limpar CPF
 var cpf_buf: [11]u8 = undefined;
 const cpf_limpo = limparCpf(cpf, &cpf_buf) catch {
 return CpfError.InvalidCpf;
 };

 if (cpf_limpo.len != 11) {
 return CpfError.InvalidCpf;
 }

 // Construir URL
 var url_buf: [256]u8 = undefined;
 const url = std.fmt.bufPrint(&url_buf, "{s}/cpf/{s}", .{
 config.base_url,
 cpf_limpo,
 }) catch {
 return CpfError.ApiError;
 };

 // Criar cliente HTTP
 var client = http.Client{ .allocator = allocator };
 defer client.deinit();

 // Configurar URI
 const uri = std.Uri.parse(url) catch {
 return CpfError.ApiError;
 };

 // Headers
 const headers = http.Header{
 .name = "x-api-key",
 .value = config.api_key,
 };
 const accept_header = http.Header{
 .name = "Accept",
 .value = "application/json",
 };

 var extra_headers = [_]http.Header{ headers, accept_header };

 // Fazer requisição
 var req = client.open(.GET, uri, .{
 .extra_headers = &extra_headers,
 .keep_alive = false,
 }) catch {
 return CpfError.ConnectionError;
 };
 defer req.deinit();

 req.send() catch {
 return CpfError.ConnectionError;
 };
 req.wait() catch {
 return CpfError.Timeout;
 };

 // Verificar status
 // Nota: a CPFHub.io não retorna 429 ao atingir o limite — cobra R$0,15/consulta adicional.
 const status = req.response.status;
 switch (status) {
 .ok => {},
 .bad_request => return CpfError.InvalidCpf,
 .unauthorized => return CpfError.Unauthorized,
 .not_found => return CpfError.NotFound,
 else => return CpfError.ApiError,
 }

 // Ler body
 var body_buf: [4096]u8 = undefined;
 const body_len = req.reader().readAll(&body_buf) catch {
 return CpfError.ParseError;
 };
 const body = body_buf[0..body_len];

 // Parsear JSON
 const parsed = json.parseFromSlice(
 struct {
 success: bool,
 data: CpfData,
 },
 allocator,
 body,
 .{},
 ) catch {
 return CpfError.ParseError;
 };
 defer parsed.deinit();

 if (!parsed.value.success) {
 return CpfError.ApiError;
 }

 return parsed.value.data;
}
```

---

## 5. Implemente o ponto de entrada

```zig
// src/main.zig
const std = @import("std");
const cpfhub = @import("cpfhub.zig");

pub fn main() !void {
 const allocator = std.heap.page_allocator;
 const stdout = std.io.getStdOut().writer();

 const config = cpfhub.Config{
 .api_key = "SUA_CHAVE_DE_API",
 .base_url = "https://api.cpfhub.io",
 .timeout_ns = 5 * std.time.ns_per_s,
 };

 const cpf = "12345678900";

 try stdout.print("Consultando CPF: {s}\n", .{cpf});

 const resultado = cpfhub.consultarCpf(allocator, config, cpf) catch |err| {
 const msg = switch (err) {
 cpfhub.CpfError.InvalidCpf => "CPF invalido",
 cpfhub.CpfError.NotFound => "CPF nao encontrado",
 cpfhub.CpfError.Unauthorized => "Chave de API invalida",
 cpfhub.CpfError.RateLimited => "Rate limit excedido",
 cpfhub.CpfError.Timeout => "Timeout na consulta",
 cpfhub.CpfError.ConnectionError => "Erro de conexao",
 cpfhub.CpfError.ParseError => "Erro ao processar resposta",
 cpfhub.CpfError.ApiError => "Erro da API",
 else => "Erro desconhecido",
 };
 try stdout.print("Erro: {s}\n", .{msg});
 return;
 };

 try stdout.print("\n--- Resultado ---\n", .{});
 try stdout.print("Nome: {s}\n", .{resultado.name});
 try stdout.print("CPF: {s}\n", .{resultado.cpf});
 try stdout.print("Genero: {s}\n", .{resultado.gender});
 try stdout.print("Nascimento: {s}\n", .{resultado.birthDate});
}
```

---

## 6. Compile e execute

```bash
zig build run
```

Saída esperada:

```
Consultando CPF: 12345678900

--- Resultado ---
Nome: João da Silva
CPF: 12345678900
Genero: M
Nascimento: 15/06/1990
```

---

## 7. Versão com servidor HTTP

Para expor a consulta como endpoint HTTP usando `std.http.Server`:

```zig
// src/server.zig
const std = @import("std");
const cpfhub = @import("cpfhub.zig");

pub fn main() !void {
 const allocator = std.heap.page_allocator;

 var server = std.http.Server.init(allocator, .{
 .reuse_address = true,
 });
 defer server.deinit();

 const address = std.net.Address.parseIp("0.0.0.0", 8080) catch unreachable;
 server.listen(address) catch |err| {
 std.log.err("Erro ao iniciar servidor: {}", .{err});
 return;
 };

 std.log.info("Servidor iniciado na porta 8080", .{});

 while (true) {
 var response = server.accept() catch continue;
 defer response.deinit();

 handleRequest(allocator, &response) catch |err| {
 std.log.err("Erro ao processar requisição: {}", .{err});
 };
 }
}

fn handleRequest(
 allocator: std.mem.Allocator,
 response: *std.http.Server.Response,
) !void {
 const config = cpfhub.Config{
 .api_key = "SUA_CHAVE_DE_API",
 };

 // Extrair CPF da URL (esperado: /api/cpf/12345678900)
 const path = response.request.target;

 if (!std.mem.startsWith(u8, path, "/api/cpf/")) {
 response.status = .not_found;
 try response.do_send();
 return;
 }

 const cpf = path[9..];

 const resultado = cpfhub.consultarCpf(allocator, config, cpf) catch {
 response.status = .internal_server_error;
 try response.do_send();
 return;
 };

 // Construir resposta JSON
 var buf: [1024]u8 = undefined;
 const json_response = std.fmt.bufPrint(&buf,
 \\{{"success":true,"data":{{"cpf":"{s}","name":"{s}","gender":"{s}","birthDate":"{s}"}}}}
 , .{
 resultado.cpf,
 resultado.name,
 resultado.gender,
 resultado.birthDate,
 }) catch {
 response.status = .internal_server_error;
 try response.do_send();
 return;
 };

 response.status = .ok;
 response.transfer_encoding = .{ .content_length = json_response.len };
 try response.do_send();
 _ = try response.write(json_response);
 try response.finish();
}
```

---

## 8. Benchmarks de performance

O Zig permite executar benchmarks simples para medir a latência da integração:

```zig
// src/benchmark.zig
const std = @import("std");
const cpfhub = @import("cpfhub.zig");

pub fn main() !void {
 const allocator = std.heap.page_allocator;
 const stdout = std.io.getStdOut().writer();

 const config = cpfhub.Config{
 .api_key = "SUA_CHAVE_DE_API",
 };

 const iterations = 10;
 var total_ns: u64 = 0;

 for (0..iterations) |i| {
 const start = std.time.nanoTimestamp();

 _ = cpfhub.consultarCpf(allocator, config, "12345678900") catch {};

 const elapsed = @as(u64, @intCast(std.time.nanoTimestamp() - start));
 total_ns += elapsed;

 try stdout.print("Iteração {d}: {d}ms\n", .{
 i + 1,
 elapsed / std.time.ns_per_ms,
 });
 }

 try stdout.print("\nMédia: {d}ms\n", .{
 total_ns / iterations / std.time.ns_per_ms,
 });
}
```

Espere latências em torno de ~900ms por consulta, tempo que reflete o processamento da API — o overhead do cliente Zig é desprezível.

---

## 9. Boas práticas

* **Alocação** -- Use alocadores explícitos para controle total de memória. Prefira `page_allocator` para simplicidade ou `ArenaAllocator` para performance.

* **Buffers fixos** -- Use buffers de tamanho fixo na stack para dados previsíveis, evitando alocações no heap.

* **Erros** -- Use o sistema de erros do Zig (error unions) para tratamento explícito e sem overhead de exceções.

* **Timeout** -- Configure timeout na requisição HTTP para evitar bloqueios indefinidos, respeitando a latência de ~900ms da API.

* **Compilação** -- Use `zig build -Doptimize=ReleaseFast` para máxima performance em produção.

* **LGPD** -- A API da CPFHub.io é 100% compatível com a LGPD. Em aplicações de alta performance, garanta que logs e buffers contendo dados pessoais sejam limpos adequadamente.

---

## Perguntas frequentes

### Por que usar Zig para consumir uma API de CPF em vez de linguagens como Go ou Rust?

Zig oferece controle total sobre alocações de memória e zero overhead de runtime, o que o torna adequado quando o serviço de consulta de CPF precisa coexistir com código C legado ou operar em ambientes com memória restrita. Para a maioria dos projetos web, Go ou Rust entregam produtividade maior; Zig brilha em integrações de baixo nível com código C ou em ferramentas de sistema onde cada byte importa.

### Como configurar o timeout da requisição HTTP em Zig para respeitar a latência da API?

A API da CPFHub.io responde em ~900ms. No cliente Zig com `std.http.Client`, configure `timeout_ns` com pelo menos 5 segundos (`5 * std.time.ns_per_s`) para absorver variações de rede sem falsos timeouts. Ajuste conforme o SLA do seu serviço — ambientes com latência de rede alta podem precisar de 8 a 10 segundos.

### O que acontece se o limite do plano gratuito for ultrapassado durante os benchmarks?

A CPFHub.io não bloqueia requisições ao atingir o limite do plano gratuito (50 consultas/mês). Cada consulta adicional é cobrada a R$0,15 automaticamente. Ao rodar benchmarks com múltiplas iterações, monitore o consumo no painel para evitar cobranças não planejadas — ou use o plano Pro com 1.000 consultas por R$149/mês.

### Como garantir que buffers Zig com dados de CPF sejam limpos após o uso?

Use `@memset` para zerar explicitamente qualquer buffer que tenha armazenado CPF ou dados pessoais antes de liberá-lo ou reutilizá-lo. O Zig não inicializa memória automaticamente, o que exige disciplina do desenvolvedor — mas também garante que nenhum dado sensível vaze entre requisições em buffers reutilizados.

---

### Leia também

- [Como validar CPF no frontend com React e API REST](https://cpfhub.io/blog/como-validar-cpf-no-frontend-com-react-e-api-rest)
- [Como consumir API de CPF em Rust com reqwest e serde](https://cpfhub.io/blog/como-consumir-api-de-cpf-em-rust-com-reqwest-e-serde)
- [Como consumir API de CPF em Go com net/http e tratamento de erros](https://cpfhub.io/blog/como-consumir-api-de-cpf-em-go-com-net-http-e-tratamento-de-erros)
- [Boas práticas para consumir APIs de CPF de forma segura](https://cpfhub.io/blog/boas-praticas-consumir-apis-cpf-segura)

---

## Conclusão

Consumir a API da [**CPFHub.io**](https://www.cpfhub.io/)

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

