Primeros pasos
De cero al Resumen de un mes en tres pasos.
1. Crear una llave
En la app de Kabal, un administrador de la empresa abre API en el menú y pulsa Nueva llave. La llave lleva un nombre (para qué es, por ejemplo "Planilla") y un vencimiento: 30, 90 o 365 días, una fecha, o ninguno.
La llave se muestra una sola vez: cópiela y guárdela como un secreto, en el mismo lugar donde su sistema guarda sus otras credenciales. Kabal solo guarda una huella de ella y no puede volver a mostrarla; si se pierde, cree otra y revoque la anterior.
Una llave se ve así:
kba_4Hq0x9mT1vZp8bLwYc3RkN7sJ2dF6gAeU5oXiQyKtMh
2. Pedir el Resumen
Mande la llave en la cabecera Authorization, como un token bearer, y pida un rango de fechas. Las fechas son civiles en la zona horaria de la empresa, las dos incluidas:
curl -H "Authorization: Bearer $KABAL_API_KEY" \
"https://app.kabal-attendance.com/api/v1/reports/summary/?date_from=2026-10-01&date_to=2026-10-31"
La respuesta es una fila por empleado activo de todas las sedes, ordenadas por código:
{
"date_from": "2026-10-01",
"date_to": "2026-10-31",
"company_timezone": "America/Guatemala",
"results": [
{
"employee": "0193a4b2-7c1e-7d40-9a51-3f2c8b6e1d07",
"code": "E001",
"name": "Ana López",
"location": "0193a4b2-6f00-7a10-8c22-1b9d4e5f6a70",
"location_name": "Oficina central",
"expected_days": 22,
"expected_minutes": 10560,
"late_days": 3,
"late_minutes": 41,
"worked_minutes": 10612,
"ordinary_minutes": 10480,
"extra_minutes": 132,
"has_pending": false
}
]
}
La fila de arriba va recortada: la referencia lista todos los campos.
3. Leer lo que debe una persona
Lo que debe cada persona en el rango es una resta sobre la misma fila:
debe = expected_minutes - ordinary_minutes
Los turnos de Ana pedían 10 560 minutos y trabajó 10 480 de ellos: debe 80 minutos. Sus 132 minutos extra no los pagan, porque los minutos ordinarios nunca incluyen tiempo extra. Reportes explica cuándo vale la resta y cuándo conviene esperar antes de confiar en ella.
Un script para el cierre mensual
import os
import requests
BASE = 'https://app.kabal-attendance.com/api/v1'
session = requests.Session()
session.headers['Authorization'] = f"Bearer {os.environ['KABAL_API_KEY']}"
summary = session.get(
f'{BASE}/reports/summary/',
params={'date_from': '2026-10-01', 'date_to': '2026-10-31', 'include_inactive': 'true'},
timeout=60,
)
summary.raise_for_status()
for row in summary.json()['results']:
owed = row['expected_minutes'] - row['ordinary_minutes']
print(row['code'], row['late_days'], row['late_minutes'], owed, row['has_pending'])
include_inactive=true trae también a quienes se fueron durante el mes; sin él solo vuelven los empleados activos hoy.
Lo siguiente
- Autenticación: qué significa cada 401 y cada 403.
- Reportes: el Detalle, sus páginas y cada columna.