Skip to content
Skip to main content

How to list Microsoft contacts

Last updated:

Pulling contacts out of Microsoft 365 the native way means a detour through Azure AD: register an app, request the Contacts.Read permission, clear admin consent for enterprise tenants, then handle Graph throttling on top. The address book itself is one GET call once you’re past that setup.

The Nylas Contacts API skips the Azure registration and the Graph plumbing. One request reads an Outlook address book and returns the same contact schema you’d get from a Google or Exchange account, so your code doesn’t branch per provider.

Why use Nylas instead of the Microsoft Graph API directly?

Section titled “Why use Nylas instead of the Microsoft Graph API directly?”

Microsoft Graph exposes contacts through GET /me/contacts, but reaching that endpoint takes real setup work. You register an Azure AD application, request the Contacts.Read permission scope, secure admin consent for organization tenants, and run the MSAL token lifecycle yourself. The 4 hurdles below are where most of the time goes:

  • Azure AD app registration: every Graph integration starts with an app object, a client secret, and redirect URIs configured in the Azure portal.
  • Admin consent: tenant admins must approve delegated permissions like Contacts.Read before users in restricted organizations can connect.
  • Graph permission scopes: read access needs Contacts.Read; read-write needs Contacts.ReadWrite, and each scope changes the consent prompt.
  • Throttling: Graph returns HTTP 429 with a Retry-After header once a mailbox exceeds its per-app request budget, so you build backoff logic.

The API normalizes all 4 into one REST call with one contact object. If you already run Graph and only target Microsoft, the native route works fine.

To list Microsoft contacts you need a connected Outlook or Microsoft 365 account and the right Graph permission on your Azure app. Setup takes 2 pieces: an authenticated grant and the Contacts.Read scope approved for the tenant.

  • A Nylas application with a valid API key
  • A grant for a Microsoft 365 or Outlook account
  • The Contacts.Read permission enabled in your Azure AD app registration

For the full Azure AD walkthrough, including admin consent and publisher verification, see the Microsoft provider guide.

Many Microsoft organizations block third-party apps until a tenant admin approves them. If users hit a “Need admin approval” screen during auth, their organization restricts user consent and an admin must grant the Contacts.Read permission once for the whole tenant. After that single approval, every user in that organization can connect without seeing the prompt again. Nylas documents the flow in Configuring Microsoft admin approval.

Send a GET request to /v3/grants/{grant_id}/contacts with the grant ID for the Outlook account. The endpoint returns the user’s address book as a data array of contact objects plus a request_id. Each object carries the full contact, so a single parser reads all 3 providers (Outlook, Gmail, and Exchange) without provider-specific branches.

The request below lists contacts for one grant. The response is the unified Nylas contact schema, with emails, phone_numbers, job_title, company_name, and groups populated from the Microsoft account.

For create, update, and delete operations plus the complete field reference, see Manage contacts with the Contacts API.

Narrow the result set with query parameters instead of listing every contact and filtering client-side. The list endpoint accepts email, phone_number, source, group, and recurse, and Microsoft supports all 5. The recurse parameter is Microsoft-only and descends exactly 1 level into Contact Group subgroups.

This curl request returns contacts whose email contains jane from the user’s saved address book. Swap email for group to pull a single Outlook contact folder by its group ID.

The source=inbox value surfaces people the user has emailed but never saved, which is handy for recipient autocomplete. On Microsoft it needs the extra People.Read permission alongside Contacts.Read.

Microsoft contacts behave differently from Google’s in 5 areas worth knowing before you build: the Graph endpoint mapping, contact folders, categories, the lack of auto-generated contacts, and throttling. The notes below cover each so your integration doesn’t trip on an Outlook-specific quirk.

Behind the scenes, Nylas reads Microsoft contacts through Graph’s GET /me/contacts endpoint and normalizes the response into the unified schema. Graph fields like emailAddresses, businessPhones, and jobTitle become emails, phone_numbers, and job_title. You read the normalized object and never touch a Graph field name. The required delegated scope is Contacts.Read, the same permission Microsoft lists for that endpoint.

Outlook stores contacts in folders, and each folder maps to a Nylas contact group. Filter to one folder by passing its ID through the group query parameter, then add recurse=true to include subfolders 1 level deep. Don’t hardcode folder names because users rename and create their own. List the groups first to discover the real IDs for an account.

Microsoft has two organizing concepts that look similar but aren’t. Contact folders map to Nylas groups; Outlook categories (the colored labels like “Red Category”) are a separate tagging system that Graph exposes as a categories string array on the contact, not as folders. If you need category data, the unified contact object won’t carry it the way it carries group membership, so plan around folders rather than categories for grouping.

Google quietly builds an “Other contacts” list from people you’ve emailed, exposed through the contacts.other.readonly scope. Microsoft has no equivalent auto-created collection. An Outlook address book holds only contacts the user explicitly saved. To suggest people the user has emailed but never saved, use the source=inbox filter, which Nylas derives from message participants rather than from any Microsoft-managed list.

Microsoft Graph enforces per-app, per-mailbox request limits and answers an over-budget request with HTTP 429 Too Many Requests and a Retry-After header telling you how many seconds to wait. Nylas retries throttled requests automatically, so you don’t write backoff logic yourself. If your app polls contacts on a tight loop across many mailboxes, you’ll still hit these limits faster. Microsoft documents the behavior in its throttling guidance. Sync contact changes with webhooks instead of polling to stay well under the cap.