Verificación contra el código y la base de HOY, no un resumen de lo que se hizo. Incluye una corrida nueva del endpoint con 5 eventos, el contrato documentado y el cierre con lo que bloquea la primera carga.
Este documento es una validación ANTERIOR a los ajustes hechos al endpoint de ingesta y ya NO refleja su comportamiento real. No lo uses como referencia para desarrollar el scraper. La referencia vigente es el contrato consolidado: docs/scraping/contrato-endpoint-ingesta-eventos.md (repo LPDI relacionamiento).
Estado REAL verificado hoy en producción (SHA 64192e08) — contradice cuatro afirmaciones de este documento (marcadas abajo con OBSOLETO):
venue. Contradice la sección 05 ("El endpoint no geocodifica").por_confirmar=true con coordenadas falsas → guardó las de la ciudad, precisión city, bandera true. Contradice el punto "Banderas de ubicación" de la sección 04.| Punto | Estado | Evidencia (hoy) | Qué falta |
|---|---|---|---|
| A5 Organizadores |
Parcial | Directorio: 1.175 activos (el total 1.384 incluye 209 borrados; no creció). Compuestos: de ~89 a 2. Puntuación terminal: 1. Espacios dobles: 0. Tipo dirección: 4. Duplicados por mayúsculas: 3 grupos (6 filas). 47 fusiones ejecutadas. | Limpiar residuales (2 compuestos, 4 dirección, 6 duplicados) y 2 vínculos que apuntan a un organizador borrado. Confirmar que las 47 fusiones eran las aprobadas. No encontré tabla de respaldo (ver 06). |
| A6 Placeholders de ubicación |
OK | Placeholders de Luma ("registrarse para ver la ubicación"): quedan 2 a 3 (de decenas). El endpoint además los limpia al ingerir (a prueba de futuro). Los eventos con placeholder conservan ciudad, país y coordenadas. | Decisión tuya: hay 468 con "Por confirmar" (población distinta, con geo intacta). Parecen sede por definir legítima. Si quieres blanquearlos, lo hago. |
| B1 Columnas de procedencia |
OK | Existen fuente, id_fuente, url_fuente. Índice: UNIQUE (fuente, id_fuente) WHERE fuente IS NOT NULL AND id_fuente IS NOT NULL, exactamente como se pidió. Registros con fuente no nula: 0 (limpio, sin pruebas colgadas). |
Nada. |
| B2 Endpoint de ingesta |
OK | Verificado con la prueba en vivo (ver 03): crea, actualiza sin duplicar, rechaza país inválido, limpia placeholder, no crea usuarios. Contrato en el punto 04. | Nada para la carga. Opcional: geocodificación (ver 05) y modo de prueba sin escribir. |
| B3 Aprobación en lote |
OK | Selección múltiple, procesa todos (en tandas de 6). Sin tope duro: ~150 funciona. Si uno falla, sigue el resto. Aprobar eventos de ingesta NO dispara correos (ya lo dejamos así el 13-ago porque el correo de sistema rebotaría). | Nada. Para 150 eventos pasados de CTW: 0 correos. |
PENDING (curación humana), igual que uno futuro.Enviados por el endpoint real contra la base, y borrados al final. Base confirmada como estaba: 0 filas de prueba, 0 usuarios creados.
| Caso | Enviado | Resultado | Verificación en base |
|---|---|---|---|
| 1. Válido futuro | fecha 01-dic-2026, país CO | created P-CO-999-26-00038 | status PENDING |
| 2. Válido pasado | fecha 12-ago-2026, país CO | created P-CO-999-26-00039 | status PENDING (sin bloqueo por fecha) |
| 3. Reenvío del 1 con cambio | mismo id, nombre cambiado | updated (mismo id y código) | 1 sola fila, nombre actualizado. No duplicó. |
| 4. País fuera del catálogo | país "XX" | error "país no reconocido" | No se creó. |
| 5. Placeholder de Luma en ubicación | "Registrarse para ver la ubicación" | created P-CO-999-26-00040 | ubicacion_texto quedó en NULL (limpiado). |
POST /api/admin/eventos/ingestAuthorization: Bearer <INGEST_SECRET> (401 si falta o no coincide)fuente (string, aplica a todo el lote) y eventos (array). No es un array plano.id_fuente, nombre, fecha_inicio (YYYY-MM-DD)ubicacion_lat / ubicacion_lng (numéricas; snake_case)id_fuente por evento; fuente en el nivel del lote; url_fuente por eventohorarios, tematicas, actividades, organizadores_raw, hosts_speakers: van como arrays/objetos, no como string JSON(fuente, id_fuente). Si existe, ACTUALIZA sin tocar el estado ni el código. Si no, crea en PENDING.contact_email = ingesta@lpdi.co y sin usuario dueño.fuente IS NOT NULL distingue "lo que entró por ingesta" de lo que registró una persona. (No hay UUID de cuenta de sistema: es un correo fijo, no una cuenta.)id_fuente, el evento_id y el evento_codigo generado.curl -X POST https://eco.lpdi.co/api/admin/eventos/ingest \
-H "Authorization: Bearer $INGEST_SECRET" \
-H "Content-Type: application/json" \
-d '{
"fuente": "luma",
"eventos": [{
"id_fuente": "evt-abc12345",
"nombre": "Demo Day Colombia Tech Week",
"fecha_inicio": "2026-08-12",
"fecha_finalizacion": "2026-08-12",
"modalidad": "presencial",
"pais_code": "Colombia",
"ciudad": "Medellin",
"estado_provincia": "Antioquia",
"ubicacion_texto": "Ruta N, Medellin",
"ubicacion_lat": 6.2447, "ubicacion_lng": -75.5686,
"organizadores_raw": [{"nombre": "Aceleradora X", "rol": "Aceleradora"}],
"tematicas": [{"categoria": "innovacion", "subcategoria": "tecnologia", "principal": true}],
"url_fuente": "https://lu.ma/evt-abc12345"
}]
}'
{ "ok": true, "fuente": "luma",
"summary": { "total": 1, "created": 1, "updated": 0, "errors": 0 },
"results": [{ "id_fuente": "evt-abc12345", "status": "created",
"evento_id": "…", "evento_codigo": "P-CO-004-26-00041" }] }
Tu observación de Luma (las coordenadas solo aparecen cuando el organizador oculta la dirección) va a repetirse en muchas fuentes. Por eso conviene resolverlo en el servidor una sola vez: si el evento llega con ciudad y país pero sin coordenadas, el endpoint podría geocodificar y guardar la aproximación. Así no lo duplicas en cada extractor nuevo. Esfuerzo moderado (conectar un geocodificador y guardar el resultado). Lo dejo como recomendación, no lo toco sin tu visto bueno.