Introdução
Angular é um dos frameworks front-end mais utilizados em projetos corporativos no Brasil, especialmente em fintechs, bancos e sistemas de gestão. Em muitos desses projetos, a validação de CPF é um requisito obrigatório -- seja no cadastro de usuários, no checkout de uma loja ou na abertura de conta digital.
Embora a validação dos dígitos verificadores possa ser feita localmente, confirmar que o CPF realmente existe e obter os dados do titular exige uma consulta a uma API externa. A CPFHub.io oferece uma API REST simples de integrar em qualquer projeto Angular, com autenticação via header e resposta JSON tipada.
Arquitetura da solução
A integração será organizada em três camadas:
-
Service -- Encapsula a chamada à API da CPFHub.io e expõe métodos tipados para o resto da aplicação.
-
Interceptor -- Adiciona automaticamente o header
x-api-keyem todas as requisições para a API, centralizando a autenticação. -
Componente com Reactive Forms -- Formulário que coleta o CPF, aciona a validação e exibe os dados retornados.
Essa separação de responsabilidades segue as boas práticas do Angular e facilita testes unitários e manutenção.
Configurando o ambiente
Variáveis de ambiente
Primeiro, configure a chave de API nas variáveis de ambiente do Angular. Nunca coloque a chave diretamente no código-fonte.
// src/environments/environment.ts
export const environment = {
production: false,
cpfhubApiUrl: 'https://api.cpfhub.io',
cpfhubApiKey: 'SUA_CHAVE_DE_API'
};
Importar HttpClientModule
No módulo principal, importe o HttpClientModule:
// src/app/app.module.ts
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { CpfhubInterceptor } from './interceptors/cpfhub.interceptor';
@NgModule({
imports: [
HttpClientModule,
// ...outros imports
],
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: CpfhubInterceptor,
multi: true
}
]
})
export class AppModule {}
Criando o interceptor de autenticação
O interceptor adiciona automaticamente os headers necessários em todas as requisições direcionadas à API da CPFHub.io. Isso evita repetição de código e garante que a autenticação nunca seja esquecida.
// src/app/interceptors/cpfhub.interceptor.ts
import { Injectable } from '@angular/core';
import {
HttpInterceptor,
HttpRequest,
HttpHandler,
HttpEvent
} from '@angular/common/http';
import { Observable } from 'rxjs';
import { environment } from '../../environments/environment';
@Injectable()
export class CpfhubInterceptor implements HttpInterceptor {
intercept(
req: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
if (req.url.startsWith(environment.cpfhubApiUrl)) {
const authReq = req.clone({
setHeaders: {
'x-api-key': environment.cpfhubApiKey,
'Accept': 'application/json'
}
});
return next.handle(authReq);
}
return next.handle(req);
}
}
O interceptor verifica se a URL da requisição pertence à API da CPFHub.io antes de adicionar os headers. Isso garante que a chave de API não seja enviada para outros serviços.
Criando o service de consulta de CPF
O service encapsula toda a lógica de comunicação com a API e expõe interfaces tipadas.
Definindo as interfaces
// src/app/models/cpf-response.model.ts
export interface CpfData {
cpf: string;
name: string;
nameUpper: string;
gender: string;
birthDate: string;
day: number;
month: number;
year: number;
}
export interface CpfResponse {
success: boolean;
data: CpfData;
}
Implementando o service
// src/app/services/cpfhub.service.ts
import { Injectable } from '@angular/core';
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError, timeout } from 'rxjs/operators';
import { CpfResponse } from '../models/cpf-response.model';
import { environment } from '../../environments/environment';
@Injectable({
providedIn: 'root'
})
export class CpfhubService {
private readonly apiUrl = environment.cpfhubApiUrl;
constructor(private http: HttpClient) {}
consultarCpf(cpf: string): Observable<CpfResponse> {
const cpfLimpo = cpf.replace(/\D/g, '');
return this.http
.get<CpfResponse>(`${this.apiUrl}/cpf/${cpfLimpo}`)
.pipe(
timeout(10000),
catchError(this.handleError)
);
}
private handleError(error: HttpErrorResponse) {
let mensagem = 'Erro desconhecido na consulta de CPF.';
if (error.status === 400) {
mensagem = 'CPF informado está em formato inválido.';
} else if (error.status === 401) {
mensagem = 'Chave de API inválida ou ausente.';
} else if (error.status === 429) {
mensagem = 'Limite de requisições excedido. Tente novamente em instantes.';
} else if (error.status === 500) {
mensagem = 'Erro interno do servidor. Tente novamente.';
}
return throwError(() => new Error(mensagem));
}
}
Validação local dos dígitos verificadores
Antes de consumir uma consulta da API, é boa prática validar os dígitos verificadores localmente. Isso evita gastar consultas com CPFs matematicamente inválidos.
// src/app/validators/cpf.validator.ts
import { AbstractControl, ValidationErrors, ValidatorFn } from '@angular/forms';
export function cpfValidator(): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
const cpf = control.value?.replace(/\D/g, '');
if (!cpf || cpf.length !== 11) {
return { cpfInvalido: true };
}
// Rejeitar sequências repetidas
if (/^(\d)\1{10}$/.test(cpf)) {
return { cpfInvalido: true };
}
// Validar primeiro dígito verificador
let soma = 0;
for (let i = 0; i < 9; i++) {
soma += parseInt(cpf.charAt(i)) * (10 - i);
}
let resto = (soma * 10) % 11;
if (resto === 10) resto = 0;
if (resto !== parseInt(cpf.charAt(9))) {
return { cpfInvalido: true };
}
// Validar segundo dígito verificador
soma = 0;
for (let i = 0; i < 10; i++) {
soma += parseInt(cpf.charAt(i)) * (11 - i);
}
resto = (soma * 10) % 11;
if (resto === 10) resto = 0;
if (resto !== parseInt(cpf.charAt(10))) {
return { cpfInvalido: true };
}
return null;
};
}
Criando o componente de formulário
Com o service, o interceptor e o validator prontos, vamos criar o componente que une tudo.
Template HTML
<!-- src/app/components/cpf-form/cpf-form.component.html -->
<form [formGroup]="cpfForm" (ngSubmit)="onSubmit()">
<div class="campo">
<label for="cpf">CPF</label>
<input
id="cpf"
formControlName="cpf"
placeholder="000.000.000-00"
maxlength="14"
/>
<span *ngIf="cpfForm.get('cpf')?.hasError('cpfInvalido')" class="erro">
CPF inválido.
</span>
</div>
<button type="submit" [disabled]="cpfForm.invalid || carregando">
{{ carregando ? 'Consultando...' : 'Consultar CPF' }}
</button>
</form>
<div *ngIf="dadosCpf" class="resultado">
<h3>Dados do titular</h3>
<p><strong>Nome:</strong> {{ dadosCpf.name }}</p>
<p><strong>Gênero:</strong> {{ dadosCpf.gender === 'M' ? 'Masculino' : 'Feminino' }}</p>
<p><strong>Data de nascimento:</strong> {{ dadosCpf.birthDate }}</p>
</div>
<div *ngIf="erro" class="erro-consulta">
<p>{{ erro }}</p>
</div>
Componente TypeScript
// src/app/components/cpf-form/cpf-form.component.ts
import { Component } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { CpfhubService } from '../../services/cpfhub.service';
import { CpfData } from '../../models/cpf-response.model';
import { cpfValidator } from '../../validators/cpf.validator';
@Component({
selector: 'app-cpf-form',
templateUrl: './cpf-form.component.html'
})
export class CpfFormComponent {
cpfForm: FormGroup;
dadosCpf: CpfData | null = null;
carregando = false;
erro: string | null = null;
constructor(
private fb: FormBuilder,
private cpfhubService: CpfhubService
) {
this.cpfForm = this.fb.group({
cpf: ['', [Validators.required, cpfValidator()]]
});
}
onSubmit(): void {
if (this.cpfForm.invalid) return;
this.carregando = true;
this.erro = null;
this.dadosCpf = null;
const cpf = this.cpfForm.get('cpf')?.value;
this.cpfhubService.consultarCpf(cpf).subscribe({
next: (response) => {
this.dadosCpf = response.data;
this.carregando = false;
},
error: (err) => {
this.erro = err.message;
this.carregando = false;
}
});
}
}
Testando a integração
Teste unitário do service
// src/app/services/cpfhub.service.spec.ts
import { TestBed } from '@angular/core/testing';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { CpfhubService } from './cpfhub.service';
describe('CpfhubService', () => {
let service: CpfhubService;
let httpMock: HttpTestingController;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [CpfhubService]
});
service = TestBed.inject(CpfhubService);
httpMock = TestBed.inject(HttpTestingController);
});
it('deve consultar CPF com sucesso', () => {
const mockResponse = {
success: true,
data: {
cpf: '12345678900',
name: 'João da Silva',
nameUpper: 'JOAO DA SILVA',
gender: 'M',
birthDate: '15/06/1990',
day: 15,
month: 6,
year: 1990
}
};
service.consultarCpf('123.456.789-00').subscribe((res) => {
expect(res.success).toBeTrue();
expect(res.data.name).toBe('João da Silva');
});
const req = httpMock.expectOne(
'https://api.cpfhub.io/cpf/12345678900'
);
expect(req.request.method).toBe('GET');
req.flush(mockResponse);
});
});
Boas práticas de segurança
Nunca exponha a chave de API no frontend
O exemplo acima armazena a chave nas variáveis de ambiente do Angular, mas lembre-se: essas variáveis são incluídas no bundle de produção e ficam visíveis no código-fonte do navegador.
Para produção, a abordagem recomendada é criar um endpoint backend (BFF -- Backend for Frontend) que faz a chamada à API da CPFHub.io e repassa os dados ao frontend:
// Backend (Express.js como BFF)
const express = require('express');
const app = express();
app.get('/api/cpf/:cpf', async (req, res) => {
const { cpf } = req.params;
const response = await fetch(
`https://api.cpfhub.io/cpf/${cpf}`,
{
headers: {
'x-api-key': process.env.CPFHUB_API_KEY,
'Accept': 'application/json'
}
}
);
const data = await response.json();
res.json(data);
});
app.listen(3000);
Dessa forma, a chave de API fica protegida no servidor e o frontend consome apenas o seu BFF.
Perguntas frequentes
O que é necessário para implementar validação de CPF neste contexto?
A validação de CPF exige uma chamada à API com o número do documento e a chave de autenticação. A CPFHub.io retorna o status do CPF, nome do titular e data de nascimento em menos de 200ms, permitindo a verificação em tempo real durante o cadastro ou transação.
A API CPFHub.io funciona para todos os volumes de consulta?
Sim. O plano gratuito oferece 50 consultas por mês sem cartão de crédito — ideal para testes e projetos pequenos. Para volumes maiores, o plano Pro inclui 1.000 consultas mensais por R$149. Se o limite for ultrapassado, a API não bloqueia: cobra R$0,15 por consulta adicional.
Como garantir conformidade com a LGPD ao usar uma API de CPF?
Use o CPF apenas para a finalidade declarada ao titular, armazene apenas o necessário (não guarde o CPF cru se um token bastar), implemente controle de acesso aos logs de consulta e documente a base legal para o tratamento. A ANPD orienta que dados de identificação devem ser tratados com o princípio da necessidade.
Quanto tempo leva para integrar a API CPFHub.io?
A integração básica leva menos de 30 minutos: crie uma conta em cpfhub.io, gere a API key no painel e faça uma chamada GET para https://api.cpfhub.io/cpf/{CPF} com o header x-api-key. A documentação inclui exemplos em Python, Node.js, PHP, Java e outras linguagens.
Conclusão
Integrar validação de CPF em aplicações Angular é um processo estruturado quando se utilizam services, interceptors e reactive forms. O service encapsula a lógica de consulta, o interceptor centraliza a autenticação e os reactive forms garantem uma experiência fluida para o usuário. Acesse cpfhub.io para criar sua conta — o plano gratuito com 50 consultas mensais está disponível sem cartão de crédito para validar a integração antes de ir a produção.
CPFHub.io
Pronto para integrar a API?
50 consultas gratuitas para testar agora. Sem cartão de crédito. Acesso imediato à documentação.
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.



