Working with presence¶
Presence answers one question: is this person reachable right now? It is a
per-user resource (/users/{id}/presence) that Teams keeps current, driven by
the user's activity (InACall, InAMeeting, …). The scripts here read it in
bulk, override it for yourself, and poll it for changes — using throwaway state
that expires on its own.
Permissions: Presence.Read (your own), Presence.Read.All (anyone),
Presence.ReadWrite (change your own).
The model¶
flowchart LR
M["client.me.presence"] --> A["availability<br/>Available · Busy · DoNotDisturb · Offline"]
M --> AC["activity<br/>InACall · InAMeeting · OutOfOffice · …"]
M --> SM["status_message"]
M --> WL["work_location"]
C["client.communications"] --> B["get_presences_by_user_id([…])"]
availability is the coarse state; activity refines it. A status message and a
work location ride along on the same resource.
Read one user¶
→ get.py — pass --user ana@contoso.com to read a colleague's
presence with client.users[upn].presence.
Read many users at once¶
One request per 650 users instead of one per user — the right shape for a people-picker or a "who's available" dashboard.
for presence in client.communications.get_presences_by_user_id(upns).execute_query():
print(presence.id, presence.availability, presence.activity)
Set your own presence¶
client.me.presence.set_user_preferred_presence("DoNotDisturb", "DoNotDisturb", "PT2H").execute_query()
client.me.presence.set_status_message("In a meeting", expiry).execute_query()
→ set.py · the counterpart is clear.py
Two things to know:
- It only shows while the user has a presence session — i.e. while Teams
(or an app) is signed in. With no session, the API keeps reporting
Offlineno matter what you set. A preferred presence is not a fake presence. expiration_durationis a fixed window (5–240 minutes); when it lapses, the presence reverts to automatic. Clearing ends it immediately. There is noclearStatusMessageaction in this API version, so an empty message is the way to wipe a status message.
An application can also publish presence for its own sessions — for example a
softphone — with client.communications.presences[user_id].set_presence(session_id, …).
Watch for changes¶
Presence has no change notifications: no webhooks, no delta. Monitoring means polling, and the pattern is bulk-read, remember the previous state, report only transitions. The same file shows the business rules — who is reachable, and how to drive an agent on/off duty.
Troubleshooting¶
| Symptom | Cause |
|---|---|
everyone is PresenceUnknown |
the caller lacks Presence.Read.All, or no user session exists |
set succeeded but presence is Offline |
the user has no presence session (Teams closed) |
403 when reading someone else |
the app only has Presence.Read (own presence) |
set-time 400 |
expirationDuration outside PT5M–PT4H |
InvalidArgument: The provided availability/activity is invalid |
the activity must match the availability (Available/Available, Away/Away, DoNotDisturb/DoNotDisturb, Offline/OffWork) — you cannot fake InAMeeting |
Cannot set the presence of another user |
delegated setUserPreferredPresence only works on /me/presence |