If you've ever worked with SharePoint through the Microsoft Graph API, you've probably run into the same rabbit hole we did: how do you deal with lookups to users?
Naturally, the first question is: Where does SharePoint keep its list of known users?
If you search online, you'll find the same advice repeated everywhere: "Look for the list named User Information List."
At first glance, that sounds simple. Unfortunately, it isn't.
The problem with filtering
When querying SharePoint lists through MS Graph API (/sites/{tenant}.sharepoint.com,{siteId},{webId}/lists), we expected to be able to filter by useful fields such as `name`, `system`, or others. Every attempt failed with errors - except one:
$filter=displayName eq 'User Information List'
That was the only filter that actually worked. Relying on `displayName` felt brittle, especially since localization could easily change it. But with no other option, we reluctantly continued with this "solution".
The localisation surprise
Then came the day when a client's SharePoint site didn't have a "User Information List" at all. Or so we thought.
The catch? Their SharePoint instance was running in a non-English localisation. The list was there, just under a different name. Since the Graph API wasn't returning system lists by default, we couldn't see it.
We cross-checked with an English-localised instance and confirmed something important: system lists are hidden unless you explicitly include them. (facepalm moment).
The solution
The trick is to use the `system` property when listing lists. This ensures that system lists are included in the response. Once you do that, you can safely filter by `name=users` in your code, which stays consistent regardless of localization.
Here's the request:
GET https://graph.microsoft.com/v1.0/sites/{tenant}.sharepoint.com,{siteId},{webId}/lists?$top=999&$select=id,name,displayName,system
And a sample response:
{
"@odata.etag": "\"xxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx,240\"",
"id": "xxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"name": "users",
"displayName": "User Information List",
"system": {}
}
Notice the important part: `"name": "users"`.
That's the consistent key you should rely on, not the localised `displayName`.
What we learned (the hard way)
- Graph API filtering on lists is extremely limited.
- System lists (like the User Information List) don't show up unless you include `system`.
- Always rely on `name=users` instead of `displayName`, so your code works across different languages and tenants.
With this approach, you can reliably retrieve the User Information List's ID and name without falling into localisation or filtering traps.