Conectar ZKTeco a Odoo: Integración Cloud vía API REST (Sin VPN ni Software Local)
La mayoría de las integraciones ZKTeco-Odoo requieren acceso a la red local, VPN o IP estática. Aprenda cómo conectar ZKTeco a Odoo — incluyendo Odoo Online y Odoo.sh — con una API REST en la nube.
Introduction
Si ha buscado cómo conectar ZKTeco a Odoo, probablemente ya descubrió que la respuesta es más complicada de lo que debería ser. Decenas de hilos en el foro de la comunidad de Odoo hacen la misma pregunta, y las respuestas casi siempre conducen a los mismos callejones sin salida: librerías Python locales que solo funcionan en la misma red que el dispositivo, túneles VPN que su equipo de IT detesta, o configuraciones de IP estática que exponen su red a internet.
Este tutorial toma un enfoque diferente. En lugar de luchar con las limitaciones de la red local, vamos a usar una API REST en la nube para conectar su reloj biométrico ZKTeco con Odoo — ya sea que use Odoo Online, Odoo.sh o una instancia auto-hospedada.
El Problema: Por Qué la Integración Biométrica Odoo Es Tan Difícil
Los dispositivos biométricos ZKTeco (lectores de huella, terminales de reconocimiento facial) están en todas partes. Son accesibles, confiables y ampliamente desplegados en oficinas de toda América Latina y España. Odoo es uno de los ERP de código abierto más populares. Conectar los dos debería ser sencillo. No lo es.
Aquí está el porqué.
Las Herramientas Tradicionales Solo Funcionan en Red Local
Las herramientas más comunes para comunicarse con dispositivos ZKTeco son:
pyzk — Una librería Python que se comunica con dispositivos ZKTeco a través de la red local. Requiere acceso directo al dispositivo desde la misma red. Es de código abierto pero tiene bugs conocidos con versiones de firmware más recientes y mantenimiento limitado.
node-zklib — Un equivalente en Node.js. Misma restricción: la computadora que ejecuta el código debe estar en la misma red que el dispositivo. Existen múltiples forks, ninguno es definitivo.
Módulos del Odoo App Store — Hay varios módulos que prometen integrar ZKTeco con Odoo. Casi todos usan pyzk o node-zklib internamente, lo que significa que heredan la misma dependencia de red local.
Esto Falla con Odoo en la Nube
Si usa Odoo Online (la plataforma SaaS de Odoo), no puede instalar librerías Python personalizadas. Punto. El enfoque con pyzk es imposible.
Si usa Odoo.sh (la plataforma PaaS de Odoo), no puede instalar paquetes Python a nivel de sistema que requieran acceso a hardware local. El enfoque con pyzk falla de nuevo.
Incluso si auto-hospeda Odoo en un VPS o servidor en la nube, su instancia de Odoo está en un centro de datos y su dispositivo ZKTeco está en su oficina. No están en la misma red. Para hacer funcionar pyzk, necesita una de estas soluciones:
Un túnel VPN entre la red de su oficina y su servidor — agrega complejidad, latencia y un costo recurrente.
Redirección de puertos en el router de su oficina para exponer el dispositivo a internet — un riesgo de seguridad significativo.
Una IP estática en su conexión de internet — no disponible con todos los proveedores de internet, y aún así requiere redirección de puertos.
Ninguna de estas opciones es aceptable para uso en producción, especialmente si gestiona dispositivos en múltiples ubicaciones.
El Enfoque Cloud: Configure Una Vez, Acceda Desde Cualquier Lugar
Existe una arquitectura mejor. En lugar de que Odoo acceda a su red local para obtener datos del dispositivo, el dispositivo envía los datos a la nube de PunchConnect, y Odoo los consulta desde ahí mediante una API REST estándar.
Usted configura el dispositivo una sola vez a través del panel de PunchConnect. Después, los datos de asistencia fluyen automáticamente a la nube. Su instancia de Odoo los consulta mediante una API REST estándar — sin software local, sin VPN, sin IP estática. Solo llamadas HTTPS desde cualquier lugar.
Esto funciona con todos los modelos de implementación de Odoo: Online, .sh y auto-hospedado. Consulte nuestra documentación de la API para la referencia completa de endpoints.
ZKTeco Device ──(auto-sync)──> PunchConnect Cloud ──(REST API)──> Odoo
│
└──(Webhook)──> Your server (optional)Paso a Paso: Conectar ZKTeco a Odoo con PunchConnect
Requisitos Previos
Un dispositivo ZKTeco (la mayoría de los modelos modernos son compatibles — incluyendo las series K, uFace, SpeedFace, ProFace y MB).
Una instancia de Odoo (cualquier versión, cualquier modelo de hospedaje).
Una cuenta de PunchConnect. Inicie su prueba gratuita de 7 días — no se requiere tarjeta de crédito.
Paso 1: Registre Su Dispositivo en PunchConnect
Después de crear su cuenta de PunchConnect, recibirá un token de API (con prefijo pc_live_). Úselo para registrar su dispositivo.
Python:
JavaScript (Node.js):
```javascript
const API_TOKEN = "pc_live_your_token_here";
const BASE_URL = "https://api.punchconnect.com";
const response = await fetch(${BASE_URL}/v1/devices, {
method: "POST",
headers: {
Authorization: Bearer ${API_TOKEN},
"Content-Type": "application/json",
},
body: JSON.stringify({
serial_number: "BFGH234900045",
name: "Main Entrance - Floor 1",
location: "Headquarters",
}),
});
const device = await response.json();
console.log(Device ID: ${device.id});
console.log(Status: ${device.status});
```
import requests
API_TOKEN = "pc_live_your_token_here"
BASE_URL = "https://api.punchconnect.com"
# Register a new device
response = requests.post(
f"{BASE_URL}/v1/devices",
headers={
"Authorization": f"Bearer {API_TOKEN}",
"Content-Type": "application/json"
},
json={
"serial_number": "BFGH234900045",
"name": "Main Entrance - Floor 1",
"location": "Headquarters"
}
)
device = response.json()
print(f"Device ID: {device['id']}")
print(f"Status: {device['status']}")Paso 2: Conecte el Dispositivo
Una vez registrado, siga las instrucciones de configuración en el panel de PunchConnect para conectar su dispositivo ZKTeco. El proceso toma aproximadamente 5 minutos por dispositivo — ingresará algunas configuraciones en el panel de administración del dispositivo y comenzará a sincronizar automáticamente.
En menos de 60 segundos después de la configuración, el dispositivo aparece como "online" en su panel. Puede verificarlo a través de la API:
response = requests.get(
f"{BASE_URL}/v1/devices",
headers={"Authorization": f"Bearer {API_TOKEN}"}
)
for device in response.json()["data"]:
print(f"{device['name']}: {device['status']}")
# Output: "Main Entrance - Floor 1: online"Paso 3: Configure Webhooks para Asistencia en Tiempo Real
Para sincronización de asistencia en tiempo real, configure un webhook. PunchConnect enviará eventos de asistencia mediante POST a su URL conforme ocurran — sin necesidad de polling.
Cada POST del webhook incluye un payload JSON con el ID del empleado, la marca de tiempo, información del dispositivo y la dirección de la marcación (entrada/salida).
Si no puede recibir webhooks (por ejemplo, en Odoo Online), pase al Paso 4 — puede consultar la API con un cron en su lugar.
response = requests.post(
f"{BASE_URL}/v1/webhooks",
headers={
"Authorization": f"Bearer {API_TOKEN}",
"Content-Type": "application/json"
},
json={
"url": "https://your-odoo-instance.com/api/punchconnect/webhook",
"events": ["attendance.created"],
"secret": "your_webhook_secret"
}
)
webhook = response.json()
print(f"Webhook ID: {webhook['id']}")
print(f"Status: {webhook['status']}")Paso 4: Obtenga los Datos de Asistencia en Odoo
Aquí es donde todo se conecta. Este script Python obtiene registros de asistencia de PunchConnect y crea entradas de asistencia en Odoo usando la API XML-RPC de Odoo.
Esto funciona desde cualquier computadora que tenga acceso a internet — un cron job en su servidor, una acción programada de Odoo, o incluso una función serverless.
Puede ejecutar este script como una acción programada de Odoo (ir.cron) que se ejecute cada 10-15 minutos, un cron job en cualquier servidor, o un manejador de webhooks que procese registros en tiempo real desde el Paso 3.
import requests
import xmlrpc.client
from datetime import datetime, timedelta
# ---------- PunchConnect Config ----------
PC_TOKEN = "pc_live_your_token_here"
PC_BASE = "https://api.punchconnect.com"
# ---------- Odoo Config ----------
ODOO_URL = "https://your-company.odoo.com"
ODOO_DB = "your-database"
ODOO_USER = "admin@yourcompany.com"
ODOO_PASSWORD = "your_api_key"
# ---------- Connect to Odoo ----------
common = xmlrpc.client.ServerProxy(f"{ODOO_URL}/xmlrpc/2/common")
uid = common.authenticate(ODOO_DB, ODOO_USER, ODOO_PASSWORD, {})
models = xmlrpc.client.ServerProxy(f"{ODOO_URL}/xmlrpc/2/object")
# ---------- Fetch Recent Attendance from PunchConnect ----------
since = (datetime.utcnow() - timedelta(hours=1)).isoformat() + "Z"
response = requests.get(
f"{PC_BASE}/v1/attendance",
headers={"Authorization": f"Bearer {PC_TOKEN}"},
params={
"since": since,
"limit": 100
}
)
records = response.json()["data"]
print(f"Fetched {len(records)} attendance records")
# ---------- Sync to Odoo ----------
for record in records:
# Look up the Odoo employee by badge ID
employee_ids = models.execute_kw(
ODOO_DB, uid, ODOO_PASSWORD,
"hr.employee", "search",
[[["barcode", "=", record["employee_id"]]]]
)
if not employee_ids:
print(f"No Odoo employee found for badge {record['employee_id']}, skipping")
continue
employee_id = employee_ids[0]
punch_time = record["timestamp"]
if record["direction"] == "in":
# Create check-in record
models.execute_kw(
ODOO_DB, uid, ODOO_PASSWORD,
"hr.attendance", "create",
[{"employee_id": employee_id, "check_in": punch_time}]
)
print(f"Check-in recorded for employee {employee_id} at {punch_time}")
elif record["direction"] == "out":
# Find open attendance and set check-out
open_attendance = models.execute_kw(
ODOO_DB, uid, ODOO_PASSWORD,
"hr.attendance", "search",
[[
["employee_id", "=", employee_id],
["check_out", "=", False]
]],
{"limit": 1, "order": "check_in desc"}
)
if open_attendance:
models.execute_kw(
ODOO_DB, uid, ODOO_PASSWORD,
"hr.attendance", "write",
[open_attendance, {"check_out": punch_time}]
)
print(f"Check-out recorded for employee {employee_id} at {punch_time}")Extra: Sincronice Empleados Hacia el Dispositivo
También puede enviar empleados desde Odoo hacia su dispositivo ZKTeco a través de PunchConnect, para que los nuevos ingresos aparezcan en el dispositivo automáticamente:
# Fetch employees from Odoo
employees = models.execute_kw(
ODOO_DB, uid, ODOO_PASSWORD,
"hr.employee", "search_read",
[[["active", "=", True]]],
{"fields": ["id", "name", "barcode"]}
)
# Sync to PunchConnect (which syncs to the device)
response = requests.post(
f"{PC_BASE}/v1/employees/sync",
headers={
"Authorization": f"Bearer {PC_TOKEN}",
"Content-Type": "application/json"
},
json={
"employees": [
{
"id": str(emp["barcode"]),
"name": emp["name"]
}
for emp in employees
if emp["barcode"]
]
}
)
result = response.json()
print(f"Synced {result['synced']} employees, {result['errors']} errors")Odoo Online vs Auto-Hospedado: Qué Enfoque Funciona en Cada Caso
Si usa Odoo Online, no puede instalar librerías Python personalizadas. El enfoque con pyzk/node-zklib es imposible. Una API REST en la nube como PunchConnect es su única opción viable para la integración biométrica Odoo con ZKTeco.
Si usa Odoo.sh, no puede instalar paquetes a nivel de sistema que se comuniquen con hardware local. Mismo resultado — las herramientas tradicionales basadas en red local no van a funcionar.
Si auto-hospeda Odoo en un VPS o servidor en la nube, técnicamente podría configurar VPN + pyzk, pero toma horas configurarlo, requiere monitoreo constante de la VPN y se rompe cuando su proveedor de internet cambia su IP. Con PunchConnect, la configuración toma menos de 30 minutos y funciona en todas sus ubicaciones desde una sola API.
El enfoque tradicional también lo limita a polling únicamente (ejecutar un script periódicamente para extraer datos del dispositivo). PunchConnect soporta webhooks en tiempo real, de modo que los eventos de asistencia llegan a Odoo en segundos después de cada marcación.
Para despliegues en múltiples ubicaciones, la diferencia es aún más notoria. Una configuración basada en VPN requiere configuración individual por sede. PunchConnect gestiona todos los dispositivos desde un solo panel y una sola API — ya sea que tenga 2 dispositivos o 200.
Precios
PunchConnect cuesta $200 USD por dispositivo (licencia única) más $50 USD/año para renovaciones a partir del Año 2. No hay cargos por usuario, lo cual importa a escala — ya sea que tenga 10 empleados o 10,000 por dispositivo, el precio es el mismo.
Hay descuentos por volumen disponibles: 10+ dispositivos a $180, 25+ a $160, 50+ con precio personalizado. Vea el desglose completo en nuestra página de precios.
PunchConnect actualmente maneja cargas de producción con más de 24,000 empleados en múltiples ubicaciones — así que opera a escala real.
Preguntas Frecuentes
Es posible conectar ZKTeco a Odoo Online sin instalar software local? Sí. PunchConnect es una API REST en la nube — su dispositivo ZKTeco sincroniza datos con la nube de PunchConnect, y su instancia de Odoo Online los consulta mediante llamadas HTTPS estándar. Sin software local, sin VPN, sin IP estática.
Qué modelos de reloj biométrico ZKTeco son compatibles? La mayoría de los modelos modernos de ZKTeco son compatibles, incluyendo las series K, uFace, SpeedFace, ProFace y MB. Si su lector de huella o terminal facial tiene capacidad de conexión a servidor cloud, va a funcionar. Contáctenos si tiene dudas sobre un modelo específico.
Funciona con Odoo Community o solo con Odoo Enterprise? Funciona con ambas ediciones. La integración usa la API XML-RPC de Odoo, que está disponible tanto en Odoo Community como en Enterprise, en cualquier versión desde Odoo 12 en adelante.
Cuánto tarda la configuración inicial del control de asistencia cloud? Registrar el dispositivo en PunchConnect toma menos de 5 minutos. Configurar el script de sincronización con Odoo toma entre 15 y 30 minutos dependiendo de su experiencia. En total, puede tener el sistema de asistencia funcionando en menos de una hora.
PunchConnect funciona si tengo oficinas en varios países de Latinoamérica? Sí. PunchConnect gestiona todos sus dispositivos desde un solo panel y una sola API, sin importar su ubicación geográfica. Ya sea que tenga dispositivos en México, Colombia, Chile o cualquier otro país, todos se administran de forma centralizada sin necesidad de VPN ni configuración de red por sede.
Comience Ahora
Conectar ZKTeco a Odoo no tiene por qué involucrar VPNs, IPs estáticas ni scripts locales frágiles. El enfoque de API REST en la nube es más simple, más seguro y funciona con todos los modelos de implementación de Odoo.
Inicie su prueba gratuita de 7 días — no se requiere tarjeta de crédito. Registre su dispositivo y conéctelo a través del panel en aproximadamente 15 minutos. Luego ejecute el script de sincronización anterior o configure webhooks para asistencia en tiempo real.
Si tiene preguntas sobre la integración o necesita ayuda con su modelo específico de ZKTeco, escríbanos a través de nuestra página de contacto. Tenemos experiencia con prácticamente todas las variantes de firmware de ZKTeco.