Consulta por Lote
Envía una lista de hasta 10.000 CPF (el número de identificación fiscal de personas físicas en Brasil) y recibe, para cada uno, el nombre, el género y la fecha de nacimiento, procesados en segundo plano. Cuesta 1 crédito por CPF encontrado.
¿Usas Cursor, Lovable, v0 u otra IA? Copia el prompt de la consulta por lote y pégalo en tu asistente.
¿No es esta? Compara las consultas. Si prefieres no escribir código, el dashboard acepta archivos CSV/TXT o CPF pegados y exporta el resultado en CSV.
Flujo en dos pasos:
POST /cpf/bulkenvía la lista y responde de inmediato con unjobId.GET /cpf/bulk/{jobId}devuelve el progreso y los resultados. Repite hasta questatussea"done"o"failed".
Endpoint
https://api.cpfhub.io/cpf/bulkParámetros
| Dónde | Nombre | Obligatorio | Descripción |
|---|---|---|---|
| Header | x-api-key | Sí | Tu clave de API. Consulta Autenticación. |
| Header | Content-Type | Sí | application/json |
| Body | cpfs | Sí | string[] de CPF, con o sin formato. No vacío, máximo 10.000. Los elementos que no son cadenas cuentan como inválidos. |
| Body | fileName | No | Etiqueta libre. Vuelve como file_name en el estado. |
| Body | format | No | Etiqueta libre del formato de origen (por ejemplo, "csv"). Vuelve como format. |
Qué pasa al enviar
| Etapa | Efecto |
|---|---|
| Normalización | Quita el formato. Los CPF sin 11 dígitos o con dígito verificador incorrecto van a invalid y no se cobran. |
| Duplicados | Se eliminan. Cada CPF se consulta y se cobra una sola vez. No cuentan en totalRecords ni en invalid. |
| Límite por minuto | Cada envío cuenta como una solicitud en el límite de la Consulta Simple (30 por minuto por defecto). |
| Saldo | Sin excedente: el saldo debe cubrir todos los CPF válidos (totalRecords × el costo de la Consulta Simple, 1 crédito por defecto). Si no alcanza, recibes 403 y no se cobra nada. |
Más de 10.000 CPF: divídelos en bloques y envía un POST por cada uno.
Ejemplo
Revisa el estado antes de leer data: en caso de error, la respuesta no trae jobId.
curl -X POST "https://api.cpfhub.io/cpf/bulk" \
-H "x-api-key: $CPFHUB_API_KEY" \
-H "content-type: application/json" \
-d '{
"cpfs": ["12345678909", "11144477735", "52998224725"]
}'Respuesta
HTTP 202 Accepted
{
"success": true,
"data": {
"jobId": "4a1ef25e-052c-4464-9657-4148f53bb0fc",
"status": "processing",
"totalRecords": 3,
"invalid": 0
}
}| Campo | Tipo | Descripción |
|---|---|---|
data.jobId | string | ID del lote. Guárdalo para consultar el estado. |
data.status | string | Siempre "processing" |
data.totalRecords | number | CPF válidos y únicos que se van a consultar |
data.invalid | number | Elementos descartados (formato, dígito verificador o no es una cadena) |
El envío responde en camelCase. El estado responde en snake_case.
Estado y resultados
https://api.cpfhub.io/cpf/bulk/{jobId}Usa la misma clave de API del envío. No consume crédito, no cuenta en el límite por minuto y funciona con saldo en cero.
Polling:
- Empieza cada 5 s y aumenta hasta 30 s en lotes grandes. Cada llamada devuelve el array
cpfscompleto (hasta ~2 MB con 10.000 CPF). - Define un plazo máximo en el cliente (por ejemplo, 30 min). El tiempo del lote depende de cuántos CPF envíes, y cada consulta queda en el mismo rango de la Consulta Simple (~150 ms).
- Ante un
5xxo un error de red, reintenta en el siguiente ciclo. Es seguro repetir elGET.
curl "https://api.cpfhub.io/cpf/bulk/4a1ef25e-052c-4464-9657-4148f53bb0fc" \
-H "x-api-key: $CPFHUB_API_KEY"HTTP 200 OK
{
"success": true,
"data": {
"id": "4a1ef25e-052c-4464-9657-4148f53bb0fc",
"status": "done",
"file_name": null,
"format": null,
"total_records": 2,
"processed": 2,
"found": 1,
"not_found": 1,
"skipped": 0,
"error": null,
"created_at": "2026-10-02T14:15:16.000Z",
"updated_at": "2026-10-02T14:15:18.000Z",
"cpfs": [
{
"cpf": "12345678909",
"found": true,
"name": "Fulano de Tal",
"nameUpper": "FULANO DE TAL",
"gender": "M",
"birthDate": "15/06/1990",
"day": 15,
"month": 6,
"year": 1990
},
{
"cpf": "52998224725",
"found": false,
"name": null,
"nameUpper": null,
"gender": null,
"birthDate": null,
"day": null,
"month": null,
"year": null
}
]
}
}| Campo | Descripción |
|---|---|
data.id | ID del lote (el jobId del envío) |
data.status | "processing", "done" o "failed" |
data.total_records | CPF válidos y únicos en el lote |
data.processed | CPF ya procesados (incluye skipped) |
data.found | Encontrados. Cada uno consume 1 crédito por defecto (el costo de tu plan está en el dashboard) |
data.not_found | No encontrados. No consumen crédito. |
data.skipped | No consultados porque el saldo se agotó durante el lote (sin excedente). No consumen crédito. |
data.error | Motivo de la falla cuando status es "failed" |
data.file_name, data.format | Etiquetas enviadas en el POST |
data.created_at, data.updated_at | Fechas ISO 8601 |
data.cpfs[] | Resultado de cada CPF procesado: cpf (11 dígitos), found, name, nameUpper, gender, birthDate, day, month, year (null cuando found es false) |
Mientras el estado es "processing", los contadores se actualizan cada 50 CPF y pueden ir por detrás de cpfs.
Errores
La API responde solo en portugués. Los mensajes de error se muestran tal como llegan, con la traducción entre paréntesis la primera vez.
| Estado | Cuándo ocurre | Qué hacer |
|---|---|---|
400 | cpfs ausente, vacío, no es un array o tiene más de 10.000 elementos | Corrige el body. |
401 | Clave de API ausente, inválida o inactiva (error es una cadena) | Revisa el header x-api-key. |
403 | Sin excedente: saldo en cero (error cadena "Limite de créditos excedido", límite de créditos excedido) o saldo menor que el lote (error.message: "Créditos insuficientes para o lote: N necessários.", créditos insuficientes para el lote: se necesitan N). También cuenta inactiva/bloqueada. Solo en el POST. | Recarga créditos o reduce el lote. |
404 | El jobId no existe o se creó con otra clave de API | Revisa el jobId y la clave. |
422 | Ningún CPF válido en la lista | Corrige la lista. |
429 | Límite por minuto excedido (solo en el POST) | Espera los segundos indicados en el header Retry-After. |
500, 503 | Falla pasajera. No se creó ningún lote. | Intenta de nuevo. Repórtalo si persiste. |
Formato del error, reintentos y cómo probar sin gastar créditos: Códigos de Error. Límite por minuto y créditos: Límites de Uso.
Detalles
Estados del lote
| Situación | Cómo identificarla | Qué hacer |
|---|---|---|
| En procesamiento | status: "processing" | Sigue con el polling. cpfs ya trae resultados parciales. |
| Completado | "done" y skipped: 0 | Usa cpfs. |
| Completado con omitidos | "done" y skipped > 0 | El saldo se agotó durante el lote. Recarga y reenvía solo los CPF que faltaron. |
| Falló | "failed" | Lee error. Los encontrados en cpfs ya fueron cobrados. Reenvía solo los que faltaron. |
Valores de error cuando el lote falla:
error | Significado |
|---|---|
"Banco de dados indisponível" (base de datos no disponible) | No se procesó ni se cobró nada. |
"Falha ao registrar validação" (falla al registrar la consulta) | Falló al guardar un resultado. El procesamiento se detuvo. |
"Worker interrompido (job órfão)" (worker interrumpido, job huérfano) | El procesamiento se interrumpió. Se marca así tras ~10 min sin actualización. |
Con excedente, ningún CPF se omite: todos se consultan y el excedente se cobra.
Cruzar los resultados con tu lista
cpfs llega en orden de procesamiento y no incluye los skipped ni los no procesados. Normaliza tu lista a 11 dígitos y cruza por el campo cpf. Los que falten son los que debes reenviar (incluye los inválidos, que no cuestan nada).
const normalize = (cpf: string) => cpf.replace(/\D/g, '')
const results = new Map(job.cpfs.map((item) => [item.cpf, item]))
for (const original of myCpfs) {
const result = results.get(normalize(original))
console.log(original, result ? (result.found ? result.name : 'no encontrado') : 'sin resultado')
}
// CPF para reenviar en un nuevo lote (si el lote falló o tuvo skipped)
const missing = [...new Set(myCpfs.map(normalize))].filter((cpf) => !results.has(cpf))Más
- Envío no idempotente: cada
POSTaceptado crea un lote nuevo y cobra los encontrados. Si la conexión se cae sinjobId, revisa el dashboard oGET /quotaantes de reenviar. Si recibiste una respuesta de error, no se creó ningún lote. - Crédito: solo se cobra
found: true. Los inválidos, repetidos, no encontrados yskippedno se cobran. - Exportación CSV: solo en el dashboard, con las columnas
CPF,Nome(nombre),Nascimento(fecha de nacimiento) yEncontrado(encontrado), sin género.
Actualizado el 4 de octubre de 2026