Book meeting rooms in Google Workspace and Microsoft 365 with an API
Updated
TL;DR
A room is a calendar with its own email address: you book it by adding that address to the event as an attendee, as a resource on Google (resource: true) or as type resource on Graph, and the room accepts or declines on its own. Listing rooms is the harder part: Google needs the Admin SDK Directory API and an admin-level scope, and Microsoft's Places API needs Place.Read.All, which requires admin consent, and returns nothing until Places is set up in the tenant. Personal Gmail and Outlook.com accounts have no rooms.
A room is a calendar
In both Google Workspace and Microsoft 365, a meeting room is a resource with its own calendar and email address. You don't "reserve" it through a separate API. You invite it.
Google: "To book a room or other resource, add its email address as an event attendee." Mark it with "resource": true, which "Can only be set when the attendee is added to the event for the first time." The room then "automatically accepts or declines the invitation" based on its availability and who may book it. (Google's resources guide)
Microsoft Graph: add the room's address as an attendee with "type": "resource". Exchange's default: "anyone can book resources. The bookings are automatically accepted if the resource is available", and it declines on "A scheduling conflict with an existing reservation", with a default booking window of 180 days and a maximum meeting length of 24 hours. (Exchange resource mailboxes)
The room's answer comes back as that attendee's response status, so read the event again, or wait for the change, before telling your user the room is theirs.
Listing rooms on Google
The Calendar API can't list or create rooms; "The Calendar API does not offer a way to create resource calendars." Rooms live in the Admin SDK Directory API:
GET https://admin.googleapis.com/admin/directory/v1/customer/my_customer/resources/calendars
?query=buildingId=US-NYC-9TH AND featureInstances.feature.name:PhoneIt needs admin.directory.resource.calendar.readonly (or the read-write scope). Each resource has a resourceEmail to invite, a resourceCategory of CONFERENCE_ROOM or OTHER, a capacity ("number of seats in a room"), a buildingId, a floorName and featureInstances. The query parameter filters on building, capacity, features and category. Expect the call to be refused for users who aren't Workspace administrators.
Listing rooms on Microsoft 365
Graph's Places API lists rooms and room lists:
GET https://graph.microsoft.com/v1.0/places/microsoft.graph.room
GET https://graph.microsoft.com/v1.0/places/{room-list-email}/microsoft.graph.roomlist/roomsIt needs Place.Read.All, which requires admin consent, and personal Microsoft accounts are "Not supported". Pages hold up to 100 rooms. One prerequisite catches many teams: Places must be configured in the tenant, "otherwise, these APIs do not return any places", and "All rooms must be associated with Exchange mailboxes." The older findRooms call is beta only, and Microsoft says "Use of these APIs in production applications is not supported."
Is the room free?
Check rooms the way you check people. On Google, add the room's email to a freeBusy query; on Graph, getSchedule takes "users, distributions lists, or resources (rooms or equipment)". To find a time that suits several people and a room, intersect everyone's free time, then keep only the slots where at least one room that fits is also free. Find a meeting time across calendars walks through the people part.
Personal accounts
Gmail and Outlook.com accounts have no room directory, and Places, findRooms and getSchedule don't support personal Microsoft accounts. A product that serves both should offer rooms only to work accounts.
How Pyas does it
Rooms work the same way on Google Workspace and Microsoft 365:
GET /v2/roomslists a connected work account's rooms with their name, email, capacity, building, floor and features, filtered by minimum capacity, building, feature or name. On Google, Pyas reads the Directory API, which needs the admin directory scope through Native Auth; on Microsoft 365, it reads Places.roomson an event books rooms by email, up to 20, sent as a resource attendee to each provider. Reads return each room with its response, separately from people.- Meeting times with a room. Ask for meeting times with
roomsand Pyas picks matching rooms, smallest first, and returns only the slots where everyone and a room are free.
See the calendar API for the full event model.