Búsquedas por lote.
Cuando necesitas verificar más de ~10 cédulas a la vez, en lugar de hacer N llamadas individuales subes un CSV (o un array JSON) y recibes un solo archivo con todos los resultados cuando termina.
Tres pasos
POST /v1/batches/con tu CSV o un JSON → recibes unbatch_id.- Polling de
GET /v1/batches/{id}cada 5-10 segundos mientrasstatus === "running". - Cuando
status === "completed", descargasGET /v1/batches/{id}/results.csv.
Tiempos aproximados
| Cédulas | Endpoint | Tiempo total |
|---|---|---|
| 50 | full_check | ~3 min |
| 50 | identity_validation | ~30 s |
| 1.000 | full_check | ~30 min |
| 15.000 | full_check | ~7-8 horas |
Crear un batch
/v1/batches/Opción A — multipart con archivo CSV
curl -X POST https://api.tverificas.com/v1/batches/ \
-H "Authorization: Bearer $TVERIFICAS_API_KEY" \
-F "file=@empleados.csv" \
-F "endpoint=full_check"import httpx
with httpx.Client() as c, open("empleados.csv", "rb") as f:
r = c.post(
"https://api.tverificas.com/v1/batches/",
files={"file": ("empleados.csv", f, "text/csv")},
data={"endpoint": "full_check"},
headers={"Authorization": f"Bearer {TVERIFICAS_API_KEY}"},
)
batch = r.json()
print(batch["id"], batch["total_count"])const fd = new FormData();
fd.append("file", fileInput.files[0]);
fd.append("endpoint", "full_check");
const r = await fetch("https://api.tverificas.com/v1/batches/", {
method: "POST",
headers: { Authorization: `Bearer ${TVERIFICAS_API_KEY}` },
body: fd,
});
const batch = await r.json();Opción B — JSON con array de cédulas
curl -X POST https://api.tverificas.com/v1/batches/ \
-H "Authorization: Bearer $TVERIFICAS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"cedulas": ["1192801234", "1020304050", "79876543"],
"endpoint": "identity_validation"
}'Respuesta del POST (HTTP 202)
{
"id": "9cf1dc24-193b-4c73-8672-1562daa53d7c",
"status": "pending",
"endpoint": "full_check",
"source_filename": "empleados.csv",
"total_count": 1000,
"warnings": {
"invalid_rows": [[5, "cedula no numerica: 'abc'"]],
"duplicates_skipped": 12
},
"created_at": "2026-04-28T10:15:00Z"
}warnings.invalid_rows lista las filas que no se procesaron (con número de línea y motivo). duplicates_skipped cuenta las repetidas dentro del mismo CSV. El batch arranca igual con las filas válidas — no aborta.
Formato del CSV
Entrada
Una sola columna obligatoria, las demás opcionales:
cedula,user_reference,purpose
1192801234,empleado-001,onboarding
1020304050,empleado-002,onboarding
79876543,empleado-003,renovacion-anual| Parámetro | Tipo | Descripción |
|---|---|---|
cedularequerido | string | Número del documento. Acepta guiones y espacios (se limpian). Max 12 dígitos. |
user_reference | string | Identificador interno tuyo (empleado, cliente, etc). Aparece en el resultado. |
purpose | string | Motivo de la consulta (onboarding, renovación, KYC). Útil para auditoría. |
Aliases del header aceptados
cedula/cédula/documento/iduser_reference/ref/referenciapurpose/proposito/motivo
Si la primera fila ya es numérica, se asume sin header.
Salida — results.csv
cedula,nombre,tipo_documento,nacionalidad,status,sources_total,sources_ok,coincidencias,sin_coincidencia,errores,duration_ms,billable,cost_units_charged,user_reference,purpose,search_id,completed_at
1192801234,CARLOS ENRIQUE MOSQUERA,Cedula de Ciudadania,Colombiana,completed,44,42,2,40,2,58521,true,1.00,empleado-001,onboarding,9cf1dc24-...,2026-04-28T10:18:30Zsearch_id te permite traer la respuesta completa con GET /v1/searches/{id} durante 30 días.
Ver el progreso
/v1/batches/{id}curl https://api.tverificas.com/v1/batches/$BATCH_ID \
-H "Authorization: Bearer $TVERIFICAS_API_KEY"{
"id": "9cf1dc24-...",
"status": "running",
"endpoint": "full_check",
"total_count": 1000,
"pending_count": 720,
"running_count": 28,
"completed_count": 247,
"failed_count": 5,
"degraded_count": 0,
"percent_complete": 25.2,
"billable_units_so_far": "247.00",
"avg_duration_ms": 58430,
"estimated_seconds_remaining": 4320,
"estimated_completion_at": "2026-04-28T11:42:00Z",
"results_url": null,
"started_at": "2026-04-28T10:15:01Z",
"completed_at": null
}Estados del batch
pending— recién creado, esperando dispatch.dispatching— creando los Search rows internamente.running— hay búsquedas en proceso.completed— todas terminaron (con éxito o no).failed— error irrecuperable del orquestador (raro).
results_url se llena solo cuando status === "completed".
Estados de cada búsqueda dentro del batch
| Status | Cobra | Significado |
|---|---|---|
| completed | Sí | OK, suficientes fuentes contestaron |
| degraded | No | Respondieron muy pocas fuentes. No te cobramos. |
| failed | No | Timeout o error de upstream. No te cobramos. Puedes reintentar. |
| running, pending | — | Todavía no terminó |
Patrón recomendado de polling
Adaptativo — cada 10s al inicio, cada 5s cuando hay actividad:
import time, httpx
with httpx.Client(headers={"Authorization": f"Bearer {KEY}"}) as c:
while True:
r = c.get(f"https://api.tverificas.com/v1/batches/{batch_id}")
b = r.json()
print(f"{b['status']} {b['percent_complete']}%")
if b["status"] in ("completed", "failed"):
break
# Si recién arrancó, polea más espaciado
time.sleep(5 if b["percent_complete"] >= 5 else 10)async function pollUntilDone(batchId) {
while (true) {
const r = await fetch(`https://api.tverificas.com/v1/batches/${batchId}`, {
headers: { Authorization: `Bearer ${KEY}` },
});
const b = await r.json();
if (b.status === "completed" || b.status === "failed") return b;
await new Promise(r => setTimeout(r, b.percent_complete >= 5 ? 5000 : 10000));
}
}Descargar resultados
/v1/batches/{id}/results.csv# Cuando status === "completed"
curl https://api.tverificas.com/v1/batches/$BATCH_ID/results.csv \
-H "Authorization: Bearer $TVERIFICAS_API_KEY" \
-o resultados.csvSi lo pides antes de tiempo:
HTTP/1.1 425 Too Early
{ "error": "batch not yet completed", "status": "running" }Búsquedas individuales del batch
Listar las del batch
# Todas
curl "https://api.tverificas.com/v1/batches/$BATCH_ID/searches" \
-H "Authorization: Bearer $TVERIFICAS_API_KEY"
# Solo las fallidas
curl "https://api.tverificas.com/v1/batches/$BATCH_ID/searches?status=failed" \
-H "Authorization: Bearer $TVERIFICAS_API_KEY"Query params: status=failed|completed|..., limit=50&offset=0 (max 1000).
Detalle completo de una
curl https://api.tverificas.com/v1/searches/$SEARCH_ID \
-H "Authorization: Bearer $TVERIFICAS_API_KEY"Trae response_data con las ~44 verificaciones por fuente. Disponible durante 30 días (después se purga el payload pero queda la metadata).
Reintentar una fallida
curl -X POST \
"https://api.tverificas.com/v1/batches/$BATCH_ID/searches/$SEARCH_ID/retry" \
-H "Authorization: Bearer $TVERIFICAS_API_KEY"Devuelve 202. La búsqueda vuelve a pending y se re-encola. El batch vuelve a running si estaba completed. Útil cuando falló por un timeout transitorio de una fuente.
Cuotas y costos
- Cada Search se cuenta como 1 unidad (o
0.20paraidentity_validation). - Tu plan tiene N unidades incluidas por mes. Pasadas esas, lo extra es overage facturable al cierre del mes.
- No te cobramos cuando: el status final es
failedodegraded; la consulta es un cache hit (misma cédula buscada en las últimas 24h); es una keytest; o es un retry con la mismaIdempotency-Key.
billable_units_so_far en el progreso del batch te dice exactamente cuánto vas consumiendo en tiempo real.
Manejo de errores
| HTTP | Cuándo | Qué hacer |
|---|---|---|
| 400 | CSV vacío o sin cédulas válidas | Revisa error y invalid_rows |
| 401 | API key inválida o revocada | Revisa la key en /app/api-keys |
| 403 | test_mode_exceeded | Pasa la key a live |
| 404 | Batch no existe o no es de tu org | — |
| 425 | Pediste results.csv antes de tiempo | Polea hasta completed |
| 5xx | Error transitorio | Reintenta con backoff exponencial (1s, 2s, 4s…) |
Headers opcionales útiles
| Parámetro | Tipo | Descripción |
|---|---|---|
Idempotency-Key | uuid | Si retransmites el mismo POST con la misma key, devolvemos el mismo batch. Evita duplicados por reintentos de red. |
X-User-Reference | string | Identifica al usuario en tu lado que disparó la consulta. Lo guardamos para auditoría. |
Límites operativos
- Tamaño máximo de CSV: ~15.000 cédulas por batch recomendado. Más que eso, parte en varios.
- Concurrencia interna: hasta 50 búsquedas en paralelo contra las fuentes.
- Retención:
response_data30 días desde creación. Metadata (cédula, status, costos) se conserva siempre. - Cache: la misma cédula dentro de 24h devuelve el resultado anterior sin cobrar de nuevo.
Quickstart end-to-end
# 0. Variables
KEY="tvk_live_xxx"
URL="https://api.tverificas.com"
# 1. Crear CSV de prueba
cat > test.csv <<EOF
cedula,user_reference
1192801234,emp-001
1020304050,emp-002
79876543,emp-003
EOF
# 2. Subir
RESP=$(curl -s -X POST "$URL/v1/batches/" \
-H "Authorization: Bearer $KEY" \
-F "file=@test.csv" -F "endpoint=identity_validation")
BID=$(echo "$RESP" | jq -r .id)
echo "Batch: $BID"
# 3. Polear
while true; do
STATUS=$(curl -s "$URL/v1/batches/$BID" -H "Authorization: Bearer $KEY" | jq -r .status)
echo "$STATUS"
[ "$STATUS" = "completed" ] && break
sleep 5
done
# 4. Descargar
curl -s "$URL/v1/batches/$BID/results.csv" \
-H "Authorization: Bearer $KEY" \
-o resultados.csv
cat resultados.csv