Referencia técnica completa para conectar agentes IA con Google Calendar y Microsoft Outlook vía API REST
Automatización completa de reservas para el equipo comercial
Autenticación OAuth 2.0 y operaciones CRUD de eventos
import { google } from 'googleapis'; // OAuth 2.0 — contexto de usuario const oauth2Client = new google.auth.OAuth2( process.env.GOOGLE_CLIENT_ID, process.env.GOOGLE_CLIENT_SECRET, process.env.GOOGLE_REDIRECT_URI ); const { tokens } = await oauth2Client.getToken(authCode); oauth2Client.setCredentials(tokens); const calendar = google.calendar({ version: 'v3', auth: oauth2Client }); // Service Account — acceso servidor a servidor const auth = new google.auth.GoogleAuth({ keyFile: '/path/service-account.json', scopes: ['https://www.googleapis.com/auth/calendar'], clientOptions: { subject: 'alba@cultivaia.com' }, });
// Consultar disponibilidad semana 16-20 jun const { data } = await calendar.freebusy.query({ requestBody: { timeMin: '2026-06-16T09:00:00+02:00', timeMax: '2026-06-20T18:00:00+02:00', timeZone: 'Europe/Madrid', items: [ { id: 'alba@cultivaia.com' }, { id: 'marc@cultivaia.com' }, ], }, }); // Bloques ocupados por persona const albaBusy = data.calendars['alba@cultivaia.com'].busy; const marcBusy = data.calendars['marc@cultivaia.com'].busy; // → buscar ventana de 1h libre para ambos const slot = findCommonSlot(albaBusy, marcBusy, 60);
const event = await calendar.events.insert({ calendarId: 'primary', conferenceDataVersion: 1, // activa creación automática de Meet sendUpdates: 'all', // notifica a todos los asistentes requestBody: { summary: 'Onboarding CULTIVA IA · Finca Rural El Molino', description: 'Sesión de onboarding inicial.\n\nAgenda:\n- Diagnóstico digital\n- Propuesta de automatizaciones\n- Siguiente paso', start: { dateTime: '2026-06-17T10:00:00', timeZone: 'Europe/Madrid' }, end: { dateTime: '2026-06-17T11:00:00', timeZone: 'Europe/Madrid' }, attendees: [ { email: 'alba@cultivaia.com', displayName: 'Alba Ros', responseStatus: 'accepted' }, { email: 'marc@cultivaia.com', displayName: 'Marc Pont', responseStatus: 'accepted' }, { email: 'info@elmolino.es', displayName: 'Finca El Molino' }, ], conferenceData: { createRequest: { requestId: 'cultiva-molino-' + Date.now(), conferenceSolutionKey: { type: 'hangoutsMeet' }, }, }, reminders: { useDefault: false, overrides: [ { method: 'email', minutes: 1440 }, // 24h antes { method: 'popup', minutes: 15 }, // 15min antes ], }, }, }); console.log('✅ Evento creado:', event.data.htmlLink); console.log('📹 Meet link:', event.data.conferenceData?.entryPoints?.[0]?.uri); // → https://meet.google.com/abc-defg-hij
Azure AD OAuth 2.0 y operaciones avanzadas (findMeetingTimes)
import { ClientSecretCredential } from '@azure/identity'; import { Client } from '@microsoft/microsoft-graph-client'; import { TokenCredentialAuthenticationProvider } from '@microsoft/microsoft-graph-client/authProviders/azureTokenCredentials'; const credential = new ClientSecretCredential( process.env.AZURE_TENANT_ID, process.env.AZURE_CLIENT_ID, process.env.AZURE_CLIENT_SECRET ); const authProvider = new TokenCredentialAuthenticationProvider( credential, { scopes: ['https://graph.microsoft.com/.default'] } ); const graphClient = Client.initWithMiddleware({ authProvider }); // → listo para llamadas a /users/{id}/events
const suggestions = await graphClient .api(`/users/${marcUserId}/findMeetingTimes`) .post({ attendees: [{ emailAddress: { address: 'alba@cultivaia.com' }, type: 'required', }], timeConstraint: { timeslots: [{ start: { dateTime: '2026-06-16T09:00:00', timeZone: 'Romance Standard Time' }, end: { dateTime: '2026-06-20T18:00:00', timeZone: 'Romance Standard Time' }, }]}, meetingDuration: 'PT1H', maxCandidates: 5, minimumAttendeePercentage: 100, }); // suggestions.meetingTimeSuggestions[0].meetingTimeSlot // → { start: { dateTime: '2026-06-17T08:00:00', ... } }
Patrones de recurrencia estándar iCalendar para Google Calendar
recurrence estructurado con pattern (daily/weekly/monthly) + range (startDate/endDate/numberOfOccurrences).Diferencias clave para elegir la integración adecuada
| Funcionalidad | Google Calendar | Outlook / Graph |
|---|---|---|
| Autenticación | Google OAuth 2.0 · Service Account | Azure AD OAuth 2.0 · Client Secret |
| Videollamada integrada | hangoutsMeet via conferenceData |
isOnlineMeeting: true (Teams) |
| Consulta disponibilidad | freebusy.query |
getSchedule / findMeetingTimes |
| Webhooks (duración máx.) | Push notifications · 7 días | Subscriptions · 3 días |
| Eventos recurrentes | RRULE strings (iCalendar) | Objeto recurrence estructurado |
| Smart scheduling | No nativo (implementar manualmente) | findMeetingTimes con ranking |
| Sync eficiente | Sync tokens (incremental) | Delta queries (incremental) |
| Límite de tasa | ~10 QPS por usuario | 10.000 req / 10 min por app/tenant |
| Librerías oficiales | googleapis |
@microsoft/microsoft-graph-client |
Reglas críticas para una integración robusta en producción
Europe/Madrid o el TZ del cliente explícitamente.new Date().toISOString() o date-fns.sendUpdates: 'all'. Los cambios silenciosos causan confusión y faltas de asistencia.