Skip to main content

Google Calendar ExecModule

Overview

GoogleCalendarModule connects ValkyrAI workflows to Google Calendar API v3 through the native map I/O ExecModule ABI. Workflow Studio discovers it as GoogleCalendarModule; its OAuth access token resolves only from an encrypted IntegrationAccount.

The initial production operation set covers calendar discovery, bounded event reads, availability, and governed event mutations:

  • list_calendars and get_calendar
  • list_events, get_event, and list_instances
  • free_busy
  • create_event, update_event, quick_add_event, and delete_event

List operations follow only Google-provided opaque page tokens and never accept provider URLs. Read-only requests and free/busy queries can retry transient failures. Event creates, patches, quick-adds, and deletes run once so ambiguous timeouts cannot duplicate, reschedule, notify, or remove calendar activity.

Usage

  1. Enable Google Calendar API in a Google Cloud project.
  2. Complete OAuth consent and authorize the narrowest Calendar scopes needed by the selected operations.
  3. Store the current OAuth access token in the encrypted apiKey field of an IntegrationAccount.
  4. Optionally store the default calendar ID in IntegrationAccount.accountId; otherwise the module uses primary.
  5. Set the account status to READY and bind it through ExecModuleConfig.authConfig.integrationAccount.
  6. Use list_calendars or get_calendar to verify the intended calendar before mutations.
  7. For updates, provide an ETag from the latest event read when concurrency protection is required.
  8. Reconcile Google Calendar state before repeating any write after an ambiguous connection failure.

Workflow input cannot provide OAuth credentials or an arbitrary endpoint. Production routing is fixed to www.googleapis.com over HTTPS.

Inputs

NameTypeRequirementDefaultDescription and constraints
operationstringRequiredNoneOne of the 10 documented operations.
calendarIdstringCalendar/event operationsIntegrationAccount.accountId or primaryGoogle Calendar ID, maximum 1,024 characters.
eventIdstringEvent get/update/delete/instancesNoneOpaque Google event ID using letters, digits, underscore, or hyphen.
eventobject or JSON stringEvent create/updateNoneAllowlisted event fields, 512 KiB maximum, nesting limited to eight levels.
quickAddTextstringquick_add_eventNoneNatural-language event description, 1–4,096 characters.
timeMin / timeMaxRFC3339 stringfree_busy; optional list boundNoneOffset-bearing timestamps; timeMax must be later than timeMin.
calendarIdsstring arrayOptional free_busycalendarIdOne through 50 calendar or group IDs.
timeZonestringOptionalProvider defaultValid IANA time-zone ID.
querystringOptional list_eventsNoneFree-text event search, maximum 1,024 characters.
pageTokenstringOptional list continuationNoneOpaque Google continuation token, maximum 4,096 characters.
limitintegerOptional100Maximum emitted resources, 1–10,000.
returnAllbooleanOptionalfalseContinue provider pages until exhaustion or the result cap.
sendUpdatesstringEvent mutationsnonenone, all, or externalOnly.
etagstringOptional update/deleteNoneIf-Match value from a current event read.
confirmDeletebooleandelete_eventfalseMust be true before a delete request is sent.

Event payloads accept only id, summary, description, location, start, end, attendees, recurrence, reminders, visibility, transparency, colorId, guestsCanInviteOthers, guestsCanModify, guestsCanSeeOtherGuests, extendedProperties, source, and attachments.

Timed events require both start.dateTime and end.dateTime as offset-bearing RFC3339 timestamps. All-day events require both start.date and end.date in YYYY-MM-DD form. Attendee email addresses, recurrence lines, array sizes, text lengths, and nested fields are validated before the provider request.

Outputs

NameTypeWhen presentDescription
statusstringAlwayssuccess or error.
operationstringAlwaysNormalized operation name.
resourceStatusstringProvider returns statusGoogle Calendar resource status, such as confirmed or cancelled.
attemptsintegerAlwaysProvider attempts across all pages.
httpStatusintegerProvider respondedLast Google Calendar HTTP status.
dataobjectSingle-resource/write/free-busy successCalendar, event, deletion receipt, or free/busy response.
id / htmlLinkstringProvider returns fieldSafe convenience event identity and browser link.
items / countarray / integerList successBounded resources and emitted count.
hasMorebooleanList successWhether another provider page exists.
nextPageTokenstringAnother page existsOpaque continuation token.
errorobjectFailureSafe code, message, optional HTTP status, and retryable flag.

OAuth tokens and authorization headers never enter outputs. Provider error text passes through ValkyrAI's sensitive-data redaction policy.

IntegrationAccount Requirements

SettingRequirement
ProviderGoogle OAuth 2.0 application with Calendar API enabled
Read scopescalendar.calendarlist.readonly, calendars.readonly, and events.readonly as needed
Availability scopecalendar.freebusy or calendar.events.freebusy
Write scopecalendar.events, calendar.events.owned, or calendar when broader calendar management is intentionally required
accountIdOptional default calendar ID; primary is used when absent
apiKeyCurrent OAuth access token in an encrypted SecureField
passwordLegacy encrypted token fallback only; prefer apiKey
statusREADY or legacy unset status; CLOSED and ERROR fail closed

OAuth authorization-code exchange, refresh-token storage, access-token refresh, revocation, and rotation belong to the platform IntegrationAccount lifecycle. Workflow inputs never handle OAuth secrets.

Configuration

{
"version": "1.0.0",
"authConfig": {
"authStrategy": 1,
"integrationAccount": "integration-account:google-calendar-operations"
},
"retryPolicy": {
"maxAttempts": 3,
"backoffStrategy": "EXPONENTIAL",
"initialDelayMs": 1000,
"maxDelayMs": 60000,
"jitter": false
},
"executionConfig": {"timeoutMs": 30000},
"payloadConfig": {
"parameters": "{\"operation\":\"list_events\",\"calendarId\":\"primary\",\"limit\":100}"
}
}

The integration-account value is symbolic. Persisted workflows use the generated relationship rather than a plaintext token or calendar identifier.

Operations

OperationGoogle Calendar behaviorSide effect
list_calendarsLists calendars subscribed by the authenticated user.Read-only; safe retries and bounded pagination.
get_calendarReads one calendar's metadata.Read-only; safe retries.
list_eventsLists expanded events ordered by start time with optional time/search filters.Read-only; safe retries and bounded pagination.
get_eventReads one event by ID.Read-only; safe retries.
list_instancesLists instances of one recurring event.Read-only; safe retries and bounded pagination.
free_busyQueries busy windows for one through 50 calendars or groups.Read-only POST; safe retries.
create_eventInserts one allowlisted timed or all-day event.Creates an event and may notify guests; single attempt.
update_eventApplies a partial event patch and optional If-Match guard.Mutates an event and may notify guests; single attempt.
quick_add_eventCreates one event from bounded natural-language text.Creates an event and may notify guests; single attempt.
delete_eventDeletes one event after explicit confirmation.Destructive and potentially notifying; single attempt.

Errors and Failure Modes

CodeTypical causeRetryableResolution
VALIDATION_ERRORMissing/invalid ID, time, time zone, event, attendee, recurrence, deletion guard, or bound.NoCorrect input; no unsafe request was sent.
UNSUPPORTED_OPERATIONUnknown operation.NoSelect a documented operation.
INTEGRATION_ACCOUNT_REQUIREDNo bound account.NoBind a Google Calendar IntegrationAccount.
INTEGRATION_ACCOUNT_NOT_READYAccount is closed or in error.NoRepair or reconnect the account.
CREDENTIAL_MISSINGBound account has no decryptable access token.NoRefresh or re-authorize the IntegrationAccount.
GOOGLE_CALENDAR_HTTP_400Google rejected a field, time, recurrence, or request combination.NoCorrect the safe validation detail.
GOOGLE_CALENDAR_HTTP_401 / 403Token expired, scope missing, or calendar access denied.NoRe-authorize with the narrow required scopes.
GOOGLE_CALENDAR_HTTP_404Calendar or event is absent or invisible.NoRe-read/list using the same account.
GOOGLE_CALENDAR_HTTP_409 / 412Event ID conflict or stale If-Match ETag.NoRead current state and rebuild the mutation.
GOOGLE_CALENDAR_HTTP_429 / 5xxRate limit or transient provider failure.Yes for readsHonor Retry-After; reconcile writes before repeating them.
NETWORK_ERRORTimeout, DNS, TLS, or connectivity failure.Yes for readsVerify connectivity and provider state.
RESPONSE_TOO_LARGEResponse exceeded 5 MiB.NoLower the limit or narrow the time range.
INVALID_PROVIDER_RESPONSEA list response returned a non-array items field.NoVerify Google API compatibility and request context.

Example

Create one approved customer activation review:

{
"operation": "create_event",
"calendarId": "primary",
"sendUpdates": "all",
"event": {
"summary": "Customer activation review",
"description": "Review onboarding progress and unblock production activation.",
"location": "Google Meet",
"start": {
"dateTime": "2026-08-10T10:00:00-07:00",
"timeZone": "America/Los_Angeles"
},
"end": {
"dateTime": "2026-08-10T10:30:00-07:00",
"timeZone": "America/Los_Angeles"
},
"attendees": [
{"email": "customer@example.com"}
]
}
}

Expected result:

{
"status": "success",
"operation": "create_event",
"attempts": 1,
"httpStatus": 200,
"id": "event123",
"data": {
"id": "event123",
"status": "confirmed"
}
}

Notes

  • Pagination: calendar lists use pages of at most 250 and event lists use pages of at most 2,500. Total output is capped at 10,000. Only opaque nextPageToken values from Google are followed.
  • Rate limits: GET requests and free/busy queries retry HTTP 408, 429, 500, 502, 503, and 504 according to RetryPolicy, including numeric or HTTP-date Retry-After values. Mutations never retry automatically.
  • API limits: request bodies are capped at 512 KiB, responses at 5 MiB, free/busy calendars at 50, attendees at 200, recurrence lines at 50, and event arrays at 1,000.
  • Idempotency: create, update, quick-add, and delete are single-attempt. A caller-supplied Google-compatible event id can provide create correlation; otherwise reconcile by ID, time range, and summary before retrying an ambiguous write.
  • Concurrency: update_event and delete_event can send If-Match from the latest event ETag. Google partial patch requests consume more quota than update requests, so reserve patches for bounded changes.
  • Destructive behavior: only delete_event is destructive and requires confirmDelete=true. Guest notifications are controlled explicitly by sendUpdates.
  • API behavior: recurring events, all-day boundaries, organizer permissions, Workspace policies, attachments, reminders, guest delivery, and calendar ACLs can impose provider-side rules beyond local structural validation.
  • Security: credentials remain in IntegrationAccount SecureFields. Fixed-host routing, bounded identifiers, allowlisted event fields, forbidden credential-like nested keys, capped payloads/responses, and redacted provider messages prevent arbitrary routing and secret reflection.
  • External verification: request construction, pagination, validation, ETag handling, retry safety, redaction, response mapping, and metadata discovery have deterministic local tests. Live OAuth consent, refresh, calendar policies, guest email delivery, quotas, Meet conference creation, and calendar mutations require separately authorized Google credentials and are not exercised in repository tests.
  • Deferred operations: calendar create/update/delete, ACL management, settings, colors, watch channels/triggers, event import/move, batch endpoints, Meet conference generation, attachments requiring Drive scopes, OAuth refresh, and arbitrary API calls.
  • Functional references: n8n Google Calendar node source, Google Calendar Events API, Google Freebusy query, and Google Calendar OAuth scopes.