Building a Meeting Room Display with Microsoft Graph: What It Takes (and When to Just Buy One)
You can absolutely build a meeting room display on the Microsoft Graph API. The two endpoints you need are not complicated. Here is exactly what the build looks like, the three things that quietly turn a weekend project into a maintenance job, and the honest line for when buying is cheaper.
At some point, usually after getting a quote for room displays, an engineer in the building says the thing every engineer says: "We're already paying for Microsoft 365. The room data is right there in Graph. I could build this in a weekend."
They are not wrong about the data. Room availability genuinely is right there in the Microsoft Graph API, and the two endpoints you need are not complicated. The weekend estimate is where it goes sideways, and it goes sideways in three specific, predictable places.
This post is the honest version. What the build actually looks like, which endpoints do the work, the three things that turn it from a weekend project into a thing you maintain forever, and the napkin math for when buying a finished product is the cheaper decision. Written for the person who could build it, so you can decide whether you should.
The two endpoints that do the work
A room display has to answer two questions: which rooms exist, and is this one free right now. Graph has a clean answer for each.
Listing rooms: the Places API. The modern way to enumerate rooms is the places endpoint:
GET https://graph.microsoft.com/v1.0/places/microsoft.graph.room
This returns up to 100 rooms per page, with a richer payload than the older findRooms function (capacity, building, floor, and the rest of the Place metadata). There is also a findRooms action, but as of 2026 it still lives in the beta endpoint, so for anything you intend to keep running, prefer places.
Checking availability: getSchedule. Once you have a room's mailbox address, free/busy comes from a single call:
POST https://graph.microsoft.com/v1.0/me/calendar/getSchedule
{
"schedules": ["boardroom@yourdomain.com"],
"startTime": { "dateTime": "2026-06-08T08:00:00", "timeZone": "Europe/Copenhagen" },
"endTime": { "dateTime": "2026-06-08T18:00:00", "timeZone": "Europe/Copenhagen" },
"availabilityViewInterval": 15
}
getSchedule returns a scheduleInformation object per room with a free/busy view and the meeting blocks. It takes up to 20 schedules in one call, which matters later. The least-privileged permission is Calendars.Read, and crucially it supports app-only access, so your display can authenticate as itself rather than as a signed-in human. That is the difference between a display and a kiosk someone has to log into every Monday.
That is the whole data layer. Two endpoints. This is why the weekend estimate feels reasonable, and for a single-room proof of concept it more or less is.
If the build is still an open question at this stage, our guide to meeting room display software covers what the finished products already handle.
The three things that turn a weekend into a maintenance job
Here is where the estimate quietly triples. None of these are exotic. They are just the unglamorous 80% that the demo never shows.
1. Auth that survives a reboot at 6am with nobody watching
App-only auth via client credentials is the right model, which means registering an app in Entra ID, granting Calendars.Read (or Place.Read.All for the room list) with admin consent, and storing a client secret or certificate on a device that lives screwed to a wall in a corridor. Secrets expire. Certificates rotate. When that credential lapses, every display in the building goes blank at once, and the person who set it up has usually changed teams. Building the token flow is an afternoon. Building the part where it renews itself, fails gracefully, and tells someone before it dies is the actual work.
2. Throttling, and the math of "every room, every minute"
A display that feels live needs to refresh roughly every 30 to 60 seconds. Multiply that by every room, and you are making a lot of Graph calls. Graph throttles per-app and per-mailbox, and it will start returning 429 responses with Retry-After headers exactly when you have the most rooms, which is exactly when you least want screens freezing. This is what getSchedule's 20-schedules-per-call limit is for: batch your rooms, stagger the polling, cache aggressively, and respect Retry-After. Doable, but this is real backend engineering, not a fetch loop.
3. The check-in and release loop
Reading availability is the easy half. The reason rooms get displays at all is usually ghost meetings: the room shows busy, nobody turns up, and it stays locked for an hour. Fixing that means a button on the glass that checks people in and auto-releases the room when they don't. Now you are writing back to calendars, handling the "who is allowed to release this" question, dealing with recurring meetings, and reconciling your write with whatever the room mailbox's own auto-processing does. (If that last sentence sounds like a trap, it is — see our piece on auto-releasing rooms for why.) This is the feature people actually want, and it is the hardest 20% by a wide margin.
The part Graph doesn't give you at all: the hardware
Even with the software solved, a display is a physical object on a wall. You need a screen, something to power it, a mounting plan, a way to push updates to fifteen devices without visiting each one, and a story for what shows on the screen when the wifi drops. Graph has no opinion on any of this. If you go the tablet route, our guide to the best tablet for a meeting room display covers why the obvious choice is usually the wrong one, and the e-ink vs tablet vs TV comparison covers the trade-offs. The point here is only that the API is one layer of a three-layer problem.
The honest build-vs-buy math
So when does building win? The deciding number is rarely the licence fee. It is engineering time.
A serious in-house build — auth that self-renews, batched and throttle-aware polling, a check-in and release loop, an update mechanism, and monitoring so you know when a screen dies — is realistically two to four weeks of a competent engineer's time to build, plus a standing maintenance tail every time Microsoft adjusts Graph, a secret expires, or someone adds a room. Off-the-shelf room display software typically runs in the low tens of dollars per room per month and has already solved every one of the three hard parts above, plus the hardware.
The rule of thumb that holds up: if you have fewer than roughly 30 rooms, buying is almost always cheaper once you count the maintenance tail. Building makes sense when you have unusual requirements an off-the-shelf product can't meet (a bespoke check-in flow, integration with a custom facilities system, signage that has to match a strict brand spec), genuine scale, and an engineer whose job is explicitly to own it. "We already pay for M365" is a reason the data is available. It is not, by itself, a reason to build.
Lobby is the buy side of this decision — it reads exactly these Graph endpoints, handles the auth, throttling, and check-in loop, and runs on low-power displays — so if you read the three hard parts and thought "yeah, I don't want to own that," that is the product's entire reason to exist.
TL;DR
Building a meeting room display on Microsoft Graph is real and not that hard at the data layer: use GET /places/microsoft.graph.room to list rooms and POST /calendar/getSchedule (app-only, Calendars.Read) for free/busy. The cost lives in three places the demo hides — self-renewing app auth, throttle-aware batched polling, and a check-in/release write loop — plus the hardware Graph doesn't touch. Under ~30 rooms, buying is almost always cheaper once you count maintenance. Build only for genuinely bespoke requirements with an owner assigned.
Related reading
- Microsoft 365 Room Mailboxes: The IT Manager's Setup and Hygiene Checklist
- How to Release a Meeting Room Automatically
- Why Your Meeting Rooms Show "Free" When They're Not
- E-Ink vs. Tablet vs. TV: Choosing the Right Hardware