Skip to content
Docs
Calendars & meetings

Google Calendar

Let hires read your calendar, find times when everyone is free, book and move meetings, and answer invitations in Google Calendar.

Explore 9 actions and their permissionsExact inputs, sign-in scopes, access limits and approval rules.

With Google Calendar, a hire can:

  • list your calendars and what's on them, and read an event with who's coming and how they answered,
  • see when people are busy, and suggest times when everyone is free inside working hours,
  • put events on a calendar, with a Google Meet link and invitations if you like,
  • move, rename or cancel events it's allowed to change, and add or remove guests,
  • accept, decline or say maybe to invitations, with a note to the organiser.

It's how a personal-assistant hire keeps someone's diary: "find 45 minutes with Ali next week and send an invite" works end to end.

1. Make an app in Google Cloud

Roster connects as an app you own. If you already made one for Gmail, use the same app: turn on the Calendar API, add the two scopes below, and use its client ID and secret here too.

  1. Open console.cloud.google.com, and create a project (or pick one).
  2. APIs & Services → Library: search for Google Calendar API and click Enable.
  3. APIs & Services → OAuth consent screen: Internal with Google Workspace; with a personal account, External, add yourself as a test user, then Publish app (in testing, Google stops the access after 7 days).
  4. Add the scopes https://www.googleapis.com/auth/calendar.events and https://www.googleapis.com/auth/calendar.readonly.
  5. Credentials → Create credentials → OAuth client ID, type Web application. Under Authorized redirect URIs, add the address Roster shows on the Google Calendar connection. It ends in /api/integrations/google-calendar/oauth/callback.
  6. Copy the Client ID and Client secret.

2. Connect it in Roster

  1. Open Integrations → Tools → Add a tool, search for Google Calendar and choose it.
  2. Paste the OAuth app client ID and OAuth app client secret.
  3. Time zone: the zone hires read and write times in, like Asia/Dubai. Leave it empty to use the calendar's own.
  4. Click Connect, then Connect with Google Calendar on the new connection, sign in with the calendar's account and click Allow.

What Roster asks Google for

PermissionWhy
View and edit events (calendar.events)Read events; book, change, cancel and answer (only hires allowed to)
See your calendars (calendar.readonly)List calendars and see when people are free

3. Give hires access

On the hire's Tools tab, click Give access on Google Calendar:

  • Read only: it can list calendars and events, see who's free and suggest times. It can't book, change, cancel or answer anything.
  • Read and write: it can also book, change and cancel events and answer invitations.
  • Calendars: the calendars it may use, by name or ID; primary is the account's own. Leave it empty for every calendar.
  • Who it may invite: domains of people it may invite, like yourbusiness.com. Leave it empty to let it invite anyone.

Inviting someone outside your team is a promise made in your business's name, so it waits for a person's approval: when a hire books or changes a meeting that invites anyone outside your team's domains, or moves a meeting someone outside is on, nothing is sent. The hire asks in the thread, and when the approver says yes, Roster books exactly that meeting. Meetings among your team go ahead without asking. To change this for a hire, use When it asks first on its Tools tab. To keep a hire to your own team altogether, put your domain in Who it may invite.

Hires write times like 2026-11-10T14:00, in the connection's time zone, and show every time in it too.

Waking a hire when the calendar changes

A hire's responsibility can watch Google Calendar: it's woken when events on its calendars (or the primary one) change, are cancelled, or when a new invitation arrives. Checking costs nothing when nothing changed.

If something goes wrong

  • "Isn't connected yet": press Connect with Google Calendar on the connection.
  • "Can only be read, not changed": the account can see that calendar but not edit it. Share it with Make changes to events in Google Calendar.
  • "Can't see their calendar" when finding a time: that person's calendar doesn't share free/busy with the account. The hire says so and suggests checking with them.
  • It worked for a week, then stopped: the app is External and still in testing. Publish it, then connect again.

Tools and permissions reference

This reference is built from the same definitions Roster uses to connect Google Calendar and give hires access. It updates with each release.

Authentication and requested permissions

The account or app you connect sets the outer limit. Each hire's access can narrow it further. Connecting a tool gives it to no hire until you give access on that hire's Tools tab.

OAuth 2.0

From the OAuth client (Web application) you created in Google Cloud for Roster.

Requested scopes:

  • https://www.googleapis.com/auth/calendar.events
  • https://www.googleapis.com/auth/calendar.readonly

Connection fields

Google Calendar connection fields
FieldWhat to provide
OAuth app client ID
clientId
Optional
From the OAuth client (Web application) you created in Google Cloud for Roster.
OAuth app client secret
clientSecret
Optional · sealed secret
Use the value for your account or connection.
Time zone
timeZone
Optional
The time zone hires read and write times in. Leave empty to use the calendar's own.

Per-hire limits

Read-only hires receive only actions that read. Read-and-write access also allows actions that change things, where the connection itself permits them. An empty resource allowlist usually means everything the connected account can reach; each field below explains its meaning.

Google Calendar per-hire limits
FieldWhat to provide
Calendars
calendars
Optional
Calendars the hire may use, by name or ID; primary is the account's own. Leave empty for every calendar. A watch checks these (or primary).
Who it may invite
inviteDomains
Optional
Domains of people the hire may invite to events, like example.com. Leave empty to let it invite anyone.

Actions

9 actions: 5 only read and 4 change something. A read action may still need approval when your workspace or hire is set to ask. A locked approval requirement always applies.

9 of 9 actions. Open an action for its arguments and full input schema.

list_calendarsRead only

The calendars this hire can use: name, ID, whether it can change them, and their time zone.

Approval: Uses your workspace and hire approval settings.

This action takes no arguments.

Full input schema (JSON)
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {}
}
list_eventsRead only

Events on a calendar between two times (default: the next 7 days), soonest first, recurring ones expanded. Optionally only those matching words.

Approval: Uses your workspace and hire approval settings.

Arguments for list_events
ArgumentTypeDetails
calendarOptionalstringcalendar name or ID; primary is the account's ownDefault: "primary"
fromOptionalstringfrom (default now): 2026-11-10T14:00 in the calendar's time zone, or 2026-11-10 for a day
toOptionalstringuntil (default a week after from): 2026-11-10T14:00 in the calendar's time zone, or 2026-11-10 for a day
queryOptionalstringwords in the title, description, place or attendees
limitOptionalintegerSee input schema below.Default: 25
Full input schema (JSON)
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "calendar": {
      "default": "primary",
      "description": "calendar name or ID; primary is the account's own",
      "type": "string",
      "minLength": 1,
      "maxLength": 300
    },
    "from": {
      "type": "string",
      "minLength": 10,
      "maxLength": 40,
      "description": "from (default now): 2026-11-10T14:00 in the calendar's time zone, or 2026-11-10 for a day"
    },
    "to": {
      "type": "string",
      "minLength": 10,
      "maxLength": 40,
      "description": "until (default a week after from): 2026-11-10T14:00 in the calendar's time zone, or 2026-11-10 for a day"
    },
    "query": {
      "description": "words in the title, description, place or attendees",
      "type": "string",
      "minLength": 1,
      "maxLength": 200
    },
    "limit": {
      "default": 25,
      "type": "integer",
      "minimum": 1,
      "maximum": 100
    }
  }
}
read_eventRead only

Read one event: when, where, the video call, who's invited and how they answered, and its notes.

Approval: Uses your workspace and hire approval settings.

Arguments for read_event
ArgumentTypeDetails
calendarOptionalstringcalendar name or ID; primary is the account's ownDefault: "primary"
idRequiredstringthe event's id, from list_events
Full input schema (JSON)
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "calendar": {
      "default": "primary",
      "description": "calendar name or ID; primary is the account's own",
      "type": "string",
      "minLength": 1,
      "maxLength": 300
    },
    "id": {
      "type": "string",
      "minLength": 1,
      "maxLength": 1100,
      "description": "the event's id, from list_events"
    }
  },
  "required": [
    "id"
  ]
}
free_busyRead only

When people are busy between two times (default: the next 7 days), from their calendars. Works for colleagues whose calendars share free/busy.

Approval: Uses your workspace and hire approval settings.

Arguments for free_busy
ArgumentTypeDetails
peopleOptionalstring[]email addresses (or calendar IDs); primary for the account's own calendarDefault: ["primary"]
fromOptionalstringfrom (default now): 2026-11-10T14:00 in the calendar's time zone, or 2026-11-10 for a day
toOptionalstringuntil (default a week after from): 2026-11-10T14:00 in the calendar's time zone, or 2026-11-10 for a day
Full input schema (JSON)
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "people": {
      "default": [
        "primary"
      ],
      "maxItems": 50,
      "type": "array",
      "items": {
        "type": "string",
        "minLength": 3,
        "maxLength": 320
      },
      "description": "email addresses (or calendar IDs); primary for the account's own calendar"
    },
    "from": {
      "type": "string",
      "minLength": 10,
      "maxLength": 40,
      "description": "from (default now): 2026-11-10T14:00 in the calendar's time zone, or 2026-11-10 for a day"
    },
    "to": {
      "type": "string",
      "minLength": 10,
      "maxLength": 40,
      "description": "until (default a week after from): 2026-11-10T14:00 in the calendar's time zone, or 2026-11-10 for a day"
    }
  }
}
find_timeRead only

Suggest times when everyone is free for a meeting of a given length, inside working hours on working days, in the calendar's time zone.

Approval: Uses your workspace and hire approval settings.

Arguments for find_time
ArgumentTypeDetails
peopleOptionalstring[]email addresses (or calendar IDs); primary for the account's own calendarDefault: ["primary"]
duration_minutesOptionalintegerSee input schema below.Default: 30
fromOptionalstringearliest (default now): 2026-11-10T14:00 in the calendar's time zone, or 2026-11-10 for a day
toOptionalstringlatest (default a week after from): 2026-11-10T14:00 in the calendar's time zone, or 2026-11-10 for a day
day_startOptionalstringworking hours start, HH:MMDefault: "09:00"
day_endOptionalstringworking hours end, HH:MMDefault: "18:00"
daysOptional"mon" | "tue" | "wed" | "thu" | "fri" | "sat" | "sun"[]working daysDefault: ["mon","tue","wed","thu","fri"]
limitOptionalintegerSee input schema below.Default: 5
Full input schema (JSON)
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "people": {
      "default": [
        "primary"
      ],
      "maxItems": 50,
      "type": "array",
      "items": {
        "type": "string",
        "minLength": 3,
        "maxLength": 320
      },
      "description": "email addresses (or calendar IDs); primary for the account's own calendar"
    },
    "duration_minutes": {
      "default": 30,
      "type": "integer",
      "minimum": 10,
      "maximum": 480
    },
    "from": {
      "type": "string",
      "minLength": 10,
      "maxLength": 40,
      "description": "earliest (default now): 2026-11-10T14:00 in the calendar's time zone, or 2026-11-10 for a day"
    },
    "to": {
      "type": "string",
      "minLength": 10,
      "maxLength": 40,
      "description": "latest (default a week after from): 2026-11-10T14:00 in the calendar's time zone, or 2026-11-10 for a day"
    },
    "day_start": {
      "default": "09:00",
      "description": "working hours start, HH:MM",
      "type": "string",
      "pattern": "^\\d{2}:\\d{2}$"
    },
    "day_end": {
      "default": "18:00",
      "description": "working hours end, HH:MM",
      "type": "string",
      "pattern": "^\\d{2}:\\d{2}$"
    },
    "days": {
      "default": [
        "mon",
        "tue",
        "wed",
        "thu",
        "fri"
      ],
      "description": "working days",
      "minItems": 1,
      "type": "array",
      "items": {
        "type": "string",
        "enum": [
          "mon",
          "tue",
          "wed",
          "thu",
          "fri",
          "sat",
          "sun"
        ]
      }
    },
    "limit": {
      "default": 5,
      "type": "integer",
      "minimum": 1,
      "maximum": 10
    }
  }
}
create_eventRead and write

Put an event on a calendar, optionally inviting people (they get an invitation) and adding a video call. Inviting people outside the team commits the business to them, so such a call waits for a person's approval: Roster asks for you and makes it, exactly as you called it, once they approve.

Approval: when it invites someone outside your team, or moves an event they're on.

Arguments for create_event
ArgumentTypeDetails
calendarOptionalstringcalendar name or ID; primary is the account's ownDefault: "primary"
titleRequiredstringSee input schema below.
startRequiredstringstart: 2026-11-10T14:00 in the calendar's time zone, or 2026-11-10 for a day
endOptionalstringend; or give duration_minutes
duration_minutesOptionalintegerSee input schema below.
locationOptionalstringSee input schema below.
descriptionOptionalstringSee input schema below.
attendeesOptionalstring[]email addresses to inviteDefault: []
video_callOptionalbooleanadd a video call linkDefault: false
notifyOptionalbooleansend invitations by emailDefault: true
Full input schema (JSON)
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "calendar": {
      "default": "primary",
      "description": "calendar name or ID; primary is the account's own",
      "type": "string",
      "minLength": 1,
      "maxLength": 300
    },
    "title": {
      "type": "string",
      "minLength": 1,
      "maxLength": 300
    },
    "start": {
      "type": "string",
      "minLength": 10,
      "maxLength": 40,
      "description": "start: 2026-11-10T14:00 in the calendar's time zone, or 2026-11-10 for a day"
    },
    "end": {
      "description": "end; or give duration_minutes",
      "type": "string",
      "minLength": 10,
      "maxLength": 40
    },
    "duration_minutes": {
      "type": "integer",
      "minimum": 5,
      "maximum": 1440
    },
    "location": {
      "type": "string",
      "minLength": 1,
      "maxLength": 500
    },
    "description": {
      "type": "string",
      "minLength": 1,
      "maxLength": 8000
    },
    "attendees": {
      "default": [],
      "description": "email addresses to invite",
      "maxItems": 100,
      "type": "array",
      "items": {
        "type": "string",
        "minLength": 3,
        "maxLength": 320
      }
    },
    "video_call": {
      "default": false,
      "description": "add a video call link",
      "type": "boolean"
    },
    "notify": {
      "default": true,
      "description": "send invitations by email",
      "type": "boolean"
    }
  },
  "required": [
    "title",
    "start"
  ]
}
update_eventRead and write

Change an event: its title, time, place, notes, or who's invited (attendees are told when notify is on). Inviting people outside the team commits the business to them, so such a call waits for a person's approval: Roster asks for you and makes it, exactly as you called it, once they approve.

Approval: when it invites someone outside your team, or moves an event they're on.

Arguments for update_event
ArgumentTypeDetails
calendarOptionalstringcalendar name or ID; primary is the account's ownDefault: "primary"
idRequiredstringthe event's id, from list_events
titleOptionalstringSee input schema below.
startOptionalstringnew start: 2026-11-10T14:00 in the calendar's time zone, or 2026-11-10 for a day
endOptionalstringnew end: 2026-11-10T14:00 in the calendar's time zone, or 2026-11-10 for a day
locationOptionalstringSee input schema below.
descriptionOptionalstringSee input schema below.
add_attendeesOptionalstring[]See input schema below.Default: []
remove_attendeesOptionalstring[]See input schema below.Default: []
notifyOptionalbooleantell attendees by emailDefault: true
Full input schema (JSON)
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "calendar": {
      "default": "primary",
      "description": "calendar name or ID; primary is the account's own",
      "type": "string",
      "minLength": 1,
      "maxLength": 300
    },
    "id": {
      "type": "string",
      "minLength": 1,
      "maxLength": 1100,
      "description": "the event's id, from list_events"
    },
    "title": {
      "type": "string",
      "minLength": 1,
      "maxLength": 300
    },
    "start": {
      "type": "string",
      "minLength": 10,
      "maxLength": 40,
      "description": "new start: 2026-11-10T14:00 in the calendar's time zone, or 2026-11-10 for a day"
    },
    "end": {
      "type": "string",
      "minLength": 10,
      "maxLength": 40,
      "description": "new end: 2026-11-10T14:00 in the calendar's time zone, or 2026-11-10 for a day"
    },
    "location": {
      "type": "string",
      "maxLength": 500
    },
    "description": {
      "type": "string",
      "maxLength": 8000
    },
    "add_attendees": {
      "default": [],
      "maxItems": 100,
      "type": "array",
      "items": {
        "type": "string",
        "minLength": 3,
        "maxLength": 320
      }
    },
    "remove_attendees": {
      "default": [],
      "maxItems": 100,
      "type": "array",
      "items": {
        "type": "string",
        "minLength": 3,
        "maxLength": 320
      }
    },
    "notify": {
      "default": true,
      "description": "tell attendees by email",
      "type": "boolean"
    }
  },
  "required": [
    "id"
  ]
}
cancel_eventRead and write

Cancel an event this calendar organised, telling attendees (with an optional note) when notify is on. For someone else's event, decline it with respond_to_invitation instead.

Approval: Uses your workspace and hire approval settings.

Arguments for cancel_event
ArgumentTypeDetails
calendarOptionalstringcalendar name or ID; primary is the account's ownDefault: "primary"
idRequiredstringthe event's id, from list_events
noteOptionalstringa short message to attendees, where the calendar supports it
notifyOptionalbooleanSee input schema below.Default: true
Full input schema (JSON)
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "calendar": {
      "default": "primary",
      "description": "calendar name or ID; primary is the account's own",
      "type": "string",
      "minLength": 1,
      "maxLength": 300
    },
    "id": {
      "type": "string",
      "minLength": 1,
      "maxLength": 1100,
      "description": "the event's id, from list_events"
    },
    "note": {
      "description": "a short message to attendees, where the calendar supports it",
      "type": "string",
      "minLength": 1,
      "maxLength": 2000
    },
    "notify": {
      "default": true,
      "type": "boolean"
    }
  },
  "required": [
    "id"
  ]
}
respond_to_invitationRead and write

Accept, decline or say maybe to an event someone else invited this calendar to, with an optional note to the organiser.

Approval: Uses your workspace and hire approval settings.

Arguments for respond_to_invitation
ArgumentTypeDetails
calendarOptionalstringcalendar name or ID; primary is the account's ownDefault: "primary"
idRequiredstringthe event's id, from list_events
responseRequired"accept" | "decline" | "maybe"See input schema below.
noteOptionalstringSee input schema below.
Full input schema (JSON)
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "calendar": {
      "default": "primary",
      "description": "calendar name or ID; primary is the account's own",
      "type": "string",
      "minLength": 1,
      "maxLength": 300
    },
    "id": {
      "type": "string",
      "minLength": 1,
      "maxLength": 1100,
      "description": "the event's id, from list_events"
    },
    "response": {
      "type": "string",
      "enum": [
        "accept",
        "decline",
        "maybe"
      ]
    },
    "note": {
      "type": "string",
      "minLength": 1,
      "maxLength": 2000
    }
  },
  "required": [
    "id",
    "response"
  ]
}

Watches and incoming events

  • This integration supports a responsibility that watches for changes. The guide above explains what it checks and how to limit it.
  • No incoming webhook handler is declared for this integration.

Limits and troubleshooting

  • Permission errors: check both the connected account's rights and the hire's resource and read/write limits.
  • Expired or revoked access: reconnect or replace the key on the connection.
  • Rate limits and unavailable services can interrupt work. The hire's timecard records the outcome.
  • The action schema describes accepted inputs. It does not grant additional access or bypass approvals.

Service documentation · Integration source reference

On this page