Para consumir a API de CPF da CPFHub.io em Flutter, adicione o pacote http ao pubspec.yaml, crie um serviço Dart que faz GET https://api.cpfhub.io/cpf/{CPF} com o header x-api-key e modele a resposta JSON em uma classe CpfData. O plano gratuito oferece 50 consultas/mês sem cartão, suficiente para desenvolvimento e testes em qualquer plataforma suportada pelo Flutter.
Introdução
O Flutter se tornou uma das plataformas mais populares para o desenvolvimento de aplicativos multiplataforma, permitindo criar aplicações para Android, iOS, web e desktop a partir de uma única base de código em Dart. Para aplicativos brasileiros que envolvem cadastro de usuários, o CPF é o documento de identificação mais utilizado e sua validação via API garante que os dados coletados sejam confiáveis.
Pré-requisitos
- Flutter SDK -- Versão 3.0 ou superior.
- Dart 3.0+ -- Incluído com o Flutter SDK.
- Conta na CPFHub.io -- Para obter a chave de API. O plano gratuito oferece 50 consultas/mês sem cartão de crédito.
- Pacote http -- Para realizar requisições HTTP.
Adicionando a dependência
No arquivo pubspec.yaml, adicione o pacote http:
dependencies:
flutter:
sdk: flutter
http: ^1.2.0
Execute flutter pub get para instalar a dependência.
Modelando a resposta da API
Crie um modelo Dart para representar os dados retornados pela API:
class CpfData {
final String cpf;
final String name;
final String nameUpper;
final String gender;
final String birthDate;
final int day;
final int month;
final int year;
CpfData({
required this.cpf,
required this.name,
required this.nameUpper,
required this.gender,
required this.birthDate,
required this.day,
required this.month,
required this.year,
});
factory CpfData.fromJson(Map<String, dynamic> json) {
return CpfData(
cpf: json['cpf'] as String,
name: json['name'] as String,
nameUpper: json['nameUpper'] as String,
gender: json['gender'] as String,
birthDate: json['birthDate'] as String,
day: json['day'] as int,
month: json['month'] as int,
year: json['year'] as int,
);
}
}
A resposta da API tem o seguinte formato:
{
"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
}
}
Criando o serviço de consulta
Implemente o serviço que encapsula a chamada à API:
import 'dart:convert';
import 'package:http/http.dart' as http;
class CpfService {
static const String _baseUrl = 'https://api.cpfhub.io/cpf/';
final String apiKey;
CpfService({required this.apiKey});
Future<CpfData> consultarCpf(String cpf) async {
final cpfLimpo = cpf.replaceAll(RegExp(r'\D'), '');
if (cpfLimpo.length != 11) {
throw Exception('CPF inválido. Informe 11 dígitos numéricos.');
}
final url = Uri.parse('$_baseUrl$cpfLimpo');
final headers = {
'x-api-key': apiKey,
'Accept': 'application/json',
};
try {
final response = await http
.get(url, headers: headers)
.timeout(const Duration(seconds: 10));
if (response.statusCode == 200) {
final body = jsonDecode(response.body) as Map<String, dynamic>;
if (body['success'] == true && body['data'] != null) {
return CpfData.fromJson(body['data'] as Map<String, dynamic>);
} else {
throw Exception('CPF não encontrado na base de dados.');
}
} else {
throw Exception('Erro HTTP: ${response.statusCode}');
}
} on Exception catch (e) {
if (e.toString().contains('TimeoutException')) {
throw Exception('A requisição excedeu o tempo limite.');
}
rethrow;
}
}
}
Implementando a tela de consulta
Crie um widget StatefulWidget que permite ao usuário digitar o CPF e visualizar o resultado:
import 'package:flutter/material.dart';
class ConsultaCpfPage extends StatefulWidget {
const ConsultaCpfPage({super.key});
@override
State<ConsultaCpfPage> createState() => _ConsultaCpfPageState();
}
class _ConsultaCpfPageState extends State<ConsultaCpfPage> {
final _cpfController = TextEditingController();
final _service = CpfService(apiKey: 'SUA_CHAVE_DE_API');
CpfData? _resultado;
String? _erro;
bool _carregando = false;
Future<void> _consultar() async {
setState(() {
_resultado = null;
_erro = null;
_carregando = true;
});
try {
final dados = await _service.consultarCpf(_cpfController.text);
setState(() {
_resultado = dados;
});
} catch (e) {
setState(() {
_erro = e.toString().replaceFirst('Exception: ', '');
});
} finally {
setState(() {
_carregando = false;
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Consulta de CPF')),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
TextField(
controller: _cpfController,
keyboardType: TextInputType.number,
maxLength: 11,
decoration: const InputDecoration(
labelText: 'CPF (somente números)',
border: OutlineInputBorder(),
),
),
const SizedBox(height: 16),
ElevatedButton(
onPressed: _carregando ? null : _consultar,
child: Text(_carregando ? 'Consultando...' : 'Consultar'),
),
const SizedBox(height: 24),
if (_resultado != null) ...[
Text('Nome: ${_resultado!.name}',
style: const TextStyle(fontSize: 16)),
Text('CPF: ${_resultado!.cpf}'),
Text('Nascimento: ${_resultado!.birthDate}'),
Text('Gênero: ${_resultado!.gender}'),
],
if (_erro != null)
Text(
_erro!,
style: const TextStyle(color: Colors.red, fontSize: 14),
),
],
),
),
);
}
@override
void dispose() {
_cpfController.dispose();
super.dispose();
}
}
Validação sintática local
Para economizar consultas à API, valide os dígitos verificadores do CPF localmente antes de enviar a requisição:
bool validarCpfLocal(String cpf) {
final cpfLimpo = cpf.replaceAll(RegExp(r'\D'), '');
if (cpfLimpo.length != 11) return false;
if (RegExp(r'^(\d)\1{10}$').hasMatch(cpfLimpo)) return false;
int soma = 0;
for (int i = 0; i < 9; i++) {
soma += int.parse(cpfLimpo[i]) * (10 - i);
}
int resto = (soma * 10) % 11;
if (resto == 10) resto = 0;
if (resto != int.parse(cpfLimpo[9])) return false;
soma = 0;
for (int i = 0; i < 10; i++) {
soma += int.parse(cpfLimpo[i]) * (11 - i);
}
resto = (soma * 10) % 11;
if (resto == 10) resto = 0;
if (resto != int.parse(cpfLimpo[10])) return false;
return true;
}
Testando com cURL
Para confirmar o funcionamento da API antes de integrar no Flutter:
curl -X GET https://api.cpfhub.io/cpf/12345678900 \
-H "x-api-key: SUA_CHAVE_DE_API" \
-H "Accept: application/json" \
--max-time 10
Boas práticas para Flutter
-
Chave de API segura -- Não inclua a chave diretamente no código em produção. Utilize variáveis de ambiente com
--dart-defineou um back-end intermediário. -
Timeout -- Sempre inclua
.timeout()nas requisições HTTP para evitar travamentos. -
Gerenciamento de estado -- Para projetos maiores, considere usar Provider, Riverpod ou Bloc para gerenciar o estado da consulta.
-
Volume de consultas -- No plano gratuito, o limite é de 50 consultas/mês. Ao atingir o limite, consultas adicionais são cobradas a R$0,15 cada — sem bloqueio do serviço. O plano Pro oferece 1.000 consultas por R$149/mês.
-
Multiplataforma -- O mesmo código funciona em Android, iOS, web e desktop, maximizando o reúso.
Perguntas frequentes
Como proteger a chave de API da CPFHub.io em um app Flutter?
Em Flutter, evite incluir a chave de API diretamente no código-fonte. A abordagem mais segura para produção é intermediar as chamadas por um back-end próprio — o app Flutter chama seu servidor, que por sua vez chama a API da CPFHub.io com a chave armazenada em variável de ambiente. Para desenvolvimento, use --dart-define=API_KEY=... ao rodar o app. Consulte as diretrizes de segurança do Flutter para mais detalhes.
O pacote http é a melhor opção para requisições HTTP em Flutter?
O pacote http é simples, mantido pela equipe do Dart e adequado para a maioria dos casos. Para projetos maiores que precisam de interceptadores, cancelamento de requisições, transformações de resposta e retry automático, o pacote dio é uma alternativa popular. Para a integração com a API CPFHub.io, o pacote http com .timeout() cobre todos os cenários descritos neste guia.
Como tratar o estado de carregamento durante a consulta de CPF no Flutter?
Use um StatefulWidget com uma variável booleana _carregando que é definida como true antes da chamada à API e false no bloco finally. Durante o carregamento, desabilite o botão de consulta e exiba um CircularProgressIndicator ou texto informativo. Isso evita chamadas duplicadas e mantém o usuário informado sobre o progresso da verificação.
É possível usar a API CPFHub.io em apps Flutter para web?
Sim. O mesmo código Dart funciona em Flutter web sem alterações. A única consideração é que chamadas diretas à API a partir do front-end (incluindo Flutter web) expõem a chave de API ao cliente. Para produção, sempre intermedie as chamadas por um back-end — independentemente da plataforma. Em desenvolvimento local, o Flutter web pode requerer configuração de CORS no servidor de testes.
Conclusão
Consumir a API de consulta de CPF da CPFHub.io em Flutter é direto: adicione o pacote http, crie um serviço tipado com CpfService, valide o CPF localmente antes de chamar a API e trate cada estado — carregando, sucesso e erro — no widget de forma explícita.
Cadastre-se em cpfhub.io — 50 consultas mensais gratuitas, sem cartão de crédito — e integre a validação de CPF no seu app Flutter hoje mesmo.
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.



