Connect Google Calendar and manage appointments through the API
Google Calendar has its own platform and connection, without Gmail permissions. Your assistant uses a Pulbot API key to generate a link; the user grants permissions in Google. Implemented locally on November 2, 2026: Google Cloud configuration, deployment, catalog seeding and real authorization still need verification.
Steps
- 1Call GET /api/v1/core/platforms/?search=Google and select Google Calendar. Do not use Google Workspace (Gmail) or Google (Gemini).
- 2Send POST /api/v1/resource-connectors/oauth2/start/ with X-API-Key and body {"platform_id":"<calendar_platform_id>"}. Give data.authorize_url to the user; expires_in is its validity, currently 600 seconds.
- 3The user selects an account and permissions in Google. The callback creates a Google Calendar resource for the user and organization that generated the link. A Gmail connection does not automatically gain Calendar access.
- 4Call GET /api/v1/resource-connectors/ and store the resource ID. Discover actions with GET /api/v1/tools/?category=all&platform=<calendar_platform_id>; inspect their inputs before execution.
- 5First test Listar calendarios and Listar eventos. Execute through POST /api/v1/tools/<tool_id>/execute/ with resource_connection_id and the inputs. This is a Pulbot simulation endpoint, but it can operate on real Google data.
Reference
- Pulbot permissions
- tool:write to generate the link and flow:simulate to execute tools; organization capabilities are evaluated separately. MCP is optional: start_connector_oauth2 works with the Calendar ID after deployment.
- calendar.calendarlist.readonly
- Requested by default to list calendars.
- calendar.events.readonly
- Requested by default to read events. Requested does not mean granted: Pulbot records the scope returned by Google.
- calendar.events
- Optional to create, modify and delete events. Overlaps read access; the user may grant management or read-only access through Google consent.
- calendar.events.freebusy
- Optional to query busy intervals. A separate permission because calendar.events.readonly and calendar.events do not automatically authorize the freeBusy endpoint.
- scopes_extra
- Omitted/null: presents all four configured scopes in Google. []: requests only the two default scopes. It requests neither full calendar access nor Gmail permissions. Google controls grouping and prior authorizations.
- Tools available in source
- Google Calendar - Listar calendarios; Listar eventos; Obtener evento; Consultar disponibilidad; Crear evento; Modificar evento; Eliminar evento. Full names use the Google Calendar - prefix; retrieve IDs from the catalog rather than hardcoding them.
- Calendar and pagination
- calendar_id defaults to primary. For another calendar use its ID, URL-encoding reserved characters. Calendar and event lists preserve nextPageToken; pass it as pageToken. Empty optional fields are omitted from the query.
- Example: list events
- {"resource_connection_id":"<connector_id>","calendar_id":"primary","timeMin":"2026-11-03T00:00:00-04:00","timeMax":"2026-11-04T00:00:00-04:00","timeZone":"America/Caracas","singleEvents":true,"orderBy":"startTime"}
- Example: availability
- {"resource_connection_id":"<connector_id>","time_min":"2026-11-03T13:00:00Z","time_max":"2026-11-03T18:00:00Z","time_zone":"America/Caracas","calendars":[{"id":"primary"}]}
- Example: create appointment
- {"resource_connection_id":"<connector_id>","calendar_id":"primary","sendUpdates":"none","event":{"id":"appt20261103001","summary":"Cita de prueba","start":{"dateTime":"2026-11-03T09:00:00-04:00","timeZone":"America/Caracas"},"end":{"dateTime":"2026-11-03T09:30:00-04:00","timeZone":"America/Caracas"}}}
- Dates and timezone
- Use RFC3339 dateTime with an offset and an IANA timeZone. For all-day events use start.date and end.date; the end is exclusive. For recurring events specify timezone and recurrence in event. Pulbot forwards the object; Google validates consistency and permissions.
- Update and delete
- Modificar evento takes calendar_id, event_id and changes (a partial object). Supplied arrays replace their entire contents. You can send If-Match with the retrieved etag. Eliminar evento takes calendar_id and event_id; status_code 204 without JSON means success.
- Guests and notifications
- event.attendees specifies guests. sendUpdates accepts none (default), all or externalOnly. all can send real invitations and updates; none does not guarantee that Google sends no email. Do not add guests in tests without authorization.
- Retries and idempotency
- Include a stable event.id per operation: 5–1024 base32hex characters (a–v, 0–9). After a timeout retrieve that ID before retrying; on 409 reconcile the existing event. No Pulbot idempotency header or local event-content validation was added.
- Operator configuration
- Enable Calendar API in Google Cloud and configure consent for these scopes. The backend reuses GOOGLE_WORKSPACE_CLIENT_ID and GOOGLE_WORKSPACE_CLIENT_SECRET, not the Google Sign-In client. Calendar does not query the Gmail profile. Redirect URIs must match the environment.
- Validation status
- All seven actions were tested through the real HTTP interpreter with mocked responses: filters, pagination, structured bodies, timezones, 403, 204, etags and token refresh. Real Google consent, deployment and operations on the user’s account remain pending.
Common errors
- 403
- May indicate denied scopes or insufficient calendar access. freeBusy also needs its specific permission.
- 409 / 412
- 409 on creation: retrieve event.id and reconcile. 412: the etag changed; read again before updating or deleting.
- Availability
- HTTP 200 may include calendars.<id>.errors. Check each calendar’s errors before offering a slot. Querying availability does not reserve the appointment or prevent races.
- 401 / invalid_state
- Check Pulbot credentials, token refresh or link validity. Generate another link if state expired or was consumed.
Next step
Continue with API → Integrate an assistant to combine Calendar, Gmail and WhatsApp. Do not announce production readiness before checking the real flow with test accounts.