Protocolo Push ZKTeco explicado: por qué es clave para el control de asistencia en la nube
Los dispositivos ZKTeco soportan dos modos de conexión: pull (SDK) y push (nube). Aprende cómo el modo push elimina IPs estáticas, servidores locales y polling — y cómo recibir datos de asistencia en tiempo real a través de una API REST.
Introduction
Compraste un dispositivo ZKTeco. Lo conectaste a la red. Ahora necesitas los datos de asistencia en tu aplicación en la nube. La pregunta es: ¿el dispositivo te envía los datos, o tú los vas a buscar al dispositivo?
Esa decisión arquitectónica — push vs. pull — determina si tu integración funciona de manera confiable a gran escala o se rompe en cuanto agregas una segunda oficina. La mayoría de los desarrolladores empiezan con el enfoque pull (bibliotecas SDK), chocan con un muro, y luego descubren que existe el modo push. Para entonces, ya perdieron semanas.
Este artículo explica qué es el modo push, por qué existe, cómo se compara con el enfoque SDK, y cómo obtener datos de asistencia en tiempo real sin tocar protocolos crudos de los dispositivos.
Modo Pull: el enfoque SDK (y por qué falla)
La forma tradicional de obtener datos de un dispositivo ZKTeco es el modo pull. Tu servidor se conecta al dispositivo en la red local, se autentica y solicita los registros. Bibliotecas como pyzk, node-zklib y zklib funcionan así.
Parece simple al principio. Escribes un script, te conectas a la IP del dispositivo, llamas get_attendance(), listo. Pero la simplicidad engaña.
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 340" fill="none" style="width:100%;max-width:800px;">
<text x="400" y="25" text-anchor="middle" fill="#94a3b8" font-size="17" font-weight="bold" font-family="system-ui">Modo Pull: el servidor se conecta al dispositivo</text>
<rect x="40" y="70" width="180" height="80" rx="12" stroke="#f87171" stroke-width="2" fill="none"/>
<text x="130" y="105" text-anchor="middle" fill="#f87171" font-size="15" font-family="system-ui">💻 Tu servidor</text>
<text x="130" y="127" text-anchor="middle" fill="#f87171" font-size="14" font-family="system-ui">(debe estar en LAN)</text>
<line x1="220" y1="110" x2="340" y2="110" stroke="#64748b" stroke-width="2" marker-end="url(#ppArrowEs)"/>
<text x="280" y="98" text-anchor="middle" fill="#64748b" font-size="13" font-family="system-ui">conexión + polling</text>
<rect x="340" y="70" width="180" height="80" rx="12" stroke="#22d3ee" stroke-width="2" fill="none"/>
<text x="430" y="105" text-anchor="middle" fill="#22d3ee" font-size="15" font-family="system-ui">🖐 Dispositivo ZKTeco</text>
<text x="430" y="127" text-anchor="middle" fill="#22d3ee" font-size="14" font-family="system-ui">(IP estática necesaria)</text>
<rect x="40" y="190" width="680" height="130" rx="10" stroke="#f87171" stroke-width="1.5" fill="none" stroke-dasharray="6,4"/>
<text x="60" y="215" fill="#f87171" font-size="15" font-weight="bold" font-family="system-ui">⚠ Limitaciones del modo Pull:</text>
<text x="60" y="240" fill="#94a3b8" font-size="14" font-family="system-ui">• El servidor debe estar en la misma red que el dispositivo (sin apps en la nube)</text>
<text x="60" y="262" fill="#94a3b8" font-size="14" font-family="system-ui">• El dispositivo necesita IP estática — un cambio DHCP rompe la conexión</text>
<text x="60" y="284" fill="#94a3b8" font-size="14" font-family="system-ui">• El polling genera retrasos (1-5 min) y desperdicio de ancho de banda</text>
<text x="60" y="306" fill="#94a3b8" font-size="14" font-family="system-ui">• Cada dispositivo = una conexión. 50 dispositivos = 50 hilos haciendo polling</text>
<defs>
<marker id="ppArrowEs" markerWidth="10" markerHeight="7" refX="10" refY="3.5" orient="auto"><polygon points="0 0, 10 3.5, 0 7" fill="#64748b"/></marker>
</defs>
</svg>
Esto es lo que sale mal en producción:
- Tu app corre en la nube. AWS, Azure, Railway, DigitalOcean — ninguno puede llegar a un dispositivo detrás de un router en una LAN corporativa. Necesitas un servidor local corriendo 24/7 como puente.
- Los dispositivos cambian de IP. El equipo de TI reinicia el router, expira el lease DHCP, alguien desconecta el switch. Tu cadena de conexión ya es incorrecta, y no recibes datos hasta que alguien lo note.
- El polling no es tiempo real. Le preguntas al dispositivo "¿registros nuevos?" cada 30 segundos. Eso es ancho de banda desperdiciado en respuestas vacías el 95% del tiempo.
- No escala. Gestionar conexiones persistentes a 50+ dispositivos en múltiples oficinas, cada una con su propia configuración de red, es un trabajo de tiempo completo.
El modo pull funciona para un solo dispositivo en una LAN. En cuanto pasas a multi-sitios o la nube, necesitas el modo push.
Modo Push: el dispositivo se conecta a ti
El modo push invierte la dirección de la conexión. El dispositivo inicia la conexión hacia un servidor en la nube, no al revés. El dispositivo no necesita IP estática. Tu servidor no necesita estar en la misma red. El dispositivo solo necesita acceso a internet.
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 320" fill="none" style="width:100%;max-width:800px;">
<text x="400" y="25" text-anchor="middle" fill="#94a3b8" font-size="17" font-weight="bold" font-family="system-ui">Modo Push: el dispositivo se conecta a la nube</text>
<rect x="20" y="60" width="170" height="65" rx="10" stroke="#22d3ee" stroke-width="2" fill="none"/>
<text x="105" y="88" text-anchor="middle" fill="#22d3ee" font-size="14" font-family="system-ui">🖐 Oficina A</text>
<text x="105" y="108" text-anchor="middle" fill="#64748b" font-size="12" font-family="system-ui">(DHCP — cualquier IP)</text>
<rect x="20" y="145" width="170" height="65" rx="10" stroke="#22d3ee" stroke-width="2" fill="none"/>
<text x="105" y="173" text-anchor="middle" fill="#22d3ee" font-size="14" font-family="system-ui">🖐 Oficina B</text>
<text x="105" y="193" text-anchor="middle" fill="#64748b" font-size="12" font-family="system-ui">(Red diferente)</text>
<rect x="20" y="230" width="170" height="65" rx="10" stroke="#22d3ee" stroke-width="2" fill="none"/>
<text x="105" y="258" text-anchor="middle" fill="#22d3ee" font-size="14" font-family="system-ui">🖐 Oficina C</text>
<text x="105" y="278" text-anchor="middle" fill="#64748b" font-size="12" font-family="system-ui">(Detrás de NAT)</text>
<line x1="190" y1="92" x2="310" y2="160" stroke="#34d399" stroke-width="2" marker-end="url(#ppArrow2Es)"/>
<line x1="190" y1="177" x2="310" y2="170" stroke="#34d399" stroke-width="2" marker-end="url(#ppArrow2Es)"/>
<line x1="190" y1="262" x2="310" y2="180" stroke="#34d399" stroke-width="2" marker-end="url(#ppArrow2Es)"/>
<text x="260" y="140" text-anchor="middle" fill="#34d399" font-size="13" font-family="system-ui">push</text>
<rect x="310" y="130" width="190" height="80" rx="12" stroke="#a78bfa" stroke-width="2" fill="none"/>
<text x="405" y="165" text-anchor="middle" fill="#a78bfa" font-size="15" font-family="system-ui">☁️ Motor de</text>
<text x="405" y="187" text-anchor="middle" fill="#a78bfa" font-size="15" font-family="system-ui">protocolo cloud</text>
<line x1="500" y1="170" x2="580" y2="170" stroke="#64748b" stroke-width="2" marker-end="url(#ppArrow2Es)"/>
<text x="540" y="158" text-anchor="middle" fill="#64748b" font-size="13" font-family="system-ui">API REST</text>
<rect x="580" y="130" width="190" height="80" rx="12" stroke="#34d399" stroke-width="2" fill="none"/>
<text x="675" y="165" text-anchor="middle" fill="#34d399" font-size="15" font-family="system-ui">💻 Tu App</text>
<text x="675" y="187" text-anchor="middle" fill="#34d399" font-size="14" font-family="system-ui">(Donde sea)</text>
<defs>
<marker id="ppArrow2Es" markerWidth="10" markerHeight="7" refX="10" refY="3.5" orient="auto"><polygon points="0 0, 10 3.5, 0 7" fill="#34d399"/></marker>
</defs>
</svg>
En modo push, el dispositivo hace el trabajo pesado. Se conecta de salida hacia la nube, envía datos de asistencia en tiempo real, recibe comandos (sincronizar hora, inscribir empleados, reiniciar), y reporta su estado — todo sin que tu servidor necesite iniciar una conexión.
Por qué el modo Push gana
| Factor | Pull (SDK) | Push (Nube) |
|--------|-----------|-------------|
| Red requerida | Misma LAN | Solo internet |
| IP del dispositivo | Estática obligatoria | Cualquiera (DHCP OK) |
| Latencia | 30s–5min de polling | Tiempo real (<1s) |
| Apps en la nube | ❌ Puente local necesario | ✅ Nativo |
| Multi-sitios | ❌ VPN por sitio | ✅ Todo converge a un punto |
| Escalabilidad | 1 hilo por dispositivo | Basado en eventos, sin polling |
| Firewall | Puertos entrantes abiertos | Solo saliente |
La parte difícil: construir un servidor de protocolo push
Aquí es donde la mayoría de los equipos se atoran. El modo push es mejor, pero implementar el servidor que recibe los datos push es complejo. El dispositivo habla un protocolo propietario. Necesitas:
- Analizar correctamente el handshake de conexión del dispositivo
- Manejar autenticación y registro de dispositivos
- Procesar registros de asistencia del formato crudo
- Poner en cola y entregar comandos a los dispositivos
- Gestionar el estado de conexión de decenas de dispositivos simultáneamente
- Manejar reconexiones, timeouts y deduplicación de datos
No es un proyecto de fin de semana. Construir un servidor de protocolo push para producción le tomó a nuestro equipo meses de trabajo y miles de horas de pruebas con 80+ dispositivos en campo.
El enfoque middleware: protocolo de entrada, API REST de salida
PunchConnect se ubica entre tus dispositivos y tu aplicación. Los dispositivos envían datos al motor de protocolo de PunchConnect. Tú consumes endpoints REST API y webhooks limpios. Nunca tocas el protocolo crudo.
Obtener datos de asistencia en tiempo real (ejemplos de código)
Una vez que tu dispositivo está configurado en el panel de PunchConnect (toma unos 5 minutos), interactúas exclusivamente con la API REST:
Obtener registros de asistencia
# Obtener los eventos de asistencia de hoycurl -X GET "https://api.punchconnect.com/v1/attendance?from=2026-03-27T00:00:00Z" \-H "Authorization: Bearer TU_CLAVE_API" \-H "Content-Type: application/json"
Python — Obtener y procesar asistencia
import requestsfrom datetime import datetime, timezoneAPI_KEY = "TU_CLAVE_API"BASE_URL = "https://api.punchconnect.com/v1"def get_attendance(from_date: str = None):"""Obtiene registros de asistencia desde PunchConnect."""params = {}if from_date:params["from"] = from_dateresponse = requests.get(f"{BASE_URL}/attendance",headers={"Authorization": f"Bearer {API_KEY}"},params=params,)response.raise_for_status()return response.json()["data"]def sincronizar_con_tu_sistema(records):"""Envía los registros de asistencia a tu sistema de RH."""for record in records:print(f"[{record['punch_time']}] "f"{record['employee_id']} — "f"{record['punch_type']} "f"({record['verify_mode']})")if __name__ == "__main__":today = datetime.now(timezone.utc).strftime("%Y-%m-%dT00:00:00Z")records = get_attendance(from_date=today)print(f"{len(records)} registros obtenidos")sincronizar_con_tu_sistema(records)
JavaScript — Escuchar webhooks en tiempo real
import express from "express";const app = express();app.use(express.json());app.post("/webhook/attendance", (req, res) => {const event = req.body;console.log(`Nuevo fichaje: ${event.employee_id} a las ${event.punch_time}`);console.log(` Tipo: ${event.punch_type} | Método: ${event.verify_mode}`);console.log(` Dispositivo: ${event.device_serial}`);res.status(200).json({ received: true });});app.listen(3000, () => {console.log("Listener de webhook escuchando en puerto 3000");});
¿Qué dispositivos ZKTeco soportan el modo push?
La mayoría de los dispositivos ZKTeco modernos soportan el modo push. Cualquier dispositivo con firmware ZMM (la mayoría de los fabricados después de 2015) tiene esta capacidad:
- Reconocimiento facial: SpeedFace V5L, SpeedFace-H5, ProFace X
- Huella dactilar: UA860, K40, IN01-A, X7
- Multi-modal: SpeedFace V4L, MultiBio 800
- Control de acceso: inBio 160/260, C3-100/200/400
Cómo verificar: Busca la configuración "Cloud Server" o "ADMS Server" en el menú de configuración de red de tu dispositivo. Si está ahí, tu dispositivo soporta modo push.
Modo push en México y Latinoamérica: contexto regional
Los relojes checadores ZKTeco son los dispositivos biométricos más comunes en empresas mexicanas, colombianas y del Cono Sur. El modo push es especialmente valioso en la región porque:
- Infraestructura de red variable — muchas oficinas en zonas industriales o rurales tienen IPs dinámicas. El modo push funciona con cualquier conexión a internet.
- Multi-sitios distribuidos — empresas agrícolas, manufactureras y de logística con plantillas en múltiples ubicaciones necesitan un punto central de datos sin VPNs costosas.
- Cumplimiento normativo — la NOM-035 en México y las regulaciones laborales colombianas exigen registros de asistencia confiables. El modo push en tiempo real proporciona evidencia inmutable.
Los modelos más comunes en LATAM: ZKTeco K40 (reloj checador de huella), SpeedFace V5L (facial), UA860 (huella + tarjeta). Todos soportan modo push.
Preguntas frecuentes sobre el modo push
¿Necesito abrir puertos del firewall para el modo push?
No. El modo push usa conexiones salientes del dispositivo, igual que un navegador web. Si tu dispositivo puede acceder a internet, puede enviar datos. Sin puertos entrantes, sin IP estática, sin redirección de puertos.
¿Qué tan en tiempo real es el modo push?
Menos de un segundo. Cuando un empleado ficha en el dispositivo, el evento llega a PunchConnect y activa tu webhook en menos de un segundo. Comparado con el polling SDK (30 segundos a 5 minutos), el modo push es prácticamente instantáneo.
¿Qué pasa si se cae el internet?
El dispositivo almacena localmente. Los dispositivos ZKTeco guardan registros en memoria interna (típicamente 50,000–100,000 registros). Cuando vuelve la conectividad, el dispositivo envía automáticamente todos los registros almacenados. PunchConnect los deduplica para que nunca tengas registros duplicados.
¿Se pueden enviar comandos al dispositivo en modo push?
Sí. PunchConnect pone en cola los comandos (inscribir empleados, sincronizar hora, reiniciar, actualizar configuración) y los entrega al dispositivo en el siguiente ciclo push. Envías comandos por la API REST, PunchConnect maneja la entrega.
¿El modo push es compatible con todos los modelos ZKTeco?
El modo push funciona con cualquier dispositivo ZKTeco que tenga la configuración "Cloud Server" o "ADMS Server" — la gran mayoría de los dispositivos fabricados después de 2015. Los dispositivos antiguos (pre-2015) solo soportan modo pull, pero son cada vez más raros en despliegues activos.
Para empezar
Si estás construyendo una integración biométrica y debatiendo entre push y pull:
1. Empieza con modo push. Es la arquitectura correcta para cualquier aplicación en la nube.
2. No construyas el servidor de protocolo tú mismo — a menos que tengas meses de sobra y experiencia profunda con protocolos ZKTeco.
3. Prueba PunchConnect gratis por 7 días — registra tu dispositivo, obtén tu clave API, y recibe tu primer webhook de asistencia en menos de 15 minutos. Sin tarjeta de crédito.
Si ya usas una biblioteca SDK y tienes problemas de escalabilidad, lee nuestra comparación: Por qué las bibliotecas open-source ZKTeco no escalan. Y si tu mayor bloqueo es la IP estática, consulta Asistencia biométrica sin IP estática.
---
*PunchConnect es un middleware probado en producción que conecta dispositivos biométricos ZKTeco a cualquier sistema de software. Actualmente gestiona la asistencia de 24,000+ empleados en 50+ sitios.*