Como consumir API de CPF em NestJS com módulos e providers

Aprenda a consumir a API de consulta de CPF da CPFHub.io em NestJS usando módulos, providers, DTOs e o HttpModule com boas práticas.

Redação CPFHub.io
Redação CPFHub.io
··7 min de leitura
Como consumir API de CPF em NestJS com módulos e providers

O NestJS é o framework Node.js mais adotado para aplicações empresariais, com arquitetura modular inspirada no Angular. Para consumir a API de CPF da CPFHub.io, crie um módulo dedicado com HttpModule, um service injetável que faz GET para https://api.cpfhub.io/cpf/{CPF} com o header x-api-key, e um controller com DTOs validados pelo class-validator. A latência média da API é de ~900ms — configure o timeout do Axios com margem suficiente para evitar falsos timeouts.


1. Pré-requisitos

  • NestJS configurado com nest new cpf-validator.

  • Node.js 18+ instalado.

  • Pacotes adicionais: @nestjs/axios, @nestjs/config, axios, class-validator, class-transformer.

  • Uma conta na CPFHub.io


2. Instale as dependências

npm install @nestjs/axios @nestjs/config axios class-validator class-transformer

3. Configure as variáveis de ambiente

Crie o arquivo .env:

CPFHUB_API_KEY=SUA_CHAVE_DE_API
CPFHUB_BASE_URL=https://api.cpfhub.io
CPFHUB_TIMEOUT=5000

Registre o ConfigModule no AppModule:

// src/app.module.ts
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { CpfModule } from './cpf/cpf.module';

@Module({
    imports: [
    ConfigModule.forRoot({ isGlobal: true }),
    CpfModule,
    ],
})
export class AppModule {}

4. Crie o módulo de CPF

// src/cpf/cpf.module.ts
import { Module } from '@nestjs/common';
import { HttpModule } from '@nestjs/axios';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { CpfService } from './cpf.service';
import { CpfController } from './cpf.controller';

@Module({
    imports: [
    HttpModule.registerAsync({
    imports: [ConfigModule],
    inject: [ConfigService],
    useFactory: (config: ConfigService) => ({
    baseURL: config.get('CPFHUB_BASE_URL'),
    timeout: config.get<number>('CPFHUB_TIMEOUT', 5000),
    headers: {
    'x-api-key': config.get('CPFHUB_API_KEY'),
    'Accept': 'application/json',
    },
    }),
    }),
    ],
    controllers: [CpfController],
    providers: [CpfService],
    exports: [CpfService],
})
export class CpfModule {}

O HttpModule.registerAsync configura o Axios com a URL base, timeout e headers a partir das variáveis de ambiente.


5. Crie os DTOs

// src/cpf/dto/cpf-response.dto.ts
export class CpfDataDto {
    cpf: string;
    name: string;
    nameUpper: string;
    gender: string;
    birthDate: string;
    day: number;
    month: number;
    year: number;
}

export class CpfResponseDto {
    success: boolean;
    data: CpfDataDto;
}
// src/cpf/dto/cpf-param.dto.ts
import { IsString, Matches, Length } from 'class-validator';

export class CpfParamDto {
    @IsString()
    @Length(11, 11, { message: 'CPF deve conter exatamente 11 dígitos' })
    @Matches(/^\d{11}$/, { message: 'CPF deve conter apenas números' })
    cpf: string;
}

6. Crie o service

// src/cpf/cpf.service.ts
import { Injectable, HttpException, HttpStatus } from '@nestjs/common';
import { HttpService } from '@nestjs/axios';
import { firstValueFrom } from 'rxjs';
import { CpfResponseDto } from './dto/cpf-response.dto';

@Injectable()
export class CpfService {
    constructor(private readonly httpService: HttpService) {}

    async consultarCpf(cpf: string): Promise<CpfResponseDto> {
    const cpfLimpo = cpf.replace(/\D/g, '');

    try {
    const { data } = await firstValueFrom(
    this.httpService.get<CpfResponseDto>(`/cpf/${cpfLimpo}`),
    );

    return data;
    } catch (error) {
    if (error.response) {
    const status = error.response.status;
    const mensagens: Record<number, string> = {
    400: 'CPF com formato inválido',
    401: 'Chave de API inválida ou ausente',
    404: 'CPF não encontrado',
    };

    throw new HttpException(
    mensagens[status] || `Erro na API: HTTP ${status}`,
    status,
    );
    }

    if (error.code === 'ECONNABORTED') {
    throw new HttpException(
    'Timeout na consulta de CPF',
    HttpStatus.GATEWAY_TIMEOUT,
    );
    }

    throw new HttpException(
    'Falha na conexão com a API de CPF',
    HttpStatus.BAD_GATEWAY,
    );
    }
    }
}

7. Crie o controller

// src/cpf/cpf.controller.ts
import { Controller, Get, Param, UsePipes, ValidationPipe } from '@nestjs/common';
import { CpfService } from './cpf.service';
import { CpfParamDto } from './dto/cpf-param.dto';

@Controller('api/cpf')
export class CpfController {
    constructor(private readonly cpfService: CpfService) {}

    @Get(':cpf')
    @UsePipes(new ValidationPipe({ transform: true }))
    async consultar(@Param() params: CpfParamDto) {
    return this.cpfService.consultarCpf(params.cpf);
    }
}

8. Teste com cURL

Inicie a aplicação e teste:

npm run start:dev
curl -X GET http://localhost:3000/api/cpf/12345678900 \
    -H "Accept: application/json"

Resposta esperada:

{
    "success": true,
    "data": {
    "cpf": "12345678900",
    "name": "João da Silva",
    "nameUpper": "JOÃO DA SILVA",
    "gender": "M",
    "birthDate": "15/06/1990",
    "day": 15,
    "month": 6,
    "year": 1990
    }
}

9. Testes unitários

Teste o service com mock do HttpService:

// src/cpf/cpf.service.spec.ts
import { Test, TestingModule } from '@nestjs/testing';
import { HttpService } from '@nestjs/axios';
import { of } from 'rxjs';
import { CpfService } from './cpf.service';

describe('CpfService', () => {
    let service: CpfService;
    let httpService: HttpService;

    beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
    providers: [
    CpfService,
    {
    provide: HttpService,
    useValue: {
    get: jest.fn(),
    },
    },
    ],
    }).compile();

    service = module.get<CpfService>(CpfService);
    httpService = module.get<HttpService>(HttpService);
    });

    it('deve retornar dados do CPF', async () => {
    const mockResponse = {
    data: {
    success: true,
    data: {
    cpf: '12345678900',
    name: 'João da Silva',
    nameUpper: 'JOÃO DA SILVA',
    gender: 'M',
    birthDate: '15/06/1990',
    day: 15,
    month: 6,
    year: 1990,
    },
    },
    };

    jest.spyOn(httpService, 'get').mockReturnValue(of(mockResponse) as any);

    const result = await service.consultarCpf('12345678900');
    expect(result.success).toBe(true);
    expect(result.data.name).toBe('João da Silva');
    });
});

10. Boas práticas

  • Módulos -- Encapsule a integração com a CPFHub.io em um módulo dedicado que pode ser reutilizado em toda a aplicação.

  • Timeout -- Configure o timeout do HttpModule com pelo menos 5 segundos para acomodar a latência média de ~900ms da API com margem de segurança.

  • DTOs e ValidationPipe -- Valide os parâmetros de entrada com class-validator antes de chamar a API.

  • Injeção de dependência -- O padrão DI do NestJS facilita testes unitários com mocks do HttpService.

  • ConfigService -- Centralize variáveis de ambiente no ConfigModule. Nunca hardcode chaves no código.

  • Planos -- O plano gratuito inclui 50 consultas/mês. Quando o limite é atingido, a API não bloqueia: cobra R$0,15 por consulta extra. O plano Pro (R$149/mês) inclui 1.000 consultas.

A documentação oficial do NestJS detalha o HttpModule, incluindo configuração de interceptors, retry e observables com RxJS.


Perguntas frequentes

Como estruturar a integração com a API de CPF no NestJS?

Crie um módulo dedicado (CpfModule) com HttpModule.registerAsync para configurar o Axios, um service injetável para encapsular as chamadas e um controller com DTOs validados pelo class-validator. Essa separação permite reutilizar o CpfService em outros módulos da aplicação e facilita a criação de mocks nos testes unitários.

Qual timeout configurar no HttpModule para a API da CPFHub.io?

A latência média da API é de ~900ms. Configure o timeout do Axios em pelo menos 5.000ms (5 segundos) via CPFHUB_TIMEOUT no .env. Em produção com alta carga ou conexões instáveis, 8 a 10 segundos evita cancelamentos prematuros que gerariam erros desnecessários para o usuário final.

A API da CPFHub.io retorna 429 quando o limite mensal é atingido?

Não. A CPFHub.io não bloqueia requisições ao atingir o limite do plano. Quando o limite mensal é excedido, cada consulta adicional é cobrada a R$0,15 automaticamente. Por isso, remova o tratamento especial de 429 como "rate limit bloqueante" e monitore o consumo pelo painel em app.cpfhub.io/settings/billing.

Como testar o CpfService sem fazer chamadas reais à API?

Use o sistema de DI do NestJS para substituir o HttpService por um mock com jest.fn(). O TestingModule permite compilar o módulo com providers alternativos, simulando respostas da API sem consumir consultas reais do plano — o que mantém o ambiente de testes isolado e previsível.


Conclusão

O NestJS oferece a melhor estrutura no ecossistema Node.js para integrar a API da CPFHub.io

Cadastre-se em cpfhub.io

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