Cómo integrar Outlook Calendar API en tu aplicación

Autores
Publicado el

Integra todos los calendarios con una sola API

Únete a nuestra lista de espera para la Unified Calendar API y obtén acceso a nuestra Unified Calendar API, que te permite integrar todos los proveedores de calendarios en tu aplicación usando una única API.

Unirse a la lista de esperaNo se requiere tarjeta de crédito!

En nuestro último artículo sobre cómo integrar la API de Google Calendar en tu aplicación, explicamos todos los pasos que un desarrollador debe seguir para integrar la API de Google Calendar en su aplicación.

En este artículo, explicaremos cómo integrar la API de Outlook Calendar en tu aplicación, incluyendo la configuración del registro de la aplicación en Azure, la asignación de ámbitos, la verificación, las complicaciones de la integración y ejemplos reales.

Requisitos previos

Esta guía asume que ya tienes una cuenta Microsoft Work o Developer con acceso a Azure Active Directory.

Ten en cuenta que se ha desaprobado la posibilidad de crear aplicaciones fuera de un directorio. Si no tienes un directorio, deberías unirte al Programa para Desarrolladores de Microsoft 365 o registrarte en Azure.

Cómo usar e integrar la API de Outlook Calendar en tu aplicación

Paso 1: Inicia sesión en el Portal de Microsoft Azure

Visita la página de inicio de sesión del Portal de Microsoft Azure e inicia sesión.

La página del Portal de Microsoft Azure.

Sign in to the Microsoft Azure Portal

Paso 2: Registra una nueva aplicación

Después de iniciar sesión en el Portal de Microsoft Azure:

  1. Navega a Azure Active Directory

    Azure App Directory Home
  2. Busca “App Registrations” en la barra de búsqueda

    Search App Registrations
  3. Haz clic en “App Registrations”

    Click App Registrations
  4. Haz clic en “New registration”

    Click New Registration
  5. Rellena los campos requeridos:

    Azure Active Directory - Register the application
    1. El primer campo es el Nombre de tu aplicación, que es el nombre visible para los usuarios.

    2. A continuación, selecciona los tipos de cuenta admitidos. La selección variará según el tipo de aplicación que estés desarrollando (uso interno o multi-tenant). Para este ejemplo, seleccionaré “Accounts in any organizational directory (Any Microsoft Entra ID tenant – Multitenant)”, ya que permite que usuarios de cualquier organización (incluidos los de Outlook.com) utilicen mi aplicación. Esto es ideal para aplicaciones SaaS o multi-tenant.

    3. Introduce la URI de redirección: es opcional, pues podría no ser necesaria según el tipo de aplicación. Si desarrollas una aplicación web, probablemente la necesites, ya que esta URI es donde Azure enviará las respuestas OAuth. Bajo “Select a platform”, elige Web y añade la URI de redirección (por ejemplo, https://tuapp.com/auth/callback). Para la autenticación del lado del servidor, una URI web es adecuada. Asegúrate de que el dominio sea accesible y esté bajo tu control.

    4. Haz clic en “Register”.

    5. Tras hacer clic en “Register”, Azure Active Directory creará tu aplicación y te llevará a la siguiente página, donde podrás copiar el Client ID y el Tenant ID. El Application (client) ID es un GUID que identifica tu app. El Directory (tenant) ID no siempre es necesario; en la mayoría de los casos, para apps multi-tenant se usa el endpoint common. Puedes usar el tenant ID para pruebas en tu propio tenant.

      Application Created

Guarda los campos Client ID y Tenant ID en un lugar seguro; normalmente se almacenan como variables de entorno.

Paso 3: Configura los permisos de la API

Después de registrar la app, es momento de configurar los permisos de calendario. Estos permisos se muestran en el flujo OAuth para que el usuario sepa a qué ámbitos accederá tu aplicación antes de otorgar acceso.

De forma predeterminada, tu aplicación tiene el permiso “User.Read”. Si solo necesitas iniciar sesión y leer el perfil del usuario, puedes omitir este paso.

Para añadir permisos de API, sigue estos pasos:

  1. Haz clic en la pestaña “Manage” en la barra lateral izquierda.

  2. Haz clic en “API Permissions”.

    Click API Permissions
  3. Haz clic en el botón “+ Add a permission”.

    Click _Add a permission_ button
  4. Busca la tarjeta “Microsoft Graph” (suele ser la primera del panel derecho).

    Click the _Microsoft Graph_ card
  5. Elige entre “Delegated permissions” y “Application permissions”. Las primeras son útiles cuando tu app necesita acceso como el usuario autenticado. Las de aplicación se usan cuando tu app funciona como servicio en segundo plano sin usuario autenticado. Para este ejemplo usaré “Delegated Permissions”.

    Click _Delegated Permissions_
  6. Busca “Calendars”: esto mostrará todos los permisos relacionados con calendarios. Selecciona los que permitan que tu app funcione correctamente. En la mayoría de los casos, querrás “Calendars.ReadWrite” y “Calendars.ReadWrite.Shared” (si necesitas acceder a calendarios compartidos). Estos ámbitos no suelen requerir consentimiento de administrador, pero algunas organizaciones restringen el consentimiento del usuario. Si un usuario externo no puede consentir, un administrador de ese tenant deberá otorgar el consentimiento.

    Search for _Calendars Permissions_

Paso 4: Genera un Client Secret

Recomendamos que las operaciones de calendario (escrituras, lecturas, actualizaciones, etc.) se hagan desde el servidor; por eso necesitas generar un client secret.

Para ello:

  1. Haz clic en la pestaña “Certificates & secrets”.

    Click the “Certificates & secrets tab”
  2. Haz clic en “New client secret”.

    Click “New client secret”
  3. Introduce una descripción y una fecha de expiración.

    Enter a description and an expiration date

Después de generarlo, cópialo y guárdalo en un lugar seguro (normalmente en tu archivo .env).

No podrás ver ni copiar el client secret más adelante; asegúrate de copiarlo antes de salir de la página.

Paso 5: Marca y verificación

En la sección Branding & Properties del registro de la app, puedes añadir un logo e información (descripción, URL de términos de servicio, etc.). Es opcional, pero recomendable para una pantalla de consentimiento pulida. Es esencial establecer un dominio de editor (normalmente tu dominio verificado en Azure AD) para evitar que la app aparezca como “sin verificar” al otorgar consentimiento. Para apps multi-tenant, Microsoft requiere que estén publisher-verified para un uso amplio. Si tu app no lo está, los usuarios externos podrían no poder consentirla debido a políticas de seguridad introducidas en noviembre de 2020.

Branding & Properties screen

Paso 6: Familiarízate con la Graph API de Outlook

Después de configurar la aplicación, puedes empezar a explorar la API de Microsoft Calendar Graph para conocer las APIs específicas de creación, actualización y eliminación de eventos.

Paso 7: Considera usar un servicio de API de Calendario Unificado para integrar todos los proveedores con una sola API

Aunque la Microsoft Graph API está bien documentada, recomendamos usar una API de Calendario Unificado que permita integrar todos los proveedores mediante una única API.

Así obtienes la ventaja de implementar una sola API y soportar todos los proveedores, sin preocuparte por sus limitaciones o diferencias.

Otro beneficio es que no necesitas mantener varias APIs, lidiar con cambios incompatibles ni casos límite inesperados.

API Unificada de Calendarios de OneCal

OneCal Unified Calendar API Landing Page

Ejemplo de flujo de autorización de Outlook Calendar

El siguiente diagrama muestra un flujo OAuth sencillo que permite a los usuarios conectar su Outlook Calendar a tu app.

Outlook OAuth 2.0 Flow

Visita la página de documentación del flujo OAuth2 de Microsoft para obtener más información.

Lado cliente (UI)

const microsoftOauthUrl = getMicrosoftOAuthUrl()
<button href="microsoftOauthUrl" rel="noopener noreferrer"> Conectar Outlook Calendar </button>

export const SCOPES = [
 "openid",
 "email",
 "profile",
 "offline_access",
 "Calendars.ReadWrite",
 "User.Read",
];

export interface ClientState {
 session: Session;
returnUrl?: string;
}

export function stateToB64(session: ClientState): string {
 return encode(JSON.stringify(session));
}

export function getMicrosoftOAuthUrl(
state: ClientState,
) {
 const nonce = uuid();
 const TENANT_ID = process.env.NEXT_PUBLIC_MICROSOFT_TENANT_ID;
 const params = new URLSearchParams({
 client_id: process.env.MICROSOFT_CLIENT_ID || "",
 redirect_uri: `${getHostName()}/api/connect/microsoft`,
 response_type: "code id_token",
 scope: SCOPES.join(" "),
 prompt: "consent",
 response_mode: "form_post",
 state: stateToB64(state),
nonce,
});
 return `https://login.microsoftonline.com/${TENANT_ID}/oauth2/v2.0/authorize?${params}`;
}

  • El parámetro “prompt” puede tener cuatro valores: login, none, consent y select_account.

  • El parámetro “response_mode” puede ser query, fragment o form_post. Elegimos form_post para que Microsoft envíe una solicitud POST a nuestra URI de redirección.

Lado servidor (Backend)

A continuación, creamos el handler API, responsable de obtener el código y los ámbitos del servidor de Outlook y canjearlos por tokens.

En este ejemplo usamos zod para la validación.

const successSchema = z.object({
code: z.string(),
state: z.string(),
id_token: z.string(),
session_state: z.string().optional(),
});

const errorSchema = z.object({
error: z.string(),
error_description: z.string().optional(),
});
type ErrorParams = z.infer<typeof errorSchema>;

const querySchema = z.union([successSchema, errorSchema]);

function isError(query: Record<string, any>): query is ErrorParams {
 return Boolean(query.error);
}

const microsoftHandler: NextApiHandler = async (req, res) => {
 try {
 const result = querySchema.parse(req.body);
 if (isError(result)) {
 const q = new URLSearchParams({
error: "ACCESS_DENIED",
provider: CalendarProvider.MICROSOFT,
});

console.error({ result });
 return res.redirect(302, `/?${q}`);
}

 const { session, returnUrl } = stateFromB64(result.state);
 const { email } = decodeIdToken(result.id_token);
 const { access_token, refresh_token, expires_in, scope } =
await exchangeCodeForTokens(result.code);

 const connection = await upsertConnection(
{
email,
 accessToken: access_token,
 refreshToken: refresh_token,
 expiresInSeconds: expires_in,
 status: ConnectionStatus.ACTIVE,
 provider: CalendarProvider.MICROSOFT,
 scopes: scope,
 reminderCount: 0,
 lastRemindedAt: null,
},
session.user
);

 const q = new URLSearchParams({
cid: connection.id,
});
 if (returnUrl) q.append("returnUrl", returnUrl);

res.redirect(302, returnUrl ? returnUrl : `/calendars/microsoft?${q}`);
} catch (e: any) {
let error = JSON.stringify(e);

 const querystr =
typeof req.query === "string" ? req.query : JSON.stringify(req.query);

 const q = new URLSearchParams({
error,
provider: CalendarProvider.MICROSOFT,
});
 return res.redirect(302, `/?${q}`);
}
};

export default microsoftHandler;

Al igual que en el lado cliente, recomendamos tener funciones utilitarias para canjear códigos por tokens, etc.

const TENANT_ID = process.env.MICROSOFT_TENANT_ID;

export async function exchangeCodeForTokens(code: string) {
 const data = new FormData();
data.append("client_id", process.env.MICROSOFT_CLIENT_ID || "");
data.append("scope", SCOPES.join(" "));
data.append("code", code);
data.append("redirect_uri", `${getHostName()}/api/connect/microsoft`);
data.append("grant_type", "authorization_code");
data.append("client_secret", process.env.MICROSOFT_CLIENT_SECRET || "");

 try {
 const result = await fetch(
 `https://login.microsoftonline.com/${TENANT_ID}/oauth2/v2.0/token`,
{
 method: "POST",
 body: data,
}
);

 const json = await result.json();
 if (json.error) throw json;

 const parsed = responseSchema.parse(json);
 return parsed;
} catch (e) {
 console.error("Exchange failed");
 throw e;
}
}

Complicaciones de la integración con la API de Outlook Calendar

  • La verificación puede tardar y ser frustrante: Ten en cuenta que miles de desarrolladores usan Outlook a diario, por lo que el equipo de Microsoft procesa miles de envíos. Completa todos los detalles al enviar tu app y contempla el proceso de verificación en tu hoja de ruta.

  • Solicita solo los ámbitos necesarios: El equipo de Microsoft revisa minuciosamente; pedir solo lo indispensable facilita la aprobación y reduce la confusión de los usuarios al otorgar permisos.

  • Los webhooks caducan; renuévalos: Si registras webhooks para cambios en el calendario, configura un job en segundo plano que los renueve cada pocas horas.

  • Limitación y throttling: Microsoft impone reglas estrictas. Evita peticiones individuales y aplica limitación en tus llamadas para no recibir errores “MailboxConcurrency”.

    • Por buzón (par app ID & buzón): 10 000 solicitudes / 10 min y 4 solicitudes concurrentes.

    • Carga: 150 MB totales PATCH/POST/PUT por 5 min por buzón.

    • Graph global: 130 000 solicitudes / 10 s por app en todos los tenants.

    • Etiqueta de reintento: ante 429 o 503/504, revisa Retry-After y aplica backoff exponencial.

  • Problemas de zona horaria: En Outlook, un usuario puede escribir manualmente su zona horaria; maneja este caso.

  • Problemas de consentimiento y permisos: Calendars.ReadWrite es delegado, pero algunos tenants requieren consentimiento de administrador. Prepárate para un error “admin consent required” y muestra un flujo “Pide ayuda a tu administrador”.

Integra todos los proveedores de calendario con la API Unificada de OneCal

Las integraciones de calendario son nuestra especialidad. Desde 2022 sincronizamos miles de millones de eventos entre los principales proveedores, y nuestros enlaces de programación los usan miles de profesionales en todo el mundo.

Las lecciones aprendidas al trabajar con todas las APIs de calendario impulsaron la creación de la API Unificada de OneCal, evitando que nuestros usuarios dediquen cientos de horas a problemas de calendario y permitiéndoles centrarse en funciones que impulsen su producto y crecimiento.

Únete a la lista de espera de nuestra API Unificada para recibir notificaciones en cuanto lancemos el producto y aprovechar precios y descuentos de lanzamiento.