Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/shadownrx/apisquare/llms.txt

Use this file to discover all available pages before exploring further.

The Google Calendar integration is entirely optional, but when enabled it allows ApiSquare to cross-check a time slot against an existing Google Calendar before confirming a booking, and to create a calendar event automatically once a reservation is saved. It relies on the googleapis package (version ^144.0.0) and supports two authentication methods: a service account JSON key (recommended for production) or an OAuth2 refresh token generated by the included helper script.

Prerequisites

Before configuring either authentication method, make sure you have the following in place:
  • A Google Cloud project with the Calendar API enabled.
  • Either a service account with its JSON key downloaded, or OAuth2 credentials (client ID + client secret) created in the Google Cloud Console.
  • The service account’s email address (e.g. my-bot@my-project.iam.gserviceaccount.com) added as an editor under the “Share with specific people” settings of the Google Calendar you want ApiSquare to manage.
  • The Calendar ID of that calendar — found in Google Calendar under Settings → Settings for my calendars → Integrate calendar.
A service account authenticates as a non-human identity and never requires user interaction, making it the most reliable option for a deployed bot. Set the following environment variables (in Vercel’s dashboard or in .env.local):
GOOGLE_SERVICE_ACCOUNT_KEY='{"type":"service_account","project_id":"...","private_key_id":"...","private_key":"-----BEGIN RSA PRIVATE KEY-----\n...","client_email":"...@....iam.gserviceaccount.com",...}'
GOOGLE_CALENDAR_ID=your_calendar_id@group.calendar.google.com
ApiSquare’s getCalendarClient() function in lib/googleCalendar.ts reads GOOGLE_SERVICE_ACCOUNT_KEY, parses the JSON, and creates a JWT auth client scoped to the Calendar API:
import { google } from 'googleapis';

export const getCalendarClient = async () => {
  const serviceAccountKey = JSON.parse(process.env.GOOGLE_SERVICE_ACCOUNT_KEY || '{}');

  const auth = new google.auth.JWT(
    serviceAccountKey.client_email,
    undefined,
    serviceAccountKey.private_key,
    ['https://www.googleapis.com/auth/calendar'],
    undefined
  );

  await auth.authorize();
  return google.calendar({ version: 'v3', auth });
};
Store the service account JSON key as a single-line string in your environment variable. The PEM private key inside the JSON contains literal newlines — these must be escaped as \n so the entire value fits on one line. Most secret managers and the Vercel dashboard handle this automatically if you paste the raw JSON; double-check by running JSON.parse(process.env.GOOGLE_SERVICE_ACCOUNT_KEY) locally before deploying.

Method 2: OAuth2 refresh token (helper script)

If you prefer to authenticate as a Google user account rather than a service account, ApiSquare ships a helper script that walks you through the OAuth2 consent flow and prints a ready-to-use GOOGLE_REFRESH_TOKEN. Run the script from the project root:
node scripts/get-google-refresh-token.js
The script will:
1

Print an authorization URL

Copy the URL printed to the console and open it in your browser. It uses the OAuth2 client configured in the script to request https://www.googleapis.com/auth/calendar access with access_type: 'offline' and prompt: 'consent' so a refresh token is always issued.
2

Authorize the application

Sign in with the Google account that owns the calendar, grant the requested permissions, and you will be redirected to http://localhost:3000. The redirect URL will contain a code= query parameter — copy that value.
3

Paste the authorization code

Return to the terminal and paste the code when prompted. The script exchanges it for tokens and prints:
GOOGLE_REFRESH_TOKEN=1//0gXXXXXXXXXXXXXXXXX
4

Add the token to your environment

Copy the printed value into your .env.local or Vercel environment variables:
GOOGLE_REFRESH_TOKEN=1//0gXXXXXXXXXXXXXXXXX
GOOGLE_CALENDAR_ID=your_calendar_id@group.calendar.google.com

Available functions

All calendar functions are exported from lib/googleCalendar.ts. There are three:

getCalendarClient()

Returns an authenticated Google Calendar API v3 client. Called internally by the other two functions — you generally do not need to call it directly.
export const getCalendarClient = async ()

verificarDisponibilidadCalendar(fechaStr, horaStr)

Checks whether a 1-hour window starting at horaStr on fechaStr is free on the linked calendar. It calls calendar.events.list with timeMin / timeMax set to the start and end of that window and returns disponible: false if any event overlaps.
// Check availability for a 1-hour window
export const verificarDisponibilidadCalendar = async (
  fechaStr: string,  // 'YYYY-MM-DD'
  horaStr: string    // 'HH:MM'
)
Example:
import { verificarDisponibilidadCalendar } from '@/lib/googleCalendar';

const result = await verificarDisponibilidadCalendar('2025-08-15', '11:00');
// { disponible: true }
// or
// { disponible: false, mensaje: 'Lo siento, ese horario ya está ocupado en Google Calendar.' }

crearEventoCalendar(datosReserva)

Creates a calendar event for a confirmed booking. The event summary is formatted as "{service} - {name}" and the timezone is set to America/Argentina/Buenos_Aires. The event lasts 1 hour from the given start time.
// Create a calendar event for a confirmed booking
// datosReserva must include: servicio, nombre, fecha ('YYYY-MM-DD'), hora ('HH:MM')
export const crearEventoCalendar = async (datosReserva: any)
Example:
import { crearEventoCalendar } from '@/lib/googleCalendar';

const result = await crearEventoCalendar({
  servicio: 'Sesión de Quiropraxia',
  nombre: 'María García',
  fecha: '2025-08-15',
  hora: '11:00',
});
// { success: true, eventId: 'abc123xyz...' }
The returned eventId is the Google Calendar event ID. You can store it alongside the reservation if you need to update or delete the event later.

Wiring the integration into the booking flow

The Google Calendar integration is not wired into the main booking flow by default. The functions in lib/googleCalendar.ts exist and work independently, but the webhook handler in app/api/webhook/route.ts does not call them automatically. To enable calendar sync, import verificarDisponibilidadCalendar and call it before confirming a slot, then call crearEventoCalendar inside the confirmar_reserva branch after guardarReserva succeeds.
Here is the pattern to follow in app/api/webhook/route.ts:
import {
  verificarDisponibilidadCalendar,
  crearEventoCalendar,
} from '@/lib/googleCalendar';

// Inside the 'confirmar_reserva' callback branch, after guardarReserva succeeds:
if (reserva) {
  // Optionally create a Google Calendar event
  await crearEventoCalendar({
    servicio: reserva.servicio,
    nombre: reserva.nombre,
    fecha: reserva.fecha,
    hora: reserva.hora,
  });

  await clearState();
  // ... send confirmation message to user
}
And to check Google Calendar availability before showing a slot as bookable, call verificarDisponibilidadCalendar alongside the existing verificarDisponibilidad check:
const gcalCheck = await verificarDisponibilidadCalendar(estado.fecha!, horaSeleccionada);
if (!gcalCheck.disponible) {
  // Slot is occupied in Google Calendar — show updated schedule
}

Build docs developers (and LLMs) love