Cómo integrar la API de Google Calendar en tu aplicación

Autores
Publicado el

Integra todos los calendarios usando una única API

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

Regístrate GratisNo se requiere tarjeta de crédito!

En esta guía, explicaremos detalladamente cómo integrar la API de Google Calendar en tu aplicación, abarcando la configuración del proyecto de Google Cloud, los alcances requeridos, los inconvenientes y un ejemplo real de autorización.

Requisitos previos

Esta guía asume que dispones de una dirección de correo electrónico, un dominio ya listo para usar al crear el proyecto de Google Cloud, ciertos conocimientos de programación y una idea bastante clara de lo que quieres construir.

También resulta útil si nunca has trabajado con la API de Google Calendar y deseas familiarizarte con todos los pasos necesarios para integrarla en tu aplicación.

Cómo utilizar e integrar la API de Google Calendar en tu aplicación

1. Regístrate en Google Developer Console

Si todavía no tienes una cuenta en Google Developer Console, créala en https://console.cloud.google.com/.

2. Crea o selecciona un proyecto de Google Cloud existente

Google Cloud permite a desarrolladores y organizaciones tener varios proyectos. Asegúrate de estar en el proyecto correcto antes de realizar las siguientes operaciones.

Haz clic en el desplegable de proyectos en la parte superior izquierda de la pantalla. El nombre suele coincidir con el de tu proyecto.

Google Cloud Home

Selecciona un proyecto existente o crea uno nuevo haciendo clic en «New Project» en la parte superior derecha del modal.

Google Cloud - Select Project

3. Habilita los servicios de la API de Google Calendar

Una vez creado el proyecto y verificado que estás en el correcto, sigue estos pasos para habilitar la API de Google Calendar:

  1. Haz clic en «APIs & Services»

    Google Cloud - Click APIs and Services

  2. Haz clic en «Enable APIs and services»

    Google Cloud - Enable APIs and services
  3. Busca «Google Calendar API»

    Search for Google Calendar API service
  4. Haz clic en «Enable» para activar el servicio.

    Enable Google Calendar API service

4. Configura la pantalla de consentimiento OAuth

Tras habilitar la API, el siguiente paso es configurar la pantalla de consentimiento OAuth. Esta es la interfaz que verán los usuarios al conectar su calendario con tu aplicación: normalmente incluye el logotipo, el nombre de la app, los permisos solicitados, etc.

  1. Haz clic en la pestaña «OAuth Consent Screen».

    Click OAuth Consent Screen
  2. Haz clic en «Get Started».

    Click Get Started
  3. Rellena la sección «App Information». Introduce el nombre de la app y el correo de soporte.

    Fill in the “App Information” section
  4. Elige la audiencia. Puede ser interna o externa. Elige interna si la app no será pública y solo usuarios de tu organización podrán conectar sus calendarios. Elige externa si cualquier cuenta pública podrá iniciar sesión.

    Choose the audience
  5. Introduce tu información de contacto. Google requiere un correo para notificar cambios en el proyecto.

    Fill in your contact information.webp
  6. Marca la casilla «Agree to the Google API Services: User Data Policy».

    Check the Agree to the Google API Services
  7. Haz clic en «Create».

    Click “Create”

5. Crea tu cliente OAuth

Tras configurar la pantalla de consentimiento, puedes crear el cliente OAuth del proyecto. Haz clic en la pestaña «Clients» y luego en «Create Client».

También puedes hacer clic en «Create OAuth Client» en la página de resumen.

Create OAuth Client

Crea clientes para cada plataforma donde se ejecutará tu aplicación. Por ejemplo, si desarrollas una app web y otra para iOS, necesitarás un ID de cliente OAuth distinto para cada plataforma.

Google Cloud - Client Options

En este ejemplo crearemos un cliente «Web Application» y lo llamaremos «Web Client».

Google Cloud - Web Client

En este flujo también debemos configurar los orígenes JavaScript autorizados y las URI de redirección autorizadas.

En Authorized JavaScript origins, indica el dominio/URL que aloja tu app web, por ejemplo: myapp.domain.com

Google Cloud - Authorized Domains

En Authorized redirect URLs, introduce todas las URL a las que redirigirás a los usuarios tras autenticarse. La URL se completará con el código de autorización y debe incluir protocolo.

Google Cloud - Setup Redirect URL

Asegúrate de incluir también tus URL de redirección a localhost si usas la app en desarrollo. En este ejemplo incluiremos la redirección a localhost.

Tras completar los campos, haz clic en «Create». Google mostrará un modal con el Client ID y el Client Secret. Copia estos datos y guárdalos en un lugar seguro (normalmente en tu archivo .env, pues los usarás en el flujo de autenticación). También puedes descargar el JSON y guardarlo en un gestor de secretos como 1Password.

OAuth Client Created - Modal

Descarga el archivo JSON con el Client Secret o cópialo y guárdalo de forma segura: cuando cierres el modal, ya no podrás copiar el Client Secret.

6. Añade usuarios de prueba

Mientras desarrollas la aplicación localmente, no podrás conectar ninguna cuenta de Google Calendar a menos que incluyas usuarios de prueba. Esto se debe a que la app es externa y aún no está aprobada por Google.

Para añadir usuarios de prueba:

  1. Haz clic en la pestaña «Audience».

    Google Cloud - Audience Tab
  2. Desplázate hasta la sección «Test Users».

    Test Users Section
  3. Haz clic en «Add Users» y escribe el correo del usuario.

    Add Test users by email

7. Añade los alcances de calendario que vayas a usar

Según la funcionalidad que ofrezca tu app, quizá necesites solicitar distintos alcances (scopes) al usuario al autorizar su cuenta de Google Calendar.

Piensa en los alcances como permisos para acceder a datos privados de la cuenta de Google: listar calendarios, ver eventos, etc.

Google clasifica los alcances en sensibles y no sensibles. Si añades alcances sensibles, tendrás que enviar la app para verificación. Esto también aplica si tu app ya está verificada y añades nuevos alcances sensibles.

Tras añadir todos los alcances necesarios, incluye una justificación y un video de demostración para cada uno antes de enviar la app a verificación.

Para gestionar los alcances:

  1. Haz clic en la pestaña «Data Access».

    Data Access Tab
  2. Haz clic en «Add or remove scopes».

    Add Or Remove Scopes Button
  3. Busca el alcance por nombre o valor y agrégalo.

    Select Scopes Section

8. Familiarízate con la API de Google Calendar

Tras configurar el cliente y la pantalla de consentimiento, conviene explorar la página de descripción general de la API de Google Calendar y revisar los endpoints clave, como los de eventos y calendarios.

9. Usa un API de calendario unificado para integrar varios proveedores

Si solo necesitas Google Calendar, puedes saltar este paso. De lo contrario, te recomendamos usar una API de calendario unificada, que ofrezca un solo API para todos los proveedores.

Con un único API integrarás fácilmente Outlook en el futuro sin escribir código nuevo, evitarás mantener varias integraciones y no tendrás que aprender los entresijos de cada API.

Ejemplo de flujo de autorización en Google Calendar

El diagrama muestra un flujo OAuth sencillo que permite a los usuarios conectar Google Calendar con tu aplicación.

Google Calendar OAuth flow

Google ofrece clientes para Node.js, Python, etc., pero por simplicidad usaremos llamadas HTTP y TypeScript.

Lado cliente (UI)

Primero, el lado cliente renderiza un botón «Connect Google Calendar».

const googleOauthUrl = getGoogleOAuthUrl()
<button href="googleOauthUrl" rel="noopener noreferrer"> Connect Google Calendar </button>

Recomendamos usar una función utilitaria para obtener la URL OAuth, mejorar la legibilidad y añadir parámetros (estado, forzar permisos, etc.).

const SCOPES = [
 "openid",
 "email",
 "https://www.googleapis.com/auth/calendar.calendarlist",
 "https://www.googleapis.com/auth/calendar.events",
 "https://www.googleapis.com/auth/calendar.readonly",
 // añade más scopes si los necesitas
];

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

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

export function getGoogleOAuthUrl(
state: ClientState,
) {
 const params = new URLSearchParams({
 client_id: process.env.GOOGLE_CLIENT_ID || "",
 redirect_uri: `${getHostName()}/api/connect/google`, // cambia la URL si es necesario response_type: "code",
 scope: SCOPES.join(" "),
 prompt: "consent",
 access_type: "offline",
 state: stateToB64(state),
});
 return `https://accounts.google.com/o/oauth2/v2/auth?${params}`;
}

El parámetro prompt admite tres valores: none, consent y select_account.

  • consent: muestra el modal de permisos aunque el usuario ya haya autorizado, útil si añades más scopes.

  • select_account: obliga al usuario a seleccionar una cuenta.

  • none: no muestra pantallas de autenticación ni consentimiento.

Lado API (backend)

Ahora creamos el manejador que recibe el código y los scopes y los intercambia por tokens.

import { z } from "zod";
const successSchema = z.object({
code: z.string(),
scope: z.string(),
state: z.string(),
});

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

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

// Handler const googleHanlder: NextApiHandler = async (req, res) => {
 try {
 const result = querySchema.parse(req.query);
 if (isError(result)) {
 const q = new URLSearchParams({
error: "ACCESS_DENIED",
});
 return res.redirect(`/?${q}`);
}

 const { session, returnUr } = stateFromB64(
result.state
);

 if (!hasRequiredScopes(result.scope)) {
 const q = new URLSearchParams({
error: "MISSING_REQUIRED_PERMISSIONS",
});
 return res.redirect(`/?${q}`);
}

 const { access_token, refresh_token, id_token, expires_in } =
await exchangeCodeForTokens(result.code);
 const { email } = decodeIdToken(id_token);

 // Actualiza o inserta la conexión de calendario según tu caso const connection = await upsertConnection(
{
email,
 accessToken: access_token,
 refreshToken: refresh_token,
 expiresInSeconds: expires_in,
 status: ConnectionStatus.ACTIVE,
 provider: CalendarProvider.GOOGLE,
 scopes: result.scope,
 reminderCount: 0,
 lastRemindedAt: null,
},
session.user
);

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

 // Redirige de vuelta al cliente con la conexión o errores
res.redirect(
returnUrl ? returnUrl : `/calendars/google?${q}`
);
} catch (e: any) {
let error = JSON.stringify(e);

 const querystr =
typeof req.query === "string" ? req.query : JSON.stringify(req.query);
console.error("Error en googleHandler", querystr);
console.error("No se pudo conectar la cuenta de Google", e);

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

También conviene tener funciones utilitarias para intercambiar el código por tokens, decodificar el ID token, obtener el estado en base 64, etc.

export async function exchangeCodeForTokens(code: string) {
 const data = new FormData();
data.append("code", code);
data.append("client_id", process.env.GOOGLE_CLIENT_ID || "");
data.append("client_secret", process.env.GOOGLE_CLIENT_SECRET || "");
data.append("redirect_uri", `${getHostName()}/api/connect/google`); // tu URL
data.append("grant_type", "authorization_code");

 try {
 const result = await fetch("https://oauth2.googleapis.com/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("Intercambio fallido");
 throw e;
}
}

export function decodeIdToken(idToken: string) {
 const data = jwt.decode(idToken);
 if (typeof data === "string" || !data?.email) {
 throw new Error(`No se pudo analizar id_token: ${idToken}`);
}

 return data;
}

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

export function stateFromB64(encoded: string): ClientState {
 const str = decode(encoded);

 return JSON.parse(str) as ClientState;
}

Las variables de entorno GOOGLE_CLIENT_ID y GOOGLE_CLIENT_SECRET usadas arriba corresponden al Client ID y Client Secret creados en el Paso 5. Asegúrate de copiarlos; tras cerrar el modal ya no podrás ver el Client Secret.

Inconvenientes al integrar la API de Google Calendar

  • La verificación puede tardar semanas. Planifica este retraso antes del lanzamiento, pues es común que Google rechace la app en la primera revisión.

  • Los webhooks caducan tras ~24 h; renuévalos siempre. Usa cron jobs para detectar webhooks que venzan en los próximos 20 min y renuévalos.

  • Solicita solo los scopes necesarios. Google es exhaustivo y los usuarios desconfían si pides permisos excesivos.

  • Gestiona cuotas y rate limits. Google impone límites por minuto y responderá con 403 o 429; aplica backoff exponencial.

  • Evita registrar datos personales. Elimina descripciones, correos de asistentes y demás información sensible al hacer logging.

Integra varios proveedores de calendario con la OneCal Unified Calendar API

En OneCal hemos sincronizado millones de eventos entre Google Calendar, Outlook e iCloud. Sabemos lo que implica integrar varios proveedores, conocer los detalles de cada API y lograr que todo funcione sin fisuras.

Por ello estamos desarrollando una Unified Calendar API que admite Outlook, Google Calendar e iCloud de forma nativa, permitiéndote integrar los principales proveedores mediante un único API robusto y fácil de usar.

Únete a la lista de espera de la Unified Calendar API para que te avisemos en cuanto lancemos el nuevo producto.