Skip to content
Docs
Calendars & meetings

Outlook Calendar (Microsoft 365)

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

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

With Outlook Calendar, a hire can do everything it does with Google Calendar, in the same way:

  • list your calendars and what's on them, and read an event with who's coming and how they answered,
  • see when colleagues are busy, and suggest times when everyone is free inside working hours,
  • put events on a calendar, with a Teams meeting and invitations if you like,
  • move, rename or cancel meetings it organised, 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 in Microsoft 365.

1. Register an app in Microsoft Entra

If you already registered one for Outlook mail, use the same app: add the permissions below and a second redirect URI.

  1. Open entra.microsoft.com → App registrations → New registration (or open your Roster app).
  2. Supported account types: Accounts in this organizational directory only for your own organisation.
  3. Redirect URI: platform Web, the address Roster shows on the Outlook Calendar connection. It ends in /api/integrations/microsoft-calendar/oauth/callback.
  4. Copy the Application (client) ID and the Directory (tenant) ID from Overview.
  5. API permissions → Add a permission → Microsoft Graph → Delegated permissions: add User.Read, Calendars.ReadWrite and offline_access. If Microsoft says your organisation must approve the app, ask whoever manages your Microsoft 365 to grant consent on this page.
  6. Certificates & secrets → New client secret, and copy its Value.

2. Connect it in Roster

  1. Open Integrations → Tools → Add a tool, search for Outlook Calendar and choose it.
  2. Paste the OAuth app client ID (the Application ID) and OAuth app client secret.
  3. Tenant: your Directory (tenant) ID or domain, or common.
  4. Time zone: the zone hires read and write times in, like Asia/Dubai. Set this: without it, hires use UTC.
  5. Click Connect, then Connect with Outlook Calendar on the new connection, sign in with the calendar's account and click Accept.

What Roster asks Microsoft for

PermissionWhy
User.ReadKnow the account's own address
Calendars.ReadWriteRead events and availability; book, change, cancel and answer (only hires allowed to)
offline_accessStay connected without signing in again

3. Give hires access

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

  • Read only: it can list calendars and events, see who's free and suggest times, and nothing else.
  • Read and write: it can also book, change and cancel events and answer invitations.
  • Calendars: the calendars it may use, by name; primary is the account's main calendar. 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.

Microsoft 365 always tells attendees when a meeting is booked, changed or cancelled; a hire can't do any of those quietly. 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 until the approver says yes, and then Roster books exactly that meeting. 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.

Waking a hire when the calendar changes

A hire's responsibility can watch Outlook Calendar: it's woken when events in the next three months on the main calendar change or 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 Outlook Calendar on the connection.
  • "Can't see their calendar" when finding a time: that person is outside your organisation or doesn't share their availability. Finding times isn't available for personal Outlook.com accounts.
  • Times are a few hours off: set the connection's Time zone.
  • Microsoft says the app needs approval: whoever manages your Microsoft 365 grants consent on the app's API permissions page.

Tools and permissions reference

This reference is built from the same definitions Roster uses to connect Outlook Calendar (Microsoft 365) 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

The Application (client) ID of the app you registered for Roster in Microsoft Entra.

Requested scopes:

  • offline_access
  • User.Read
  • Calendars.ReadWrite

Connection fields

Outlook Calendar (Microsoft 365) connection fields
FieldWhat to provide
OAuth app client ID
clientId
Optional
The Application (client) ID of the app you registered for Roster in Microsoft Entra.
OAuth app client secret
clientSecret
Optional · sealed secret
Use the value for your account or connection.
Tenant
tenant
Optional
Your Microsoft 365 organisation's tenant ID or domain (in Microsoft Entra → Overview). Leave it as common to let any work, school or personal account sign in.

Starts with: common.

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.

Outlook Calendar (Microsoft 365) 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