Inicio rápido
La API REST de Gantlog expone proyectos, tareas, dependencias, asignaciones, horas, avance, alertas y usuarios de tu empresa. Lectura y escritura, JSON, versionada en /api/v1, con un contrato OpenAPI público como fuente única. Está incluida desde el plan Empresa.
https://app.gantlog.com/api/v11. Crea una API key
En la aplicación, un administrador va a Integraciones → Claves de API → Nueva clave de API, elige los alcances (por ejemplo projects:read, time:write), si quiere la limita a algunos proyectos y copia la clave (empieza con glk_). Se muestra una sola vez. Ver el paso a paso.
2. Haz tu primera llamada
curl "https://app.gantlog.com/api/v1/projects" \
-H "Authorization: Bearer $GANTLOG_API_KEY" \
-H "Accept: application/json"const res = await fetch('https://app.gantlog.com/api/v1/projects', {
headers: { Authorization: `Bearer ${process.env.GANTLOG_API_KEY}` },
});
const projects = await res.json();import os, requests
r = requests.get("https://app.gantlog.com/api/v1/projects",
headers={"Authorization": f"Bearer {os.environ['GANTLOG_API_KEY']}"})
projects = r.json()[
{ "id": "0b7c…e41", "code": "ERP", "name": "Implantación ERP", "kind": "PLAN",
"status": "ACTIVE", "startDate": "2026-09-01", "finishDate": "2026-12-18",
"estimateHours": 1240, "canManage": true }
]Autenticación y alcances
Envía la clave en la cabecera Authorization: Bearer glk_…. La empresa se determina por la clave, nunca por un parámetro. La clave actúa con los permisos del administrador que la creó, recortados por sus alcances y, si tiene, por su lista de proyectos; si esa persona se desactiva o deja de ser administradora, la clave deja de funcionar. Lo que cambia una clave queda en el historial como «Integración: <nombre de la clave>». Una clave nunca crea otras claves, cambia roles ni usa las rutas de sesión.
Rotar entrega una clave nueva y deja la anterior válida 24 horas para cambiarla sin corte. Revocar la apaga al momento.
| Alcance | Permite |
|---|---|
projects:read | Leer proyectos, fases, tareas, dependencias, asignaciones, horas, avance, curva S y alertas |
projects:write | Crear y cambiar proyectos, fases, tareas y dependencias |
assignments:write | Asignar personas y horas a las tareas |
time:write | Registrar horas y avance (con Idempotency-Key) |
users:read | Leer usuarios, jornadas, capacidad, calendarios, feriados y ausencias |
webhooks:manage | Crear y administrar suscripciones a eventos |
bi:read | Lectura para Power BI y Excel (OData v4 en /odata/v1); no usa la API REST |
Convenciones
- Recursos en plural, en inglés y en kebab-case; JSON en camelCase; fechas
YYYY-MM-DDe instantes ISO 8601 en UTC. - Paginación por página (
page,size,sort); el plan del Gantt se entrega completo. - Bloqueo optimista con
ETag/If-Match:428si falta,412si no coincide. - Idempotencia: cabecera
Idempotency-Keyobligatoria al registrar horas y avance.
Referencia
Resumen de las operaciones principales. La referencia completa se genera desde la especificación OpenAPI con parámetros, esquemas y ejemplos.
Proyectos
/projectsProyectos que ve la clavePOST/projectsCrear un plan o un tableroGET/projects/{id}Detalle con ETag, fin proyectado y atrasoPATCH/projects/{id}JSON Merge Patch; requiere If-MatchGET/projects/{id}/planPlan completo del Gantt con la fila resumenGET/projects/{id}/progress-curveCurva S: % esperado y real por díaTareas y dependencias
/projects/{id}/tasksFases y tareas del plan, en orden de árbolPOST/projects/{id}/tasksCrear una tarea o una fasePATCH/tasks/{id}Nombre, fechas, campos; recalcula el planDELETE/tasks/{id}Borrar (con horas, pide confirmación)PUT/tasks/{id}/predecessorsPredecesoras fin-inicio (FS) o inicio-inicio (SS) con desfaseAsignaciones, horas y avance
/tasks/{id}/assignmentsPersonas, % y horas de la tareaPUT/tasks/{id}/assignmentsDeja exactamente las enviadas; 409 si sobreasignaGET/tasks/{id}/work-logsHoras registradas en la tareaPOST/work-logsRegistrar horas (Idempotency-Key obligatoria)POST/tasks/{id}/progress-updatesReportar avance (Idempotency-Key obligatoria)Usuarios y calendarios
Alertas
Webhooks
Webhooks
Suscribe una URL https a eventos (con webhooks:manage o desde Integraciones) y recibe un POST firmado. Un 2xx en menos de 10 segundos cuenta como entregado; los fallos se reintentan con espera creciente durante 24 horas y, tras 3 días de fallos seguidos, la suscripción se pausa y se avisa a los administradores. Solo llegan eventos de proyectos que ve quien creó la suscripción. No se aceptan URLs a direcciones privadas, de loopback ni de metadatos de la nube, y no se siguen redirecciones.
Cuerpo: { "id", "type", "occurredAt", "tenantId", "data" }. Usa id para descartar duplicados. En los eventos de tareas, data.task trae la fila de la tarea como la da la API.
project.createdSe creó un proyecto o tablero
task.createdNueva tarea, subtarea o incidencia
task.updatedCambió una tarea (con los cambios)
task.rescheduledEl motor de fechas movió una tarea
task.status_changedUna tarea cambió de estado
work_log.createdAlguien registró horas
time.approvedSe aprobó una línea del timesheet (una por línea)
progress.reportedSe reportó avance de una asignación
baseline.savedSe guardó una línea base
alert.raisedSe abrió una alerta de atraso
alert.resolvedSe resolvió una alerta
Gantlog-Signature: t=1761130000,v1=5f1c…9a
# v1 = HMAC_SHA256(secreto, `${t}.${cuerpo}`) en hexadecimal; rechaza si |ahora − t| > 5 min// Node.js (Express con el cuerpo crudo)
import crypto from 'node:crypto';
function verificar(cabecera, cuerpo, secreto) {
const { t, v1 } = Object.fromEntries(cabecera.split(',').map((p) => p.split('=')));
if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return false;
const esperado = crypto.createHmac('sha256', secreto).update(`${t}.${cuerpo}`).digest('hex');
return crypto.timingSafeEqual(Buffer.from(esperado), Buffer.from(v1));
}# Python
import hmac, hashlib, time
def verificar(cabecera: str, cuerpo: bytes, secreto: str) -> bool:
partes = dict(p.split("=", 1) for p in cabecera.split(","))
if abs(time.time() - int(partes["t"])) > 300:
return False
esperado = hmac.new(secreto.encode(), partes["t"].encode() + b"." + cuerpo, hashlib.sha256).hexdigest()
return hmac.compare_digest(esperado, partes["v1"])Errores
Formato Problem Details (RFC 9457) con un code estable. Ejemplo de conflicto por sobreasignación:
HTTP/1.1 409 Conflict
Content-Type: application/problem+json
{ "type": "https://www.gantlog.com/docs/api/#errores",
"title": "Persona sobreasignada", "status": 409, "code": "overallocation",
"conflicts": [ { "date": "2026-11-05", "projectId": 17, "hours": 10.5 } ] }| Estado | code | Cuándo |
|---|---|---|
| 400 | validation | Cuerpo o parámetros inválidos; errors detalla cada campo |
| 401 | unauthenticated | Falta la clave, no existe, se revocó, venció o se desactivó |
| 403 | forbidden | La clave no tiene el alcance o la operación no es pública |
| 404 | not-found | No existe, es de otra empresa o está fuera de los proyectos de la clave |
| 409 | overallocation | La asignación sobreasigna a la persona; conflicts lista días y proyectos |
| 412 | version-conflict | El If-Match no coincide con la versión actual |
| 422 | business-rule | La petición es válida, pero viola una regla del dominio |
| 428 | precondition-required | Falta If-Match en una modificación |
| 429 | rate-limited | Límite por minuto de la clave o del mes de la empresa; ver Retry-After |
Límites de uso
Peticiones por minuto por clave y por mes por empresa (mes calendario en UTC), según el plan. Al pasarse recibes 429 rate-limited con Retry-After. Las cabeceras RateLimit-Limit, RateLimit-Remaining y RateLimit-Reset (segundos) van en todas las respuestas. Al 80 % y al 100 % del mes se avisa a los administradores. Cada consulta tiene un tiempo máximo de 15 s y hay un tope de peticiones simultáneas por servidor (también 429, reintenta en un segundo).
| Plan | Por clave | Por empresa |
|---|---|---|
| Equipo | — | No incluye la API |
| Empresa | 120 por minuto por clave | 200 000 al mes por empresa |
| Corporativo | 600 por minuto por clave | 2 000 000 al mes por empresa |
Changelog de la API
- v1 · 2026-11 · Power Automate: conector de Power Automate y Power Apps, disparadores
POST /webhooks/triggers/…, eventotime.approved,Locationabsoluta en las altas de suscripciones, tope de suscripciones por plan, la clave también sinBearery el contrato con los códigos reales (201,204) y sus errores. - v1 · 2026-10 · lectura para BI: OData v4 en
/odata/v1para Power BI y Excel con el alcancebi:read, carga incremental pormodifiedAty plantilla de Power BI. - v1 · 2026-10: primera versión pública: claves de API con alcances, proyectos, tareas, dependencias, asignaciones, horas, avance, curva S, usuarios, calendarios, ausencias, alertas y webhooks firmados. Dentro de v1 no hay cambios incompatibles (el CI compara el contrato público con el anterior); los incompatibles se publican como
/api/v2y v1 se mantiene al menos 12 meses después.