Endpoints vínculos task ↔ Zoho Calendar
functions/api/tasks/[id]/links/calendar.ts — añadido en s68 (commit 7617371, 2026-05-17).
Persiste en D1 las referencias locales a eventos de Zoho Calendar creados desde TaskModal. El evento real vive en Zoho; esta tabla es el registro de vínculos.
Endpoints
GET /api/tasks/{id}/links/calendar
Lista todos los eventos vinculados a la task ordenados por created_at DESC.
Respuesta 200:
[
{
"task_id": 42,
"zoho_event_uid": "abc123",
"calendar_uid": "cal456",
"title": "Revisión presupuesto Rack A",
"start_at": "2026-05-20T10:00:00Z",
"end_at": "2026-05-20T11:00:00Z",
"url": "https://calendar.zoho.eu/",
"created_by": "Edu",
"created_at": "2026-05-17T10:30:00"
}
]
POST /api/tasks/{id}/links/calendar
Crea un vínculo entre la task y un evento ya existente en Zoho (típicamente llamado justo después de POST /api/zoho/calendar).
Body requerido:
{
"zoho_event_uid": "string",
"calendar_uid": "string",
"title": "string (opcional)",
"start_at": "ISO string (opcional)",
"end_at": "ISO string (opcional)",
"url": "string (opcional)"
}
Autenticación: requiere CF Access. created_by = TeamMember resuelto vía resolveTeamMember(request).
Conflicto: ON CONFLICT(task_id, zoho_event_uid) DO UPDATE — actualiza metadatos si el mismo evento se vincula dos veces.
Respuesta 201: el row insertado/actualizado.
Errores:
400—task_idinválido o campos requeridos ausentes.403— actor no identificado como TeamMember.404— task no encontrada en D1.
DELETE /api/tasks/{id}/links/calendar?uid={zoho_event_uid}
Elimina el vínculo (no borra el evento en Zoho).
Query param requerido: uid = zoho_event_uid.
Respuesta 200: { "deleted": 1 } (o 0 si no existía).
Tabla D1: task_calendar_events
CREATE TABLE task_calendar_events (
task_id INTEGER NOT NULL REFERENCES tasks(id),
zoho_event_uid TEXT NOT NULL,
calendar_uid TEXT NOT NULL,
title TEXT,
start_at TEXT,
end_at TEXT,
url TEXT,
created_by TEXT NOT NULL, -- TeamMember
created_at TEXT DEFAULT (datetime('now')),
PRIMARY KEY (task_id, zoho_event_uid)
);
Creada en Migration 0027.
Integración con GET /api/tasks
El listado de tasks incluye calendar_event_count calculado en SQL:
(SELECT COUNT(*) FROM task_calendar_events WHERE task_id = tasks.id) AS calendar_event_count
Esto permite a KanbanMini, TaskTableView y TaskCalendar mostrar badges sin round-trip adicional.
Flujo típico desde TaskModal
Usuario clicka "Crear evento" en TaskZohoLinks
→ POST /api/zoho/calendar { title, start, end, attendees }
← { uid, calendar_uid, url }
→ POST /api/tasks/{id}/links/calendar { zoho_event_uid: uid, calendar_uid, ... }
← 201 LinkRow
→ TaskZohoLinks re-fetchea GET /api/tasks/{id}/links/calendar
Véase también
- [[entity—workers—endpoint—task-email-links]]
- [[entity—workers—service—zoho-lib]]
- [[entity—workers—service—staff-lib]]
- [[feature—zoho—per-user-oauth]]
- [[decision—20260517—integracion-zoho-calendar-mail-pivot]]