01 · CONCEPTO
Qué hace este API
El API de VΛLK permite que sistemas externos intercambien información con la plataforma. El contrato público está pensado para lectores QR, sistemas de registro, herramientas de logística y procesos de sincronización autorizados.
https://eventos.example.comEn desarrollo puede usarse el mismo path contra el host local configurado.Las rutas de integración pública comienzan con /api. Las rutas /api/web y su alias frontend /backend-api pertenecen a la aplicación administrativa y requieren sesión; no deben usarse como contrato de integración externa.
Primera llamada
Para registrar una lectura QR, envía el valor leído en codigo y una API key en X-API-Key:
curl -X POST "https://eventos.example.com/api/registrar_qr" \
-H "X-API-Key: REEMPLAZA_ESTA_CLAVE" \
-H "Content-Type: application/json" \
-d '{"codigo":"VALOR_LEIDO_DEL_QR"}'02 · SEGURIDAD
Autenticación y permisos
Todas las rutas públicas bajo /api exigen el encabezado:
X-API-Key: <clave-secreta>Cada clave tiene una lista explícita de permisos. El servidor valida el permiso de la operación antes de consultar o modificar información. Una clave sin permisos no puede utilizar ninguna operación y una clave suspendida devuelve 403.
| Permiso | Permite |
|---|---|
qr:read | Consultar los datos de un QR sin registrar asistencia. |
attendance:write | Registrar una lectura QR o confirmar una invitación. |
tickets:write | Marcar un ticket como impreso. |
guests:read / guests:write | Consultar invitados por ID / crear o ampliar categorías y centros. |
logistics:read / logistics:write | Consultar / crear logística y asignaciones. |
logos:read | Consultar logos. |
export:{tabla} | Extraer la tabla indicada en JSON, sin permiso de importación. |
import:{tabla} | Reemplazar la tabla indicada. Se otorga por separado. |
El servidor registra cada acceso asociado a la API key: endpoint, método y fecha. La autenticación no se envía en la URL.
Los permisos de integración operan sobre los recursos de las rutas autorizadas. El usuario responsable identifica la clave, pero no limita la extracción a su centro: las exportaciones incluyen todos los centros de la tabla autorizada.
Crear, ajustar y revocar claves
- Inicia sesión como superadministrador y abre el apartado administrativo de API keys y permisos.
- Selecciona “Generar nueva clave”, indica un nombre y el usuario responsable.
- Marca únicamente las operaciones y tablas necesarias. “Solo extracción” selecciona exportaciones; no habilita importaciones ni registro de asistencia.
- Guarda la clave, usa “Mostrar” y configúrala en el servidor de la integración como secreto.
- Para conceder o retirar acceso, abre “Editar permisos” y guarda. Los cambios se aplican a las siguientes solicitudes.
Suspensión, rotación y eliminación
Suspender bloquea temporalmente todas las operaciones y conserva la configuración. Reactivar recupera los permisos guardados. Regenerar invalida la clave anterior y conserva sus permisos y estado. Eliminar retira definitivamente la clave y su historial de accesos.
Las claves anteriores con alcance qr conservan sus operaciones históricas y las sync conservan además exportación e importación. Revisa sus permisos desde la administración. Las claves nuevas comienzan sin permisos seleccionados.
03 · CONTRATO HTTP
Respuestas y errores
Las respuestas JSON usan UTF-8. Las fechas se devuelven en ISO 8601. La extracción de integraciones devuelve JSON. Comprueba el estado HTTP y Content-Type: algunos errores de recurso inexistente pueden devolver HTML.
| HTTP | Significado | Qué revisar |
|---|---|---|
200 | Consulta o actualización correcta. | Usa el cuerpo de la respuesta. |
201 | Recurso creado. | Guarda el id devuelto. |
400 | Datos faltantes, formato inválido o regla de negocio incumplida. | Lee error. |
401 | Falta autenticación o sesión. | Agrega X-API-Key en el API público. |
403 | Clave inválida, suspendida o sin permiso. | Revisa el estado y los permisos de la clave. El campo required_permissions indica los permisos de la operación cuando faltan. |
404 | Recurso, tabla o confirmación inexistente. | Verifica el identificador o token. |
503 | Dependencia no disponible o estado operativo fuera de servicio. | Reintenta con backoff y revisa health/status. |
{"error":"API key requerida"}
{"ok":false,"error":"Código faltante."}04 · API PÚBLICA
Catálogo de endpoints
Las siguientes rutas forman el contrato de integración externa y usan X-API-Key.
Invitados
/api/invitadosCrea un invitado o actualiza el existente cuando ya hay otro registro con el mismo correo. Acepta nombre, email, genero, categoria_ids y centros_trabajo.
Permiso requerido: guests:write
{
"nombre": "Ana López",
"email": "[email protected]",
"genero": "Mujer",
"categoria_ids": [2, 4],
"centros_trabajo": ["Equipo general"]
}/api/invitados/{id}Consulta un invitado por ID e incluye sus categorías y equipos.
Permiso requerido: guests:read
Campos y respuesta
nombre y email son obligatorios para crear. categoria_ids contiene IDs existentes y centros_trabajo nombres de centros. Si el correo existe, se agregan categorías y centros sin reemplazar nombre, correo o género.
{
"id": 15,
"nombre": "Ana López",
"email": "[email protected]",
"genero": "Mujer",
"centros_trabajo": [
"Centro Norte"
],
"actualizado": false
}Creación: 201 con actualizado: false. Correo existente: 200 con actualizado: true. Consulta por ID: 200, incluye categorías como nombres. Un ID inexistente devuelve 404.
Confirmaciones y tickets
/api/confirmar-asistencia/{token}Confirma la asistencia asociada al token de una invitación y devuelve el evento y si corresponde ticket.
Permiso requerido: attendance:write
/api/imprimir-ticket/{token}Marca como impreso el ticket de una asistencia confirmada. No permite marcarlo dos veces.
Permiso requerido: tickets:write
El token pertenece a una invitación existente; no es el ID del invitado ni el valor cifrado del QR. Estas operaciones no necesitan cuerpo JSON.
{
"evento": "Foro anual",
"asistencia_confirmada": true,
"ticket": false
}Marcar impresión devuelve {"ticket_impreso":true}. Una asistencia inexistente o ticket ya marcado devuelve 400.
Logística
/api/eventos/{evento_id}/logisticaCrea un elemento logístico del evento. Requiere nombre y acepta tipo, cantidad y datos personalizados.
Permiso requerido: logistics:write
/api/eventos/{evento_id}/logisticaLista los elementos logísticos del evento.
Permiso requerido: logistics:read
/api/logistica/{logistica_id}/asignacionesAsigna un invitado a un elemento logístico. Requiere invitado_id y acepta datos personalizados.
Permiso requerido: logistics:write
/api/logistica/{logistica_id}/asignacionesLista las asignaciones del elemento logístico.
Permiso requerido: logistics:read
Las consultas devuelven listas JSON. La creación devuelve 201 con el ID nuevo. datos admite un objeto JSON; sin datos se devuelve un objeto vacío. Un evento, invitado o elemento inexistente devuelve 404.
curl -X POST "https://eventos.example.com/api/eventos/42/logistica" \
-H "X-API-Key: REEMPLAZA_ESTA_CLAVE" \
-H "Content-Type: application/json" \
-d '{"nombre":"Mesa de registro","tipo":"operación","cantidad":2,"datos":{"zona":"Norte"}}'05 · CONTRATO QR
Integración del lector QR
/api/registrar_qrValida el QR y registra un check-in único; si el boleto ya fue utilizado devuelve 409. Devuelve el contrato lector_qr_externo.v2.
Permiso requerido: attendance:write
/api/datos_qrConsulta el QR sin registrar asistencia.
Permiso requerido: qr:read
/api/logos_disponiblesDevuelve los logos PNG disponibles y su relación con dependencias configuradas.
Permiso requerido: logos:read
El lector QR es un sistema externo. El Gestor valida el código y registra la asistencia; la cámara, la impresión, el audio y el proceso local pertenecen al lector.
Registro de asistencia
POST /api/registrar_qr acepta codigo como JSON o como campo de formulario. Una respuesta correcta tiene:
{
"ok": true,
"contrato": "lector_qr_externo.v2",
"confirmacion": {
"id": 81,
"estado": "aceptado",
"numero_evento": 24,
"nivel_etiqueta": null,
"evento_horario_id": 3
},
"evento": {"id": 42, "titulo": "Foro anual", "fecha": "2026-09-20"},
"invitado": {"id": 15, "nombre": "Ana López", "invitado_especial": false},
"asistencia": {"asistencia": true, "conteo_escaneos": 1, "ticket_impreso": false},
"impresion": {
"orden_impresion": [],
"datos_invitado": [],
"datos_evento": [],
"distintivo": {"forma": "linea"},
"forma_distintivo": "linea"
}
}POST /api/datos_qr devuelve el contexto equivalente sin crear ni actualizar la asistencia. Úsalo cuando necesites validar o mostrar la información antes de registrar.
| Error | Resultado |
|---|---|
Falta codigo | 400 |
| QR inválido o con formato incorrecto | 400 |
| Confirmación inexistente | 404 |
| Límite de escaneos alcanzado | 400 |
| Boleto ya utilizado | 409 con codigo: already_checked_in |
El campo impresion.forma_distintivo puede ser linea, circulo, cuadrado, rectangulo o triangulo. No infieras el nivel a partir del nombre de la persona.
Extraer información para reportes
Otorga export:eventos para extraer eventos, o selecciona las tablas que necesita tu integración. Consultar un invitado por ID y exportar la tabla de invitados son permisos independientes.
/api/sync/{table_name}Extrae una tabla completa en JSON. Sustituye table_name por un nombre del catálogo.
Permiso requerido: export:{tabla}
curl "https://eventos.example.com/api/sync/eventos" -H "X-API-Key: REEMPLAZA_ESTA_CLAVE"{
"tabla": "eventos",
"total": 1,
"records": [
{
"id": 42,
"titulo": "Foro anual",
"fecha": "2026-09-20T09:00:00",
"creado_por": 3,
"visibilidad": "centro_trabajo"
}
]
}El ejemplo abrevia las columnas. Cada registro contiene las columnas de la tabla, no sus relaciones anidadas. Las fechas usan ISO 8601, sin agregar zona horaria si no está almacenada; los valores ausentes son null.
| Tabla | Información |
|---|---|
eventos | Eventos y configuración; categoría, tipo y creador por ID. |
invitados | Datos de personas. Para categorías y centros relacionados, consulta por ID. |
confirmaciones | Invitaciones y respuestas por evento e invitado. Incluye tokens y datos personales. |
asistencias | Asistencia, lecturas e impresión por evento e invitado. |
logisticas, logistica_asignaciones | Elementos logísticos y asignaciones de invitados. |
categorias, categorias_invitado, tipos_evento | Catálogos para interpretar los IDs. |
diccionarios, ordenes_del_dia | Catálogos dinámicos y órdenes del día. |
/api/sync/exportExtrae las once tablas soportadas. Requiere todos los permisos de exportación; si falta uno, devuelve 403 sin exportar un subconjunto.
Permiso requerido: Todos los permisos export:{tabla}
La respuesta contiene ok, total_registros, tablas (objeto con una lista por tabla) y tablas_exportadas (nombres). No incluye usuarios, contraseñas ni API keys.
Volumen y alcance
Estas rutas devuelven JSON completo, sin paginación, filtros de centro ni formatos CSV o XLSX. Programa extracciones espaciadas y configura un tiempo de espera adecuado. Los permisos de extracción son globales para las tablas seleccionadas.
Protege las descargas: pueden contener correos, tokens y respuestas de registro. Las once tablas no constituyen un respaldo completo de archivos ni de todas las relaciones de la aplicación.
06 · DATOS
Importación y reemplazo de tablas
La importación requiere import:{tabla} para la tabla enviada. Reemplaza su contenido: crea registros nuevos, actualiza los que conservan su ID y elimina los que existen en el servidor pero no vienen en la carga. Una lista vacía solicita eliminar todos sus registros; las restricciones de relaciones pueden impedirlo.
Tablas permitidas
invitados, categorias_invitado, categorias, eventos, tipos_evento, confirmaciones, asistencias, logisticas, logistica_asignaciones, diccionarios y ordenes_del_dia.
/api/sync/{table_name}Sincroniza una tabla completa. El body puede ser una lista de registros o un objeto con la propiedad records o data.
Permiso requerido: import:{tabla}
{
"records": [
{"id": 15, "nombre": "Ana López", "email": "[email protected]"},
{"id": 16, "nombre": "Luis Pérez", "email": "[email protected]"}
]
}{
"ok": true,
"tabla": "invitados",
"insertados": 1,
"actualizados": 1,
"eliminados": 0
}Los IDs conservados se actualizan. Los campos desconocidos se ignoran. Respeta los campos obligatorios y las relaciones de cada tabla. Un error de base de datos devuelve 400 y revierte los cambios de esa solicitud.
07 · APLICACIÓN
API administrativa y de monitoreo
El frontend usa /backend-api/* como alias del blueprint Flask /api/web/*. Estas rutas están protegidas por sesión, permisos de usuario y, para operaciones mutables, CSRF. No son un contrato público para integraciones externas.
Visibilidad de eventos
Los administradores pueden crear eventos únicamente para su equipo o su área. El superadministrador puede usar su centro o unidad, el centro del creador, todos los centros o un centro elegible específico.
{
"visibilidad": "centro_trabajo_elegible",
"centro_trabajo_elegible": "Centro Norte"
}| Ruta | Uso | Acceso |
|---|---|---|
/api/web/health | Readiness de API y base de datos. | Público. |
/api/web/status | Estado global, latencias, dependencias e incidentes. | Público o X-Status-Token, según configuración. |
/api/web/version | Versión actual y notas de versión. | Público. |
/api/web/csrf-token | Token para operaciones de sesión. | Sesión del navegador. |
/api/web/login, /session, /logout | Inicio, consulta y cierre de sesión. | Sesión. |
/api/web/eventos, /invitados, /diccionarios | Gestión administrativa de recursos. | Sesión y rol. |
/api/web/eventos/{id}/invitar-evento | Invita en bloque a las personas de otro evento visible, sin crear categorías automáticas. | Administrador. |
/api/web/public/eventos/{id}/registro | Registro público configurado para un evento. | Público, sujeto a reglas del evento. |
Los monitores pueden usar GET /healthz y GET /statusz desde el mismo dominio. Son alias operativos publicados por el proxy y no requieren conocer la topología interna.
08 · OPERACIÓN
Buenas prácticas de integración
- Usa HTTPS en producción y conserva la API key únicamente en el servidor o dispositivo confiable.
- Envía
Content-Type: application/jsoncuando el body sea JSON y valida siempre el status HTTP antes de leer datos. - Registra el
contratode las respuestas QR y trata campos desconocidos de forma tolerante para permitir futuras extensiones. - No reintentes automáticamente errores
400,401,403o404sin corregir la solicitud. - Para
503o fallas de red, usa reintentos limitados con espera creciente y evita duplicar operaciones de registro. - Antes de sincronizar, respalda los datos y verifica que los IDs y el contenido enviados sean completos.