Microsoft Graph documentation

Use the Microsoft Graph API to connect to the data that drives productivity – mail, calendar, contacts, documents, directory, devices, and more.
Repo URL: https://github.com/marcin-baczewski/microsoft-graph-docs
Edited by:
Cover image: Cover image
Share this using: email, Google+, Twitter, Facebook.
Exports:

1 Get started with Microsoft Graph in an Android app

Building apps for enterprise customers? Your app may not work if your enterprise customer turns on enterprise mobility security features like <a href=“https://azure.microsoft.com/en-us/documentation/articles/active-directory-conditional-access-device-policies/” target=“_newtab“>conditional device access</a>. In this case, you may not know and your customers may experience errors.

To support all enterprise customers across all enterprise scenarios, you must use the Azure AD endpoint and manage your apps using the Azure Management Portal. For more information, see Deciding between the Azure AD and Azure AD v2.0 endpoints.

This article describes the tasks required to get an access token from the Azure AD v2.0 endpoint and call Microsoft Graph. It walks you through building the Connect Sample for Android and explains the main concepts that you implement to use Microsoft Graph in your app for Android. The article also describes how to access Microsoft Graph by using either the Microsoft Graph SDK for Android or raw REST calls.

To use Microsoft Graph in your app for Android, you need to show the Microsoft sign in page to your users, as shown in the following screenshot.

Sign in page for Microsoft accounts on Android

Don’t feel like building an app? Get up and running fast by downloading the Connect Sample for Android that this article is based on.

1.1 Prerequisites

To get started, you’ll need:

1.2 Configure a new project

If you have downloaded the Connect Sample for Android, skip this step.

Start a new project in Android Studio. You can leave the default values for most of the wizard, just make sure to choose the following options:

  • Target Android Devices - Phone and Tablet
    • Minimum SDK - API 16: Android 4.1 (Jelly Bean)
  • Add an Activity to Mobile - Basic Activity

This provides you with an Android project with an activity and a button that you can use to authenticate the user.

1.3 Register the application

You need to register your app on the Microsoft App Registration Portal whether you’ve downloaded the connect sample or created a new project.

Register an app on the Microsoft App Registration Portal. This generates the app ID that you’ll use to configure the app.

  1. Sign into the Microsoft App Registration Portal using either your personal or work or school account.

  2. Choose Add an app.

Tip: If you have downloaded the Connect Sample for Android and are just creating a registration for it, uncheck Guided Setup before chosing the Create button.

  1. Enter a name for the app, and choose Create.

    For the Guided Setup flow:

    a. Choose Mobile and Desktop App to define the kind of app you are creating.

    b. Choose Android to define the mobile technology you are using.

    c. Review the introductory topic and when finished, click the Setup button at the end of the page.

    d. Follow the instructions on the Setup step to add the MSAL library to your app build.gradle.

    e. Follow the directions on the Use step to add MSAL logic to your new project

    f. On the Configure page, the portal has created a unique application ID for you. Use it to configure your app.

    For the unguided flow:

    The registration page displays, listing the properties of your app.

    a. Copy the application ID. This is the unique identifier for your app.

    b. Choose Add Platform and Native Application.

    Note: The Application Registration Portal provides a Redirect URI with a value of msalYOUR NEW APP ID://auth. Do not use the built-in redirect URIs. The Connect Sample for Android implements the MSAL authentication library which requires this redirect URI. If using a supported third party library or the ADAL library then you must use the built-in redirect URIs.

    For Guided Setup flow and unguided flow

    a. Add delegated permissions. You’ll need profile, Mail.ReadWrite, Mail.Send, Files.ReadWrite, and User.ReadBasic.All.

    b. Choose Save.

1.4 Authenticate the user and get an access token

Note: If you followed the instructions in the Guided Setup flow from the application registration portal to create a new application, you can skip these steps. Go to Call Microsoft Graph using the Microsoft Graph SDK to learn more about the Graph API.

Let’s walk through the Connect Sample for Android to learn about the MSAL and Microsoft Graph code we’ve added.

1.4.1 Add the dependency to app/build.gradle

Open the build.gradle file in the app module and find the following dependency:

    compile ('com.microsoft.identity.client:msal:0.1.+') {
        exclude group: 'com.android.support', module: 'appcompat-v7'
    }
    compile 'com.android.volley:volley:1.0.0'

1.4.2 Start the authentication flow

  1. Open the AuthenticationManager file and find the PublicClientApplication object declaration and then the instation in the getInstance method.

```java
private static PublicClientApplication mPublicClientApplication;
….

public static synchronized AuthenticationManager getInstance() {
    if (INSTANCE == null) {
        INSTANCE = new AuthenticationManager();
        if (mPublicClientApplication == null) {
            mPublicClientApplication = new PublicClientApplication(Connect.getInstance());
        }
    }
    return INSTANCE;
}

```

  1. In the ConnectActivity class, locate the event handler for the click event of the mConnectButton. Find the onClick method and review relevant code.

    The connect method enables personally identifyable information (PII) logging, gets an instance of the sample helper class AuthenticationManager, and gets the MSAL platform object users collection. If there are no users, the new user is taken to the Azure AD authentication and authorization flow. Otherwise, an authentication token is obtained silently.

```java
@Override
public void onClick(View view) {
….
connect();
}

    private void connect() {

    if (mEnablePiiLogging) {
        Logger.getInstance().setEnablePII(true);
    } else {
        Logger.getInstance().setEnablePII(false);
    }

    AuthenticationManager mgr = AuthenticationManager.getInstance();

    List<User> users = null;

    try {
        users = mgr.getPublicClient().getUsers();

        if (users != null && users.size() == 1) {
            mUser = users.get(0);
            mgr.callAcquireTokenSilent(mUser, true, this);
        } else {
            mgr.callAcquireToken(
                    this,
                    this);
        }
    } catch (MsalClientException e) {
        Log.d(TAG, "MSAL Exception Generated while getting users: " + e.toString());

    } catch (IndexOutOfBoundsException e) {
        Log.d(TAG, "User at this position does not exist: " + e.toString());
    }
}

```

  1. Find the event handler that processes the Azure AD redirect response generated by Azure AD when the user closes the authintication dialog. This handler is in the ConnectActivity class.

```java
/**
* Handles redirect response from https://login.microsoftonline.com/common and
* notifies the MSAL library that the user has completed the authentication
* dialog
* @param requestCode
* @param resultCode
* @param data
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (AuthenticationManager
.getInstance()
.getPublicClient() != null) {
AuthenticationManager
.getInstance()
.getPublicClient()
.handleInteractiveRequestRedirect(requestCode, resultCode, data);
}
}

```

  1. Find the authentication callback method that caches the authentication token that is used in Graph API calls.
    /* Callback used for interactive request.  If succeeds we use the access
         * token to call the Microsoft Graph. Does not check cache
         */
    private AuthenticationCallback getAuthInteractiveCallback() {
        return new AuthenticationCallback() {
            @Override
            public void onSuccess(AuthenticationResult authenticationResult) {
            /* Successfully got a token, call graph now */
                Log.d(TAG, "Successfully authenticated");
                Log.d(TAG, "ID Token: " + authenticationResult.getIdToken());

            /* Store the auth result */
                mAuthResult = authenticationResult;
                if (mActivityCallback != null)
                    mActivityCallback.onSuccess(mAuthResult);
            }

            @Override
            public void onError(MsalException exception) {
            /* Failed to acquireToken */
                Log.d(TAG, "Authentication failed: " + exception.toString());
                if (mActivityCallback != null)
                    mActivityCallback.onError(exception);
            }

            @Override
            public void onCancel() {
            /* User canceled the authentication */
                Log.d(TAG, "User cancelled login.");
            }
        };
    }

The connect sample app has a Connect button on the main activity. If you press the button, on first use, the app presents an authentication page using the device’s browser. The next step is to handle the code that the authorization server sends to the redirect URI and exchange it for an access token.

1.4.3 Exchange the authorization code for an access token

You need to make your app ready to handle the authorization server response, which contains a code that you can exchange for an access token.

  1. We need to tell the Android system that Connect app can handle requests to the redirect URL configured in the application registration. To do this open the AndroidManifest file and add the following children to the projects \<application/> element.

        <uses-sdk tools:overrideLibrary="com.microsoft.identity.msal" />
        <application ...>
            ...
            <activity
                android:name="com.microsoft.identity.client.BrowserTabActivity">
                <intent-filter>
                    <action android:name="android.intent.action.VIEW" />
                    <category android:name="android.intent.category.DEFAULT" />
                    <category android:name="android.intent.category.BROWSABLE" />
                    <data android:scheme="msalENTER_YOUR_CLIENT_ID"
                        android:host="auth" />
                </intent-filter>
            </activity>
            <meta-data
                android:name="https://login.microsoftonline.com/common"
                android:value="authority string"/>
            <meta-data
                android:name="com.microsoft.identity.client.ClientId"
                android:value="ENTER_YOUR_CLIENT_ID"/>
        </application>
  2. The MSAL library needs access to the application Id assigned by the registration portal. The MSAL library refers to the application Id as the “Client Id”. It gets the application Id (Client Id) from the application context that you pass in the library constructor.

Note: You can also provide the client Id at run-time by passing a string parameter to the constructor.

  1. The activity is invoked when the authorization server sends a response. Request an access token with the response from the authorization server. Go to your AuthenticationManager and find the following code in the class.

```java
/**
* Authenticates the user and lets the user authorize the app for the requested permissions.
* An authentication token is returned via the getAuthInteractiveCalback method
* @param activity
* @param authenticationCallback
*/
public void connect(Activity activity, final MSALAuthenticationCallback authenticationCallback){
mActivityCallback = authenticationCallback;
mPublicClientApplication.acquireToken(
activity, Constants.SCOPES, getAuthInteractiveCallback());
}

 /* Callback used for interactive request.  If succeeds we use the access
     * token to call the Microsoft Graph. Does not check cache
     */
private AuthenticationCallback getAuthInteractiveCallback() {
    return new AuthenticationCallback() {
        @Override
        public void onSuccess(AuthenticationResult authenticationResult) {
        /* Successfully got a token, call graph now */
            Log.d(TAG, "Successfully authenticated");
            Log.d(TAG, "ID Token: " + authenticationResult.getIdToken());

        /* Store the auth result */
            mAuthResult = authenticationResult;
            if (mActivityCallback != null)
                mActivityCallback.onSuccess(mAuthResult);
        }

        @Override
        public void onError(MsalException exception) {
        /* Failed to acquireToken */
            Log.d(TAG, "Authentication failed: " + exception.toString());
            if (mActivityCallback != null)
                mActivityCallback.onError(exception);
        }

        @Override
        public void onCancel() {
        /* User canceled the authentication */
            Log.d(TAG, "User cancelled login.");
        }
    };
}

 /**
 * Returns the access token obtained in authentication
 *
 * @return mAccessToken
 */
public String getAccessToken() throws AuthenticatorException, IOException, OperationCanceledException {
    return  mAuthResult.getAccessToken();
}

```

1.5 Call Microsoft Graph

You can use the Microsoft Graph SDK or the Microsoft Graph REST API to call Microsoft Graph.

1.5.1 Call Microsoft Graph using the Microsoft Graph SDK

The Microsoft Graph SDK for Android provides classes that build requests and process results from Microsoft Graph. Follow these steps to use the Microsoft Graph SDK.

  1. Add Internet permissions to your app. Open the AndroidManifest file and add the following child to the manifest element.

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  2. Add dependencies to the Microsoft Graph SDK and GSON.
    gradle compile 'com.microsoft.graph:msgraph-sdk-android:1.3.2' compile 'com.google.code.gson:gson:2.7'

  3. Add authentication token to new requests using the uthenticateRequest helper method. This method implements the same method from the Microsoft Graph Authentication IAuthenticationProvider interface

java /** * Appends an access token obtained from the {@link AuthenticationManager} class to the * Authorization header of the request. * @param request */ @Override public void authenticateRequest(IHttpRequest request) { try { request.addHeader("Authorization", "Bearer " + AuthenticationManager.getInstance() .getAccessToken()); // This header has been added to identify this sample in the Microsoft Graph service. // If you're using this code for your project please remove the following line. request.addHeader("SampleID", "android-java-connect-sample"); } catch (AuthenticatorException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (OperationCanceledException e) { e.printStackTrace(); } catch (NullPointerException e) { e.printStackTrace(); } }

  1. Create a draft email and send it using the following helper methods from the GraphServiceController helper class.

```java
/**
* Creates a draft email message using the Microsoft Graph API on Office 365. The mail is sent
* from the address of the signed in user.

@param senderPreferredName The mail senders principal user name (email addr)
* @param emailAddress The recipient email address.
* @param subject The subject to use in the mail message.
* @param body The body of the message.
* @param callback The callback method to invoke on completion of the POST request
*/
public void createDraftMail(
final String senderPreferredName,
final String emailAddress,
final String subject,
final String body,
ICallback<Message> callback
) {
try {
// create the email message
Message message = createMessage(subject, body, emailAddress);
mGraphServiceClient
.getMe()
.getMessages()
.buildRequest()
.post(message, callback);

    } catch (Exception ex) {
        showException(ex, "exception on send mail","Send mail failed", "The send mail method failed");
    }
}

    /**
 * Creates a new Message object 
 */
Message createMessage(
        String subject,
        String body,
        String address) {

    if (address == null || address.isEmpty()) {
        throw new IllegalArgumentException("The address parameter can't be null or empty.");
    } else {
        // perform a simple validation of the email address
        String addressParts[] = address.split("@");
        if (addressParts.length != 2 || addressParts[0].length() == 0 || addressParts[1].indexOf('.') == -1) {
            throw new IllegalArgumentException(
                    String.format("The address parameter must be a valid email address {0}", address)
            );
        }
    }
    Message message = new Message();
    EmailAddress emailAddress = new EmailAddress();
    emailAddress.address = address;
    Recipient recipient = new Recipient();
    recipient.emailAddress = emailAddress;
    message.toRecipients = Collections.singletonList(recipient);
    ItemBody itemBody = new ItemBody();
    itemBody.content = body;
    itemBody.contentType = BodyType.html;
    message.body = itemBody;
    message.subject = subject;
    return message;
}
/**
 * Sends a draft message to the specified recipients
 *
 * @param messageId String. The id of the message to send
 * @param callback
 */
public void sendDraftMessage(String messageId,
                             ICallback<Void> callback) {
    try {

        mGraphServiceClient
                .getMe()
                .getMessages(messageId)
                .getSend()
                .buildRequest()
                .post(callback);

    } catch (Exception ex) {
        showException(ex, "exception on send draft message ","Send draft mail failed", "The send draft mail method failed");
    }
}

```

1.5.2 Call Microsoft Graph using the Microsoft Graph REST API

The Microsoft Graph REST API exposes multiple APIs from Microsoft cloud services through a single REST API endpoint. Follow these steps to use the REST API.

  1. Add Internet permissions to your app. Open the AndroidManifest file and add the following child to the manifest element.

    <uses-permission android:name="android.permission.INTERNET" />
  2. Add a dependency to the Volley HTTP library.

    compile 'com.android.volley:volley:1.0.0'
  3. Replace the line String accessToken = tokenResponse.accessToken; with the following code. Insert your email address in the placeholder marked with \<YOUR_EMAIL_ADDRESS>.
    ```java
    final String accessToken = tokenResponse.accessToken;

    final RequestQueue queue = Volley.newRequestQueue(getApplicationContext());
    String url =“https://graph.microsoft.com/v1.0/me/sendMail”;
    final String body = “{” +
    " Message: {" +
    " subject: ‘Sent using the Microsoft Graph REST API’," +
    " body: {" +
    " contentType: ‘text’," +
    " content: ‘This is the email body’" +
    " }," +
    " toRecipients: [" +
    " {" +
    " emailAddress: {" +
    " address: ‘<YOUR_EMAIL_ADDRESS>’" +
    " }" +
    " }" +
    " ]}" +
    “}”;

    final StringRequest stringRequest = new StringRequest(Request.Method.POST, url,
    new Response.Listener<String>() {
    @Override
    public void onResponse(String response) {
    Log.d(“Response”, response);
    }
    },
    new Response.ErrorListener() {
    @Override
    public void onErrorResponse(VolleyError error) {
    Log.d(“ERROR”,“error =>” + error.getMessage());
    }
    }
    ) {
    @Override
    public Map<String, String> getHeaders() throws AuthFailureError {
    Map<String,String> params = new HashMap<>();
    params.put(“Authorization”, “Bearer” + accessToken);
    params.put(“Content-Length”, String.valueOf(body.getBytes().length));
    return params;
    }
    @Override
    public String getBodyContentType() {
    return “application/json”;
    }
    @Override
    public byte[] getBody() throws AuthFailureError {
    return body.getBytes();
    }
    };

    AsyncTask.execute(new Runnable() {
    @Override
    public void run() {
    queue.add(stringRequest);
    }
    });
    ```

1.6 Run the app

You’re ready to try your Android app.

  1. Start your Android emulator or connect your physical device to your computer.
  2. In Android Studio, press Shift + F10 to run your app.
  3. Choose your Android emulator or device from the deployment dialog box.
  4. Tap the Floating Action Button on the main activity.
  5. Sign in with your personal or work or school account and grant the requested permissions.
  6. In the app selection dialog, tap your app to continue.

Check the inbox of the email address that you configured in Call Microsoft Graph. You should have an email from the account that you used to sign in to the app.

1.7 Next steps

1.8 See also

This article describes the tasks required to get an access token from the Azure AD v2.0 endpoint and call Microsoft Graph. It walks you through building the Microsoft Connect Sample for AngularJS and explains the main concepts that you implement to use Microsoft Graph. The article also describes how to access Microsoft Graph by using either the Microsoft Graph JavaScript SDK or raw REST calls.

The following image shows the app you’ll create.

The web app after login showing the Send mail button

Don’t feel like building an app? Use the Microsoft Graph quick start to get up and running fast.

To download a version of the Connect sample that uses the Azure AD endpoint, see Microsoft Graph Connect Sample for AngularJS.

1.9 Prerequisites

To get started, you’ll need:

1.10 Register the application

Register an app on the Microsoft App Registration Portal. This generates the app ID and password that you’ll use to configure the app in Visual Studio.

  1. Sign into the Microsoft App Registration Portal using either your personal or work or school account.

  2. Choose Add an app.

  3. Enter a name for the app, and choose Create application.

    The registration page displays, listing the properties of your app.

  4. Copy the application ID. This is the unique identifier for your app that you’ll use to configure the app.

  5. Under Platforms, choose Add Platform > Web.

  6. Make sure the Allow Implicit Flow check box is selected, and enter *http://localhost:8080* as the Redirect URI.

  7. Choose Save.

1.11 Configure the project

  1. Open the starter-project folder in the sample files.
  2. In a command prompt, run the following commands in the root directory of the starter project. This installs the project dependencies.

    npm install  
    bower install
  3. In the starter project files, in the public/scripts folder, open config.js.
  4. In the clientID field, replace the ENTER_YOUR_CLIENT_ID placeholder value with the application ID you just copied.

1.12 Call Microsoft Graph with the SDK

The app calls Microsoft Graph to get user information and to send an email on the user’s behalf. These calls are initiated from the MainController in response to UI events.

Open app.js and add the following code to the bottom of the file. This initializes the SDK.

var authToken;
var graphClient = MicrosoftGraph.Client.init({
    authProvider: function(done) {
    if (typeof authToken === "undefined") {
      done({err: "No auth token"})
    } else {
      done(null, authToken); //first parameter takes an error if you can't get an access token
    }
    }
});

1.12.1 Using the SDK

  1. In graphHelper.js, replace // Get the profile of the current user with the following code. This configures and sends the GET request to the /me endpoint, and processes the response.

    // Get the profile of the current user.
    me: function me() {
      return graphClient.api('/me').get();
    },
  2. Replace // Send an email on behalf of the current user with the following code. This configures and sends the POST request to the /me/sendMail endpoint, and processes the response.

    // Send an email on behalf of the current user.
    sendMail: function sendMail(email) {
      return graphClient.api('/me/sendMail').post({ 'message' : email, 'saveToSentItems': true });
    }
  3. In the public/controllers folder, open mainController.js.

  4. Replace // Set the default headers and user properties with the following code. This adds the access token to the HTTP request, calls GraphHelper.me to get the current user’s profile, and processes the response.

    // Set the default headers and user properties.
    function processAuth() {
    
    // let the authProvider access the access token
    authToken = localStorage.token;
    
    if (localStorage.getItem('user') === null) {
    
      // Get the profile of the current user.
      GraphHelper.me().then(function(user) {
    
        // Save the user to localStorage.
        localStorage.setItem('user', angular.toJson(user));
    
        vm.displayName = user.displayName;
        vm.emailAddress = user.mail || user.userPrincipalName;
      });
    } else {
      let user = angular.fromJson(localStorage.user);
    
      vm.displayName = user.displayName;
      vm.emailAddress = user.mail || user.userPrincipalName;
    }
    
    }
  5. Replace // Send an email on behalf of the current user with the following code. This builds the email message, calls GraphHelper.sendMail, and processes the response.

    // Send an email on behalf of the current user.
    function sendMail() {
    
      authToken = localStorage.token;       
    
      // Build the HTTP request payload (the Message object).
      var email = {
      Subject: 'Welcome to Microsoft Graph development with Angular and the Microsoft Graph Connect sample',
      Body: {
        ContentType: 'HTML',
        Content: getEmailContent()
      },
      ToRecipients: [
        {
          EmailAddress: {
        Address: vm.emailAddress
          }
        }
      ]
      };
    
      // Save email address so it doesn't get lost with two way data binding.
      vm.emailAddressSent = vm.emailAddress;
      GraphHelper.sendMail(email)
    .then(function (response) {
      $log.debug('HTTP request to the Microsoft Graph API returned successfully.', response);
      vm.requestSuccess = true;
      vm.requestFinished = true;
      $scope.$apply();
    }, function (error) {
      $log.error('HTTP request to the Microsoft Graph API failed.');
      vm.requestSuccess = false;
      vm.requestFinished = true;
      $scope.$apply();
    });
    
    };
  6. Save all your changes.

1.13 Run the app

  1. In a command prompt, run the following command in the root directory of the starter project.

    npm start
  2. In a browser, navigate to *http://localhost:8080* and choose the Connect button.

  3. Sign in and grant the requested permissions.

  4. Optionally edit the recipient’s email address, and then choose the Send mail button. When the mail is sent, a Success message is displayed below the button.

1.14 Next steps

1.15 See also

2 Get started with Microsoft Graph in an ASP.NET 4.6 MVC app

This article describes the tasks required to get an access token from the Azure AD v2.0 endpoint and call Microsoft Graph. It walks you through building the Microsoft Graph Connect Sample for ASP.NET 4.6 and explains the main concepts that you implement to use Microsoft Graph.

The following image shows the app you’ll create.

The web app with Get email address and Send email buttons

The Azure AD v2.0 endpoint lets users sign in with a Microsoft account (MSA) or a work or school account. The app uses the ASP.Net OpenID Connect OWIN middleware and the Microsoft Authentication Library (MSAL) for .NET for sign in and token management.

Don’t feel like building an app? Use the Microsoft Graph quick start to get up and running fast. Also note that we have a REST version of this sample.

2.1 Prerequisites

To get started, you’ll need:

2.2 Register the application

In this step, you’ll register an app on the Microsoft App Registration Portal. This generates the app ID and password that you’ll use to configure the app in Visual Studio.

  1. Sign into the Microsoft App Registration Portal using either your personal or work or school account.

  2. Choose Add an app.

  3. Enter a name for the app, and choose Create application.

    The registration page displays, listing the properties of your app.

  4. Copy the application ID. This is the unique identifier for your app.

  5. Under Application Secrets, choose Generate New Password. Copy the password from the New password generated dialog.

    You’ll use the application ID and password to configure the app.

  6. Under Platforms, choose Add platform > Web.

  7. Make sure the Allow Implicit Flow check box is selected, and enter *http://localhost:55065/* as the Redirect URI.

    The Allow Implicit Flow option enables the OpenID Connect hybrid flow. During authentication, this enables the app to receive both sign-in info (the id_token) and artifacts (in this case, an authorization code) that the app uses to obtain an access token.

  8. Choose Save.

2.2.1 Configure the project

  1. Open the solution file for the starter project in Visual Studio.

  2. Open the project’s Web.config file.

  3. Locate the app configuration keys in the appSettings element. Replace the ENTER_YOUR_CLIENT_ID and ENTER_YOUR_SECRET placeholder values with the values you just copied.

The redirect URI is the URL of the project that you registered. The requested permission scopes allow the app to get user profile information and send an email.

2.3 Call Microsoft Graph

In this step, you’ll focus on the SDKHelper, GraphService, and HomeController classes.

  • SDKHelper intializes an instance of the GraphServiceClient from the library before each call to the Microsoft Graph. This is when the access token is added to the request.
  • GraphService builds and sends requests to the Microsoft Graph using the library, and processes the responses.
  • HomeController contains actions that initiate the calls to the library in response to UI events.

The starter project already declares a dependency for the Microsoft Graph .NET Client Library NuGet package: Microsoft.Graph.

  1. Right-click the Helpers folder and choose Add > Class.

  2. Name the new class SDKHelper and choose Add.

  3. Replace the contents with the following code.

    using System.Net.Http.Headers;
    using Microsoft.Graph;
    
    namespace Microsoft_Graph_SDK_ASPNET_Connect.Helpers
    {
        public class SDKHelper
        {   
            private static GraphServiceClient graphClient = null;
    
            // Get an authenticated Microsoft Graph Service client.
            public static GraphServiceClient GetAuthenticatedClient()
            {
                GraphServiceClient graphClient = new GraphServiceClient(
                    new DelegateAuthenticationProvider(
                        async (requestMessage) =>
                        {
                            string accessToken = await SampleAuthProvider.Instance.GetUserAccessTokenAsync();
    
                            // Append the access token to the request.
                            requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", accessToken);
                        }));
                return graphClient;
            }
    
            public static void SignOutClient()
            {
                graphClient = null;
            }
        }
    }

Note the call to SampleAuthProvider to get the token when the client is initialized.

  1. In the Models folder, open GraphService.cs. The service uses the library to interact with the Microsoft Graph.

  2. Add the following using statement.

    using Microsoft.Graph;
  3. Replace // GetMyEmailAddress with the following method. This gets the current user’s email address.

    // Get the current user's email address from their profile.
    public async Task<string> GetMyEmailAddress(GraphServiceClient graphClient)
    {
    
        // Get the current user. 
        // The app only needs the user's email address, so select the mail and userPrincipalName properties.
        // If the mail property isn't defined, userPrincipalName should map to the email for all account types. 
        User me = await graphClient.Me.Request().Select("mail,userPrincipalName").GetAsync();
        return me.Mail ?? me.UserPrincipalName;
    }

Note the Select segment, which requests only the mail and userPrinicipalName to be returned. You can use Select and Filter to reduce the size of the response data payload.

  1. Replace // SendEmail with the following methods to build and send the email.

    // Send an email message from the current user.
    public async Task SendEmail(GraphServiceClient graphClient, Message message)
    {
        await graphClient.Me.SendMail(message, true).Request().PostAsync();
    }
    
    public async Task<Message> BuildEmailMessage(GraphServiceClient graphClient, string recipients, string subject)
    {
    
        // Get current user photo
        Stream photoStream = await GetCurrentUserPhotoStreamAsync(graphClient);
    
    
        // If the user doesn't have a photo, or if the user account is MSA, we use a default photo
    
        if ( photoStream == null)
        {
            photoStream = System.IO.File.OpenRead(System.Web.Hosting.HostingEnvironment.MapPath("/Content/test.jpg"));
        }
    
        MemoryStream photoStreamMS = new MemoryStream();
        // Copy stream to MemoryStream object so that it can be converted to byte array.
        photoStream.CopyTo(photoStreamMS);
    
        DriveItem photoFile = await UploadFileToOneDrive(graphClient, photoStreamMS.ToArray());
    
        MessageAttachmentsCollectionPage attachments = new MessageAttachmentsCollectionPage();
        attachments.Add(new FileAttachment
        {
            ODataType = "#microsoft.graph.fileAttachment",
            ContentBytes = photoStreamMS.ToArray(),
            ContentType = "image/png",
            Name = "me.png"
        });
    
        Permission sharingLink = await GetSharingLinkAsync(graphClient, photoFile.Id);
    
        // Add the sharing link to the email body.
        string bodyContent = string.Format(Resource.Graph_SendMail_Body_Content, sharingLink.Link.WebUrl);
    
        // Prepare the recipient list.
        string[] splitter = { ";" };
        string[] splitRecipientsString = recipients.Split(splitter, StringSplitOptions.RemoveEmptyEntries);
        List<Recipient> recipientList = new List<Recipient>();
        foreach (string recipient in splitRecipientsString)
        {
            recipientList.Add(new Recipient
            {
                EmailAddress = new EmailAddress
                {
                    Address = recipient.Trim()
                }
            });
        }
    
        // Build the email message.
        Message email = new Message
        {
            Body = new ItemBody
            {
                Content = bodyContent,
                ContentType = BodyType.Html,
            },
            Subject = subject,
            ToRecipients = recipientList,
            Attachments = attachments
        };
        return email;
    }
    
    // Gets the stream content of the signed-in user's photo. 
    // This snippet doesn't work with consumer accounts.
    public async Task<Stream> GetCurrentUserPhotoStreamAsync(GraphServiceClient graphClient)
    {
        Stream currentUserPhotoStream = null;
    
        try
        {
            currentUserPhotoStream = await graphClient.Me.Photo.Content.Request().GetAsync();
    
        }
    
        // If the user account is MSA (not work or school), the service will throw an exception.
        catch (ServiceException)
        {
            return null;
        }
    
        return currentUserPhotoStream;
    
    }
    
    // Uploads the specified file to the user's root OneDrive directory.
    public async Task<DriveItem> UploadFileToOneDrive(GraphServiceClient graphClient, byte[] file)
    {
        DriveItem uploadedFile = null;
    
        try
        {
            MemoryStream fileStream = new MemoryStream(file);
            uploadedFile = await graphClient.Me.Drive.Root.ItemWithPath("me.png").Content.Request().PutAsync<DriveItem>(fileStream);
    
        }
    
    
        catch (ServiceException)
        {
            return null;
        }
    
        return uploadedFile;
    }
    
    public static async Task<Permission> GetSharingLinkAsync(GraphServiceClient graphClient, string Id)
    {
        Permission permission = null;
    
        try
        {
            permission = await graphClient.Me.Drive.Items[Id].CreateLink("view").Request().PostAsync();
        }
    
        catch (ServiceException)
        {
            return null;
        }
    
        return permission;
    }
  2. In the Controllers folder, open HomeController.cs.

  3. Add the following using statement.

    using Microsoft.Graph;
  4. Replace // Controller actions with the following actions.

    [Authorize]
    // Get the current user's email address from their profile.
    public async Task<ActionResult> GetMyEmailAddress()
    {
        try
        {
    
            // Initialize the GraphServiceClient.
            GraphServiceClient graphClient = SDKHelper.GetAuthenticatedClient();
    
            // Get the current user's email address. 
            ViewBag.Email = await graphService.GetMyEmailAddress(graphClient);
            return View("Graph");
        }
        catch (ServiceException se)
        {
            if (se.Error.Message == Resource.Error_AuthChallengeNeeded) return new EmptyResult();
            return RedirectToAction("Index", "Error", new { message = Resource.Error_Message + Request.RawUrl + ": " + se.Error.Message });
        }
    }
    
    [Authorize]
    // Send mail on behalf of the current user.
    public async Task<ActionResult> SendEmail()
    {
        if (string.IsNullOrEmpty(Request.Form["email-address"]))
        {
            ViewBag.Message = Resource.Graph_SendMail_Message_GetEmailFirst;
            return View("Graph");
        }
    
        try
        {
    
            // Initialize the GraphServiceClient.
            GraphServiceClient graphClient = SDKHelper.GetAuthenticatedClient();
    
            // Build the email message.
            Message message = await graphService.BuildEmailMessage(graphClient, Request.Form["recipients"], Request.Form["subject"]);
    
            // Send the email.
            await graphService.SendEmail(graphClient, message);
    
            // Reset the current user's email address and the status to display when the page reloads.
            ViewBag.Email = Request.Form["email-address"];
            ViewBag.Message = Resource.Graph_SendMail_Success_Result;
            return View("Graph");
        }
        catch (ServiceException se)
        {
            if (se.Error.Code == Resource.Error_AuthChallengeNeeded) return new EmptyResult();
            return RedirectToAction("Index", "Error", new { message = Resource.Error_Message + Request.RawUrl + ": " + se.Error.Message });
        }
    }

Now you’re ready to run the app.

2.4 Run the app

  1. Press F5 to build and run the app.

  2. Sign in with your personal or work or school account and grant the requested permissions.

  3. Choose the Get email address button. When the operation completes, the email address of the signed-in user is displayed on the page.

  4. Optionally edit the recipient list and email subject, and then choose the Send email button. When the mail is sent, a Success message is displayed below the button.

2.5 Next steps

2.6 See also

3 Associate your Office 365 account with Azure AD to create and manage apps

To authenticate your applications using Microsoft Azure Active Directory (Azure AD), you need to register them in Azure AD. This is where Office 365 user account and application information is stored. To manage Azure AD through the Azure Management Portal, you need a Microsoft Azure subscription. You can use the management portal in Microsoft Azure to manage users, roles, and apps.

This article shows you how to associate your Office 365 account with Azure AD to create and manage apps.

Note: This article uses Azure AD as the authentication provider for your app. If you’re using the Azure AD v2.0 endpoint, you don’t need to perform this step. For more information, see App authentication with Microsoft Graph.

3.1 Prerequisites

Office 365 for business account

If you don’t have an existing Office 365 for business account, you can:

Microsoft Azure subscription

  • If you can have an existing Microsoft Azure subscription, you can associate your Office 365 for business subscription with it.

  • Otherwise, you’ll need to create a new Azure subscription and associate it with your Office 365 account in order to register and manage apps.

<!—<a name=“bk_AssociateExistingAzureSubscription”> </a>–>

3.2 To associate an existing Azure subscription with your Office 365 account

  1. Log on to the Microsoft Azure Management portal with your existing Azure credentials (for example, your Microsoft ID such as ).

  2. Select the Active Directory node, then select the Directory tab and, at the bottom of the screen, select New.

  3. On the New menu, select Active Directory > Directory > Custom Create.

  4. In Add directory, in the Directory dropdown box, select Use existing directory. Check I am ready to be signed out, and then select the check mark in the lower-right corner.

    This brings you back to the Azure Management Portal.

  5. Log in with your Office 365 account information.

    You will be prompted whether to use your directory with Azure.

    Important: To associate your Office 365 account with Azure AD, you’ll need an Office 365 business account with global administrator privileges.

  6. Select continue, and then Sign out now.

  7. Close the browser and reopen the portal. Otherwise, you will get an access denied error.

  8. Log on again with your existing Azure credentials (for example, your Microsoft ID such as ). Go to the Active Directory node and, under Directory, you should now see your Office 365 account listed.

<!–<a name=“bk_AssociateNewAzureSubscription”> </a>–>

3.3 To create a new Azure subscription and associate it with your Office 365 account

  1. Log on to Office 365. From the Home page, select the Admin icon to open the Office 365 admin center.
  2. In the menu page along the left side of the page, scroll down to Admin and select Azure AD.

    Important: To open the Office 365 admin center, and access Azure AD, you’ll need an Office 365 business account with global administrator privileges.

  3. Create a new subscription.

    If you’re using a trial version of Office 365, you’ll see a message telling you that Azure AD is limited to customers with paid services. You can still create a trial 30-day Azure subscription at no charge, but you’ll need to perform a few extra steps:

    1. Select your country or region, and then choose Azure subscription.
    2. Enter your personal information. For verification purposes, enter a telephone number at which you can be reached, and specify whether you want to be sent a text message or called.
    3. When you receive your verification code, enter it and choose Verify code.
    4. Enter payment information, check the agreement, and select Sign up.

      Your credit card will not be charged.

      Do not close or refresh your browser while your Azure subscription is being created.

  4. When your Azure subscription is created, choose Portal.

  5. The Azure Tour appears. You can view it, or choose X to close it.

    You should now see all items in your Azure subscription. It lists a directory with the name of your Office 365 tenant.

3.4 See also

Note: This topic applies only to Microsoft Cloud Solution Provider (CSP) application developers. The Microsoft Cloud Solution Provider (CSP) program enables Microsoft’s partners to resell and manage Microsoft Online services to customers.

This topic describes how to enable application access to partner-managed customer data via Microsoft Graph using either the authorization code grant flow or the service to service client credentials flow.

Important: Calling Microsoft Graph from a CSP application is only supported for directory resources (such as user, group,device, organization) and Intune resources.

3.5 What is a partner-managed application

The CSP program enables Microsoft’s partners to resell and manage Microsoft Online Services (such as Office 365, Microsoft Azure, and CRM Online) to customers. Management of customer services is done through Delegated Admin Privileges, which enables designated partner users (known as agents) to access and configure their customers’ environments.

Additionally, as a partner developer, you can build a partner-managed app to manage your customers’ Microsoft services. Partner-managed apps are often called pre-consented apps because all your customers are automatically pre-consented for your partner-managed apps. This means when a user from one of your customer tenants uses one of your partner-managed apps, the user can use it without being prompted to give consent. Partner-managed apps also inherit Delegated Admin Privileges, so your partner agents can also get privileged access to your customers through your partner-managed application.

3.6 How to set-up a partner-managed application

An application is viewed as partner-managed when it is granted elevated permissions to access your customers’ data.

Note: Partner-managed apps can only be configured on Partner tenants, and in order to manage customer tenant resources, partner-managed apps must be configured as multi-tenant applications.

3.6.1 Register and configure a multi-tenant app

The initial steps required here follow most of the same steps used to register and configure a multi-tenant application:

  1. Register your application in your Partner tenant using the Azure Portal. To function as a partner-managed app, an application must be configured as a multi-tenant app. Additionally, if your app is deployed and sold in multiple geographic regions you will need to register your app in each of those regions as described <a href=“#region”>here</a>.
  2. Configure your multi-tenant app, again through the Azure Portal, with the required permissions it needs using a least privileged approach.

Finally grant your partner-managed app those configured permissions for all your customers. You can do this by adding the servicePrincipal that represents the app to the Adminagents group in your Partner tenant, using Azure AD powershell V2. You can download and install Azure AD PowerShell V2 from here. Follow these steps to find the Adminagents group, the servicePrincipal and add it to the group.

  1. Open a PowerShell session and connect to your partner tenant by entering your admin credentials into the sign-in window.

    Connect-AzureAd
  2. Find the group that represents the Adminagents.

    $group = Get-AzureADGroup -Filter "displayName eq 'Adminagents'"
  3. Find the service principal that has the same appId as your app.

    $sp = Get-AzureADServicePrincipal -Filter "appId eq '{yourAppsAppId}'"
  4. Finally, add the service principal to the Adminagents group.

    Add-AzureADGroupMember -ObjectId $group.ObjectId -RefObjectId $sp.ObjectId

3.7 Token acquisition flows

Token acquisition flows for partner-managed apps - authorization code grant flow and service-to-service client credentials flow - are the same as regular multi-tenant apps.

Apart from pre-consented access to all your customer tenants, partner-managed apps have one additional capability. It allows for your agents to use your app to access your customers’ tenant data (using delegated admin privileges). Conceptually it works like this:

  1. Your agent signs in to your app with their user credentials issued from your partner tenant.
  2. Your app requests an access token for the intended partner-managed customer tenant.
  3. Your app uses the access token to call Microsoft Graph.

This is a standard authorization code grant flow, except that your agents must sign-in using their partner accounts. To see how this would look, imagine your partner tenant is partner.com (which is the home tenant for your agents) and one of your customers is customer.com:

  1. Acquire an authorization code: Your app makes a request to the /authorize endpoint and must use a customer tenant, in our example customer.com, for the target tenant. Your agents would still sign-in with their username@partner.com account.

    GET https://login.microsoftonline.com/customer.com/oauth2/authorize
  2. Aquire an access token using the authorization code: Your app must use a customer tenant as the target tenant, in our example customer.com, when making the request to the token endpoint:

    POST https://login.microsoftonline.com/customer.com/oauth2/token
  3. Now you have an access token, call Microsoft Graph, putting the access token in the HTTP authorization header:

    GET https://graph.microsoft.com/beta/users
    Authorization: Bearer <token>

3.8 Register your app in the regions you support

<a name=“region”></a>

CSP customer engagement is currently limited to a single region. Partner-managed applications carry the same limitation. This means you must have a separate tenant for each region you sell in. For example, if your partner-managed app is registered in a tenant in the US but your customer is in the EU – the partner-managed app will not work. Each of your regional partner tenants must maintain their own set of partner-managed apps to manage customers within the same region. This might require additional logic in your app (prior to sign-in) to get your customers’ sign-in username to decide which region-specific partner-managed app identity to use, to serve the user.

3.9 Calling Microsoft Graph immediately after customer creation

When you create a new customer using the Partner Center API, a new customer tenant gets created. Additionally, a partner relationship also gets created, which makes you the partner of record for this new customer tenant. This partner relationship can take up to 3 minutes to propagate to the new customer tenant. If your app calls Microsoft Graph straight after creation, your app will likely receive an access denied error. A similar delay may be experienced when an existing customer accepts your invitation. This is because pre-consent relies on the partner relationship being present in the customer tenant.

To avoid this problem, we recommend that your partner app should should wait three minutes after customer creation before calling Azure AD to acquire a token (to call Microsoft Graph). This should cover most cases.
However, if after waiting three minutes you still recieve an authorization error, please wait an additional 60 seconds and try again.

Note: On the retry, you must acquire a new access token from Azure AD, before calling Microsoft Graph. Calling Microsoft Graph with the access token you already have will not work, because the access token is good for an hour and won’t contain the pre-consented permission claims.

# Get access tokens to call Microsoft Graph

To call Microsoft Graph, your app must acquire an access token from Azure Active Directory (Azure AD), Microsoft’s cloud identity service. The access token contains information (or claims) about your app and the permissions it has for the resources and APIs available through Microsoft Graph. To get an access token, your app must be able to authenticate with Azure AD and be authorized by either a user or an administrator for access to the Microsoft Graph resources it needs.

This topic provides an overview of access tokens, Azure AD, and how your app can get access tokens. If you are already familiar with integrating an app with Azure AD to get tokens, then you can skip ahead to Next Steps for information and samples specific to Microsoft Graph.

3.10 What is an access token and how do I use it?

Access tokens issued by Azure AD are base 64 encoded JSON Web Tokens (JWT). They contain information (claims) that web APIs secured by Azure AD, like Microsoft Graph, use to validate the caller and to ensure that the caller has the proper permissions to perform the operation they’re requesting. When calling Microsoft Graph, you can treat access tokens as opaque. You should always transmit access tokens over a secure channel, such as transport layer security (HTTPS).

Here’s an example of an Azure AD access token:

EwAoA8l6BAAU7p9QDpi/D7xJLwsTgCg3TskyTaQAAXu71AU9f4aS4rOK5xoO/SU5HZKSXtCsDe0Pj7uSc5Ug008qTI+a9M1tBeKoTs7tHzhJNSKgk7pm5e8d3oGWXX5shyOG3cKSqgfwuNDnmmPDNDivwmi9kmKqWIC9OQRf8InpYXH7NdUYNwN+jljffvNTewdZz42VPrvqoMH7hSxiG7A1h8leOv4F3Ek/oeJX6U8nnL9nJ5pHLVuPWD0aNnTPTJD8Y4oQTp5zLhDIIfaJCaGcQperULVF7K6yX8MhHxIBwek418rKIp11om0SWBXOYSGOM0rNNN59qNiKwLNK+MPUf7ObcRBN5I5vg8jB7IMoz66jrNmT2uiWCyI8MmYDZgAACPoaZ9REyqke+AE1/x1ZX0w7OamUexKF8YGZiw+cDpT/BP1GsONnwI4a8M7HsBtDgZPRd6/Hfqlq3HE2xLuhYX8bAc1MUr0gP9KuH6HDQNlIV4KaRZWxyRo1wmKHOF5G5wTHrtxg8tnXylMc1PKOtaXIU4JJZ1l4x/7FwhPmg9M86PBPWr5zwUj2CVXC7wWlL/6M89Mlh8yXESMO3AIuAmEMKjqauPrgi9hAdI2oqnLZWCRL9gcHBida1y0DTXQhcwMv1ORrk65VFHtVgYAegrxu3NDoJiDyVaPZxDwTYRGjPII3va8GALAMVy5xou2ikzRvJjW7Gm3XoaqJCTCExN4m5i/Dqc81Gr4uT7OaeypYTUjnwCh7aMhsOTDJehefzjXhlkn//2eik+NivKx/BTJBEdT6MR97Wh/ns/VcK7QTmbjwbU2cwLngT7Ylq+uzhx54R9JMaSLhnw+/nIrcVkG77Hi3neShKeZmnl5DC9PuwIbtNvVge3Q+V0ws2zsL3z7ndz4tTMYFdvR/XbrnbEErTDLWrV6Lc3JHQMs0bYUyTBg5dThwCiuZ1evaT6BlMMLuSCVxdBGzXTBcvGwihFzZbyNoX+52DS5x+RbIEvd6KWOpQ6Ni+1GAawHDdNUiQTQFXRxLSHfc9fh7hE4qcD7PqHGsykYj7A0XqHCjbKKgWSkcAg==

To call Microsoft Graph, you attach the access token as a Bearer token to the Authorization header in an HTTP request. For example, here’s a call that returns the profile information of the signed-in user (the access token has been truncated for readability):

HTTP/1.1
Authorization: Bearer EwAoA8l6BAAU ... 7PqHGsykYj7A0XqHCjbKKgWSkcAg==
Host: graph.microsoft.com`
GET https://graph.microsoft.com/v1.0/me/

3.11 What are Microsoft Graph permissions?

Microsoft Graph exposes a rich set of granular permissions over the resources it controls. These permissions are expressed as strings and grant apps access to Microsoft Graph resources like users, groups, user mail, etc. For example:

  • User.Read allows an app to read the profile of the signed-in user.
  • Mail.Send allows an app to send mail on behalf of the signed-in user.

There are two types of permissions:

  • Delegated permissions are used by apps that run with a user present. The user’s privileges are delegated to the app which makes calls on behalf of the user to Microsoft Graph. Many of these permissions can be consented to by a user, but others require administrator consent.
  • Application permissions are used by apps that run without a user. These often grant an app broad privileges within an organization and always require the consent of an administrator.

For a complete list of Microsoft Graph permissions, as well as the differences between delegated and application permissions, see the Permissions reference.

3.12 Where does my app get an access token?

Your app gets access tokens from Azure Active Directory (Azure AD), Microsoft’s cloud identity service. To get an access token, your app exchanges HTTP requests and responses with Azure AD using industry-standard protocols defined in the OAuth 2.0 and OpenID Connect 1.0 specifications. These protocols describe the Azure AD endpoints and exchanges with them – or authentication flows – that your app uses to securely authenticate with Azure AD and get access tokens.

On a very simple level, to get an access token, your app exchanges HTTP requests with the following endpoints:

  • The /authorize endpoint, where your app can send a user to authenticate with Azure AD and consent to the permissions your app needs.
  • The /token endpoint where your app can get an access token once user consent has been granted.

(Note: These definitions are not rigid. Depending on the protocol your app uses, it may get access tokens directly from the /authorize endpoint or it may authenticate directly with the /token endpoint.)

Here’s an example of one set of the /authorize and /token endpoints exposed by Azure AD v2.0:

https://login.microsoftonline.com/common/oauth2/v2.0/authorize
https://login.microsoftonline.com/common/oauth2/v2.0/token

Azure AD exposes two sets of endpoints, Azure AD and Azure AD v2.0. The main difference between them is that Azure AD endpoint supports only work or school accounts (that is, accounts that are associated with an Azure AD tenant), while Azure AD v2.0 also supports Microsoft accounts like Live.com or outlook.com accounts. This means that if you use the Azure AD endpoint, your app can target only organizations, but with Azure AD v2.0 it can target both consumers and organizations.

Tokens from the Azure AD endpoint are not interchangeable with those from the Azure AD v2.0 endpoint, so before you begin work on an app for production, you must choose between the endpoints. Because the Azure AD v2.0 endpoint is newer and features are still being added, there are some important limitations that you need to factor into your decision about which endpoint to use for your app in production. For more information, see Deciding between the Azure AD and Azure AD v2.0 endpoints.

3.13 What’s the difference between OAuth 2.0 and OpenID Connect?

OAuth 2.0 is an authorization protocol. It defines how your app can get access tokens by authenticating directly with Azure AD or by redirecting a user to authenticate with Azure AD and consent to the permissions your app requests. In the first case, your app gets an access token that it can use to call Microsoft Graph as itself. In second case, your app gets an access token that it can use to call Microsoft Graph on behalf of a user. With OAuth 2.0, however, your app does not receive any information about the user or how they were authenticated by Azure AD. OAuth 2.0 flows are most often used by mobile or native apps, which already know the identity of the user; or by apps like background services or daemons, which call Microsoft Graph under their own identity and not on behalf of a user.

OpenID Connect extends OAuth 2.0 to provide an identity layer. With OpenID Connect, in addition to an access token, your app can also get an id token from Azure AD. OpenID Connect id tokens contain claims about the user’s identity and details about how and where they were authenticated. OpenID Connect flows are typically used by web apps, including single page apps (SPAs). These apps can use the id token to customize their behavior for the user they’ve requested an access token for, and, in many cases, will outsource sign-in of their users to Azure AD and enable experiences like Single Sign-on (SSO).

3.14 What kind of apps can I call Microsoft Graph from?

You can call Microsoft Graph from the following kinds of apps:

  • Native apps: Apps that run on a device such as a desktop, tablet, or mobile phone. These apps use the operating system (OS) native to the device like iOS, Android, or Windows for user presentation and to make calls to Microsoft Graph on behalf of a user.
  • Web apps: Apps that run on a server and interact with the signed-in user through a user-agent, usually a web browser. Most of the presentation layer is handled on the server, and calls to Microsoft Graph are made from the server-side on behalf of a user.
  • Single Page Apps (SPA): Web apps with rich user experiences that handle much of the presentation layer through client-side scripting in the browser. Calls to Microsoft Graph are made from client-side script using technologies like AJAX and frameworks like Angular.js. Calls are made on behalf of a user.
  • Background Services/Daemons: Background services and daemons that run on a server without the presence of a user and make calls to Microsoft Graph under their own identity.
  • Web APIs: A client app calls a web API (secured by Azure AD), which then calls Microsoft Graph, all on behalf of a user. Supported by the Azure AD endpoint. For the Azure AD v2.0 endpoint, only supported if the client and the web API have the same Application ID; for example, a native app that calls a web API back end.

3.15 How do I get my app talking to Azure AD and Microsoft Graph?

Before your app can get a token from Azure AD, it must be registered. For the Azure AD v2.0 endpoint, you use the Microsoft App Registration Portal to register your app. For the Azure AD endpoint, you use the Azure portal. Registration integrates your app with Azure AD and establishes the coordinates and identifiers that it uses to get tokens. These are:

  • Application ID: A unique identifier assigned by Azure AD.
  • Redirect URI/URL: One or more endpoints at which your app will receive responses from Azure AD. (For native and mobile apps this is a URI assigned by Azure AD.)
  • Application Secret: A password or a public/private key pair that your app uses to authenticate with Azure AD. (Not needed for native or mobile apps.)

For apps that use the Azure AD endpoint, you’ll also pre-configure the Microsoft Graph permissions that your app needs during registration. For apps that use the Azure AD v2.0 endpoint, you may or may not need to pre-configure permissions.

The properties configured during registration are used on the wire. For example, in the following token request: client_id is the Application ID, redirect_uri is one of your app’s registered Redirect URIs, and client_secret is the Application Secret.

// Line breaks for legibility only

POST /common/oauth2/v2.0/token HTTP/1.1
Host: https://login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded

client_id=6731de76-14a6-49ae-97bc-6eba6914391e
&scope=user.read%20mail.read
&code=OAAABAAAAiL9Kn2Z27UubvWFPbm0gLWQJVzCTE9UkP3pSx1aXxUjq3n8b2JRLk4OxVXr...
&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F
&grant_type=authorization_code
&client_secret=JqQX2PNo9bpM0uEihUPzyrh    // NOTE: Only required for web apps

3.16 Are there authentication libraries available?

Like most developers, you will probably use authentication libraries to manage your interactions with Azure AD. Authentication libraries abstract many protocol details, like validation, cookie handling, token caching, and maintaining secure connections, away from the developer and let you focus your development on your app. Microsoft publishes open source client libraries and server middleware for both the Azure AD and Azure AD v2.0 endpoints.

For the Azure AD v2.0 endpoint:

  • Microsoft Authentication Library (MSAL) client libraries are available for .NET, JavaScript, Android, and Objective-c. All platforms are in production-supported preview, and, in the event breaking changes are introduced, Microsoft guarantees a path to upgrade.
  • Server middleware from Microsoft is available for .NET core and ASP.NET (OWIN OpenID Connect and OAuth) and for Node.js (Microsoft Azure AD Passport.js).
  • The v2.0 endpoint is compatible with many third-party authentication libraries.

For a complete list of Microsoft client libraries, Microsoft server middleware, and compatible third-party libraries, see Azure Active Directory v2.0 authentication libraries.

For the Azure AD endpoint:

  • Active Directory Authentication Library (ADAL) client libraries are available on a slightly larger number of platforms.
  • Server middleware from Microsoft is available for .NET core and ASP.NET, as well as Node.js.

For a complete list of Microsoft client libraries and server middleware, see Azure Active Directory Authentication Libraries.

3.17 Deciding between the Azure AD and Azure AD v2.0 endpoints

Azure AD exposes two sets of endpoints, Azure AD and Azure AD v2.0, where you can get access tokens to use when you call Microsoft Graph. Tokens received from each endpoint are not interchangeable. To run samples or explore the functionality of Microsoft Graph, your choice of Azure AD endpoints is not critical. However, before you begin development on a production app, you need to decide which endpoint makes the best sense for your scenario. The following discussion provides some general guidelines that you can use to help make your decision, but for the most current and comprehensive information you must see Should I use the v2.0 endpoint? in the Azure Active Directory documentation.

The main difference between Azure AD and Azure AD v2.0 is that:

  • Azure AD supports only work or school accounts; that is, accounts that are associated with an Azure AD tenant. This means that your app can target only organizations.
  • Azure AD v2.0 supports both work and school accounts and Microsoft accounts like live.com or outlook.com accounts. This means that your app can target both consumers and organizations using the v2.0 endpoint.

There are some additional advantages with Azure AD v2.0. For example:

  • Your app can use a single Application ID for multiple platforms. This simplifies app management for both developers and administrators.
  • Support for dynamic and incremental consent. With this feature your app can request additional permissions during runtime, pairing the request for the user’s consent with the functionality that requires it. This provides a much more comfortable experience for users than having to consent to a long list of permissions when they sign-in for the first time.

Because Azure AD v2.0 is newer than Azure AD and features are still being added, there are some limitations with the v2.0 endpoint that you need to factor into your decision. For example:

  • Some features may not yet be fully implemented in v2.0. For example, your app might not work if your enterprise customer turns on enterprise mobility security features like conditional device access.
  • You cannot call Microsoft Graph from a standalone web API.
  • You cannot call Cloud Solution provider apps.
  • Windows integrated authentication for federated tenants is not supported. This means that users of federated Azure AD tenants cannot silently authenticate with their on-premises Active Directory instance. They will have to re-enter their credentials.

For more information about differences between the Azure AD v2.0 endpoint and the Azure AD endpoint, see What’s different about the v2.0 endpoint?.

Important

Before making a decision about which endpoint to use when developing an app for production, consult Should I use the v2.0 endpoint?.

3.18 Next steps

Once you’ve registered your app, you’re ready to get started!

  • For quick steps on getting an access token for apps that call Microsoft Graph on behalf of a user, see Get access on behalf of users.
  • For quick steps on getting an access token for apps that call Microsoft Graph without a user, see Get access without a user.
  • To see the permissions that you can use with Microsoft Graph, see Permissions.
  • If you’re a Microsoft Cloud Solution provider interested in accessing partner-managed customer data through Microsoft Graph, see Manage app access (CSPs).

If you’re ready to jump into code, you can use the following resources to help you implement authentication and authorization with Azure AD in your app.

3.18.1 Microsoft Graph Connect samples

Microsoft publishes Connect samples for Microsoft Graph for a wide variety of platforms, including: Android, Angular.JS, ASP.NET, iOS (Obj-C and Swift), Node.JS, PHP, Python, Ruby, UWP, and Xamarin. You can use these samples to examine code that uses various authentication libraries to get tokens from Azure AD. Currently, most samples use third-party authentication libraries; however, the ASP.NET and UWP samples use Microsoft libraries.

  • The Build your first app section contains detailed articles that show you how to create Connect apps using the Azure AD v2.0 endpoint, and covers the authentication libraries used on each platform. Available samples are listed by platform and authentication endpoint.
  • To quickly get a running sample on your platform of choice, see Microsoft Graph Quick Start.
  • Visit the Microsoft Graph repo on GitHub to see all the samples available for Microsoft Graph.

3.18.2 Azure Active Directory samples and documentation

The Azure AD documentation contains articles and samples that specifically focus on authentication and authorization with Azure AD.

For the Azure AD v2.0 endpoint:

For the Azure AD endpoint:

3.19 See also

# Register your app with the Azure AD v2.0 endpoint

Your app must be registered with Azure AD. Registering your app establishes a unique application ID and other values that your app uses to authenticate with Azure AD and get tokens. For the Azure AD v2.0 endpoint, you register your app with the Microsoft App Registration Portal. You can use either a Microsoft account or a work or school account to register your app. Depending on the type of app you are developing, you will need to copy one or more properties during registration to use when you configure authentication and authorization for your app.

Note: This article primarily covers registering apps with the Azure AD v2.0 endpoint. For information about registering your app with the Azure AD endpoint, see Azure AD endpoint considerations below.

Also, be aware that if you’ve previously registered apps in the Microsoft Azure Management portal, those apps will not be listed in the App Registration Portal. Manage those apps in the Azure Management portal.

The following screenshot shows an example web app registration that has been configured with a password and implicit flow.
Web app registration with password and implicit grant.

To register your app, follow these steps; be sure to copy the indicated values to use when configuring authorization for your app:

  1. Sign into the Microsoft App Registration Portal.

    You can sign in with either a Microsoft account or a work or school account.

  2. Choose Add an app.

    Note: If you signed in with a work or school account, select the Add an app button for Converged applications.

  3. Enter a name for the app and choose Create application.

    The registration page displays, listing the properties of your app.

  4. Copy the application ID. This is the unique identifier for your app.

    You’ll use the application ID to configure the app.

  5. Under Platforms, choose Add Platform, and select the appropriate platform for your app:

    For native or mobile apps:

    1. Select Native Application.

    2. Copy the Built-in redirect URI value. You’ll need this to configure your app.

      The redirect URI is a unique URI provided for your application to ensure that messages sent to that URI are only sent to that application.

    For web apps:

    1. Select Web.

    2. Depending on the type of authentication flow you’re using, you may have to make sure the Allow Implicit Flow check box is selected.

      The Allow Implicit Flow option enables the OpenID Connect hybrid and implicit flows. The hybrid flow enables the app to receive both sign-in info (the id token) and artifacts (in this case, an authorization code) that the app uses to obtain an access token. The hybrid flow is the default flow used by the OWIN OpenID Connect middleware. For single page apps (SPA), the implicit flow enables the app to receive sign-in info and the access token.

    3. Specify a Redirect URL.

      The redirect URL is the location in your app that the Azure AD v2.0 endpoint calls when it has processed the authentication request.

    4. Under Application Secrets, choose Generate New Password. Copy the app secret from the New password generated dialog box.

      Important You must copy the app secret before you close the New password generated dialog. After you close the dialog, you cannot retrieve the secret.

  6. Choose Save.

The following table shows the properties that you need to configure and copy for different kinds of apps. Assigned means that you should use the value assigned by Azure AD.

App type Platform Application ID Application Secret Redirect URI/URL Implicit Flow
Native/Mobile Native Assigned No Assigned No
Web App Web Assigned Yes Yes Optional <br/>Open ID Connect middleware uses hybrid flow by default (Yes)
Single Page App (SPA) Web Assigned Yes Yes Yes <br/> SPAs use Open ID Connect implicit Flow
Service/Daemon Web Assigned Yes Yes No

Apps that provide an administrator consent experience may need an additional Redirect URL for Azure AD to return the response to.

For more detail about the App Registration Portal and the properties you can configure for your App, see App registration reference.

3.20 Azure AD endpoint considerations

You use the Azure portal to register your app for the Azure AD endpoint. You configure the same basic properties like Application ID, Application Secret, and Redirect URI/URL, as you would for the v2.0 endpoint; however, there are some important differences to be aware of:

  • You can only use a work or school account to register an app.
  • Your app will require a different Application ID for each platform.
  • If your app is a multi-tenant app, you must explicitly configure it to be multi-tenant at the portal.
  • You must pre-configure all the permissions (including Microsoft Graph permissions) that your app needs at the portal.

For guidance on using the Azure portal to add an app, see Integrating applications with Azure Active Directory: Adding an application.

# Get access without a user
Some apps call Microsoft Graph with their own identity and not on behalf of a user. In many cases, these are background services or daemons that run on a server without the presence of a signed-in user. An example of such an app might be an email archival service that wakes up and runs overnight. In some cases, apps that have a signed-in user present may also need to call Microsoft Graph under their own identity. For example, an app may need to use functionality that requires more elevated privileges in an organization than those carried by the signed-in user.

Apps that call Microsoft Graph with their own identity use the OAuth 2.0 client credentials grant flow to get access tokens from Azure AD. In this topic, we will walk through the basic steps to configure a service and use the OAuth client credentials grant flow to get an access token.

3.21 Authentication and authorization steps

The basic steps required to configure a service and get a token from the Azure AD v2.0 endpoint that your service can use to call Microsoft Graph under its own identity are:

  1. Register your app.
  2. Configure permissions for Microsoft Graph on your app.
  3. Get administrator consent.
  4. Get an access token.
  5. Use the access token to call Microsoft Graph.

3.22 1. Register your app

To authenticate with the Azure v2.0 endpoint, you must first register your app at the Microsoft App Registration Portal. You can use either a Microsoft account or a work or school account to register your app.

The following screenshot shows a web app registration that has been configured for a background service.
Service app registration

For a service that will call Microsoft Graph under its own identity, you need to register your app for the Web platform and copy the following values:

  • The Application ID assigned by the app registration portal.
  • An Application Secret, either a password or a public/private key pair (certificate).
  • A Redirect URL for your service to receive token responses from Azure AD.
  • A Redirect URL for your service to receive admin consent responses if your app implements functionality to request administrator consent.

For steps on how to configure an app using the Microsoft App Registration Portal, see Register your app.

With the OAuth 2.0 client credentials grant flow, your app authenticates directly at the Azure AD v2.0 /token endpoint using the Application ID assigned by Azure AD and the Application Secret that you create using the portal.

3.23 2. Configure permissions for Microsoft Graph

For apps that call Microsoft Graph under their own identity, Microsoft Graph exposes application permissions. (Microsoft Graph also exposes delegated permissions for apps that call Microsoft Graph on behalf of a user.) You pre-configure the application permissions your app needs when you register your app. Application permissions always require administrator consent. An administrator can either consent to these permissions using the Azure portal when your app is installed in their organization, or you can provide a sign-up experience in your app through which administrators can consent to the permissions you configured. Once administrator consent is recorded by Azure AD, your app can request tokens without having to request consent again. For more detailed information about the permissions available with Microsoft Graph, see the Permissions reference

To configure application permissions for your app in the Microsoft App Registration Portal: under Microsoft Graph, choose Add next to Application Permissions and then select the permissions your app requires in the Select Permissions dialog.

The following screenshot shows the Select Permissions dialog for Microsoft Graph application permissions.

Select Permissions dialog for Microsoft Graph application permissions.

Important: We recommend configuring the least privileged set of permissions required by your app. This provides a much more comfortable experience for administrators than having to consent to a long list of permissions.

You can rely on an administrator to grant the permissions your app needs at the Azure portal; however, often, a better option is to provide a sign-up experience for administrators by using the Azure AD v2.0 /adminconsent endpoint.

3.24.1 Request

// Line breaks are for legibility only.

GET https://login.microsoftonline.com/{tenant}/adminconsent?
client_id=6731de76-14a6-49ae-97bc-6eba6914391e
&state=12345
&redirect_uri=http://localhost/myapp/permissions
Parameter Condition Description
tenant Required The directory tenant that you want to request permission from. This can be in GUID or friendly name format. If you don’t know which tenant the user belongs to and you want to let them sign in with any tenant, use common.
client_id Required The Application ID that the Application Registration Portal assigned to your app.
redirect_uri Required The redirect URI where you want the response to be sent for your app to handle. It must exactly match one of the redirect URIs that you registered in the portal, except that it must be URL encoded, and it can have additional path segments.
state Recommended A value that is included in the request that also is returned in the token response. It can be a string of any content that you want. The state is used to encode information about the user’s state in the app before the authentication request occurred, such as the page or view they were on.

With requests to the /adminconsent endpoint, Azure AD enforces that only a tenant administrator can sign in to complete the request. The administrator will be asked to approve all the application permissions that you have requested for your app in the app registration portal. The following is an example of the consent dialog that Azure AD presents to the administrator:

Administrator consent dialog.

3.24.3 Response

If the administrator approves the permissions for your application, the successful response looks like this:

GET http://localhost/myapp/permissions?tenant=a8990e1f-ff32-408a-9f8e-78d3b9139b95&state=state=12345&admin_consent=True
Parameter Description
tenant The directory tenant that granted your application the permissions that it requested, in GUID format.
state A value that is included in the request that also is returned in the token response. It can be a string of any content that you want. The state is used to encode information about the user’s state in the app before the authentication request occurred, such as the page or view they were on.
admin_consent Set to true.

Try You can try this for yourself by pasting the request below in a browser. If you sign in as a Global administrator for an Azure AD tenant, you will be presented with the administrator consent dialog for the app. (This will be a different app than that in the consent dialog screenshot shown above.)

https://login.microsoftonline.com/common/adminconsent?client_id=6731de76-14a6-49ae-97bc-6eba6914391e&state=12345&redirect_uri=http://localhost/myapp/permissions

3.25 4. Get an access token

In the OAuth 2.0 client credentials grant flow, you use the Application ID and Application Secret values that you saved when you registered your app to request an access token directly from the Azure AD v2.0 /token endpoint.

You specify the pre-configured permissions by passing https://graph.microsoft.com/.default as the value for the scope parameter in the token request. See the scope parameter description in the token request below for details.

3.25.1 Token request

You send a POST request to the /token v2.0 endpoint to acquire an access token:

POST /{tenant}/oauth2/v2.0/token HTTP/1.1
Host: login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded

client_id=535fb089-9ff3-47b6-9bfb-4f1264799865&scope=https%3A%2F%2Fgraph.microsoft.com%2F.default&client_secret=qWgdYAmab0YSkuL1qKv5bPX&grant_type=client_credentials
Parameter Condition Description
tenant Required The directory tenant that you want to request permission from. This can be in GUID or friendly name format.
client_id Required The Application ID that the Microsoft App Registration Portal assigned when you registered your app.
scope Required The value passed for the scope parameter in this request should be the resource identifier (Application ID URI) of the resource you want, affixed with the .default suffix. For Microsoft Graph, the value is https://graph.microsoft.com/.default. This value informs the v2.0 endpoint that of all the application permissions you have configured for your app, it should issue a token for the ones associated with the resource you want to use.
client_secret Required The Application Secret that you generated for your app in the app registration portal.
grant_type Required Must be client_credentials.

3.25.1.1 Token response

A successful response looks like this:

{
  "token_type": "Bearer",
  "expires_in": 3599,
  "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik1uQ19WWmNBVGZNNXBP..."
}
Parameter Description
access_token The requested access token. Your app can use this token in calls to Microsoft Graph.
token_type Indicates the token type value. The only type that Azure AD supports is bearer.
expires_in How long the access token is valid (in seconds).

3.26 5. Use the access token to call Microsoft Graph

Once you have an access token, you can use it to call Microsoft Graph by including it in the Authorization header of a request. The following request gets the profile of a specific user. Your app must have the User.Read.All permission to call this API.

GET https://graph.microsoft.com/v1.0/user/12345678-73a6-4952-a53a-e9916737ff7f 
Authorization: Bearer eyJ0eXAiO ... 0X2tnSQLEANnSPHY0gKcgw
Host: graph.microsoft.com

A successful response will look similar to this (some response headers have been removed):

HTTP/1.1 200 OK
Content-Type: application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8
request-id: f45d08c0-6901-473a-90f5-7867287de97f
client-request-id: f45d08c0-6901-473a-90f5-7867287de97f
OData-Version: 4.0
Duration: 309.0273
Date: Wed, 26 Apr 2017 19:53:49 GMT
Content-Length: 407

{
    "@odata.context":"https://graph.microsoft.com/v1.0/$metadata#users/$entity",
    "id":"12345678-73a6-4952-a53a-e9916737ff7f",
    "businessPhones":[
        "+1 555555555"
    ],
    "displayName":"Chris Green",
    "givenName":"Chris",
    "jobTitle":"Software Engineer",
    "mail":null,
    "mobilePhone":"+1 5555555555",
    "officeLocation":"Seattle Office",
    "preferredLanguage":null,
    "surname":"Green",
    "userPrincipalName":"ChrisG@contoso.onmicrosoft.com"
}

3.27 Supported app scenarios and resources

Apps that call Microsoft Graph under their own identity fall into one of two categories:

  • Background services (daemons) that run on a server without a signed-in user.
  • Apps that have a signed-in user but also call Microsoft Graph with their own identity; for example, to use functionality that requires more elevated privileges than those of the user.

Apps that call Microsoft Graph with their own identity use the OAuth 2.0 client credentials grant to authenticate with Azure AD and get a token. For the v2.0 endpoint, you can explore this scenario further with the following resources:

3.28 Azure AD endpoint considerations

If you are using the Azure AD endpoint, there are some differences in the way that you configure your app and the way that it signs in to Azure AD:

  • You use the Azure portal to configure your app. For more information about configuring apps with the Azure portal, see Integrating applications with Azure Active Directory: Adding an application
  • If your app is a multi-tenant app, you must explicitly configure it to be multi-tenant at the Azure portal.
  • There is no admin consent endpoint (/adminconsent), instead, your app can request administrator consent during runtime by adding the prompt=admin_consent parameter to an authorization request. For more information, see Triggering the Azure AD consent framework at runtime in Integrating applications with Azure Active Directory.
  • The parameters in authorization and token requests are different. For example, there is no scope parameter in Azure AD endpoint requests; instead, the resource parameter is used to specify the URI of the resource (resource=https://graph.microsoft.com) that authorization (for administrator consent) or a token is being requested for.

For the Azure AD endpoint, you can explore this scenario further with the following resources:

  • For quick links to an overview, samples, and a detailed treatment of the client credentials grant flow, see Service-to-Service in the Getting Started section in Azure Active Directory for Developers.
  • For the Azure AD endpoint, you can use the Azure Active Directory Authentication Library (ADAL) to get tokens from Azure AD. ADAL is available for several platforms including .NET, iOS, Android, JavaScript, Java, and Node.js. For more information about ADAL and other Microsoft authentication libraries for the Azure AD endpoint, see Azure Active Directory Authentication Libraries.

# Get access on behalf of a user
To use Microsoft Graph to read and write resources on behalf of a user, your app must get an access token from Azure AD and attach the token to requests that it sends to Microsoft Graph. The exact authentication flow that you will use to get access tokens will depend on the kind of app you are developing and whether you want to use OpenID Connect to sign the user in to your app. One common flow used by native and mobile apps and also by some Web apps is the OAuth 2.0 authorization code grant flow. In this topic, we will walk through an example using this flow.

3.29 Authentication and Authorization steps

The basic steps required to use the OAuth 2.0 authorization code grant flow to get an access token from the Azure AD v2.0 endpoint are:

  1. Register your app with Azure AD.
  2. Get authorization.
  3. Get an access token.
  4. Call Microsoft Graph with the access token.
  5. Use a refresh token to get a new access token.

3.30 1. Register your app

To use the Azure v2.0 endpoint, you must register your app at the Microsoft App Registration Portal. You can use either a Microsoft account or a work or school account to register an app.

The following screenshot shows an example Web app registration.
Web app registration with password and Implicit Grant.

To configure an app to use the OAuth 2.0 authorization code grant flow, you’ll need to save the following values when registering the app:

  • The Application ID assigned by the app registration portal.
  • An Application Secret, either a password or a public/private key pair (certificate). This is not required for native apps.
  • A Redirect URL for your app to receive responses from Azure AD.

For steps on how to configure an app using the Microsoft App Registration Portal, see Register your app.

3.31 2. Get authorization

The first step to getting an access token for many OpenID Connect and OAuth 2.0 flows is to redirect the user to the Azure AD v2.0 /authorize endpoint. Azure AD will sign the user in and ensure their consent for the permissions your app requests. In the authorization code grant flow, after consent is obtained, Azure AD will return an authorization_code to your app that it can redeem at the Azure AD v2.0 /token endpoint for an access token.

3.31.1 Authorization request

The following shows an example request to the /authorize endpoint.

With the Azure AD v2.0 endpoint, permissions are requested using the scope parameter. In this example, the Microsoft Graph permissions requested are for User.Read and Mail.Read, which will allow the app to read the profile and mail of the signed-in user. The offline_access permission is requested so that the app can get a refresh token, which it can use to get a new access token when the current one expires.

// Line breaks for legibility only

https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize?
client_id=6731de76-14a6-49ae-97bc-6eba6914391e
&response_type=code
&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F
&response_mode=query
&scope=offline_access%20user.read%20mail.read
&state=12345
Parameter Description
tenant required The {tenant} value in the path of the request can be used to control who can sign into the application. The allowed values are common for both Microsoft accounts and work or school accounts, organizations for work or school accounts only, consumers for Microsoft accounts only, and tenant identifiers such as the tenant ID or domain name. For more detail, see protocol basics.
client_id required The Application ID that the registration portal (apps.dev.microsoft.com) assigned your app.
response_type required Must include code for the authorization code flow.
redirect_uri recommended The redirect_uri of your app, where authentication responses can be sent and received by your app. It must exactly match one of the redirect_uris you registered in the app registration portal, except it must be URL encoded. For native and mobile apps, you should use the default value of https://login.microsoftonline.com/common/oauth2/nativeclient.
scope required A space-separated list of the Microsoft Graph permissions that you want the user to consent to. This may also include OpenID scopes.
response_mode recommended Specifies the method that should be used to send the resulting token back to your app. Can be query or form_post.
state recommended A value included in the request that will also be returned in the token response. It can be a string of any content that you wish. A randomly generated unique value is typically used for preventing cross-site request forgery attacks. The state is also used to encode information about the user’s state in the app before the authentication request occurred, such as the page or view they were on.

Important: Microsoft Graph exposes two kinds of permissions: application and delegated. For apps that run with a signed-in user, you request delegated permissions in the scope parameter. These permissions delegate the privileges of the signed-in user to your app, allowing it to act as the signed-in user when making calls to Microsoft Graph. For more detailed information about the permissions available through Microsoft Graph, see the Permissions reference.

At this point, the user will be asked to enter their credentials to authenticate with Azure AD. The v2.0 endpoint will also ensure that the user has consented to the permissions indicated in the scope query parameter. If the user has not consented to any of those permissions and if an administrator has not previously consented on behalf of all users in the organization, Azure AD will ask the user to consent to the required permissions.

Here is an example of the consent dialog presented for a Microsoft account:

Consent dialog for Microsoft account

Try If you have a Microsoft account or an Azure AD work or school account, you can try this for yourself by clicking on the link below. After signing in, your browser should be redirected to https://localhost/myapp/ with a code in the address bar.

<a href=“https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=6731de76-14a6-49ae-97bc-6eba6914391e&response_type=code&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F&response_mode=query&scope=offline_access%20user.read%20mail.read&state=12345” target=“_blank“>https://login.microsoftonline.com/common/oauth2/v2.0/authorize…</a>

3.31.3 Authorization response

If the user consents to the permissions your app requested, the response will contain the authorization code in the code parameter. Here is an example of a successful response to the request above. Because the response_mode parameter in the request was set to query, the response is returned in the query string of the redirect URL.

GET http://localhost/myapp/?
code=M0ab92efe-b6fd-df08-87dc-2c6500a7f84d
&state=12345
Parameter Description
code The authorization_code that the app requested. The app can use the authorization code to request an access token for the target resource. Authorization_codes are very short lived, typically they expire after about 10 minutes.
state If a state parameter is included in the request, the same value should appear in the response. The app should verify that the state values in the request and response are identical.

3.32 3. Get a token

Your app uses the authorization code received in the previous step to request an access token by sending a POST request to the /token endpoint.

3.32.1 Token request

// Line breaks for legibility only

POST /common/oauth2/v2.0/token HTTP/1.1
Host: https://login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded

client_id=6731de76-14a6-49ae-97bc-6eba6914391e
&scope=user.read%20mail.read
&code=OAAABAAAAiL9Kn2Z27UubvWFPbm0gLWQJVzCTE9UkP3pSx1aXxUjq3n8b2JRLk4OxVXr...
&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F
&grant_type=authorization_code
&client_secret=JqQX2PNo9bpM0uEihUPzyrh    // NOTE: Only required for web apps
Parameter Description
tenant required The {tenant} value in the path of the request can be used to control who can sign into the application. The allowed values are common for both Microsoft accounts and work or school accounts, organizations for work or school accounts only, consumers for Microsoft accounts only, and tenant identifiers such as the tenant ID or domain name. For more detail, see protocol basics.
client_id required The Application ID that the registration portal (apps.dev.microsoft.com) assigned your app.
grant_type required Must be authorization_code for the authorization code flow.
scope required A space-separated list of scopes. The scopes requested in this leg must be equivalent to or a subset of the scopes requested in the first (authorization) leg. If the scopes specified in this request span multiple resource servers, then the v2.0 endpoint will return a token for the resource specified in the first scope.
code required The authorization_code that you acquired in the first leg of the flow.
redirect_uri required The same redirect_uri value that was used to acquire the authorization_code.
client_secret required for web apps The application secret that you created in the app registration portal for your app. It should not be used in a native app, because client_secrets cannot be reliably stored on devices. It is required for web apps and web APIs, which have the ability to store the client_secret securely on the server side.

3.32.2 Token response

Although the access token is opaque to your app, the response contains a list of the permissions that the access token is good for in the scope parameter.

{
    "token_type": "Bearer",
    "scope": "user.read%20Fmail.read",
    "expires_in": 3600,
    "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1Q...",
    "refresh_token": "AwABAAAAvPM1KaPlrEqdFSBzjqfTGAMxZGUTdM0t4B4..."
}
Parameter Description
token_type Indicates the token type value. The only type that Azure AD supports is Bearer
scope A space separated list of the Microsoft Graph permissions that the access_token is valid for.
expires_in How long the access token is valid (in seconds).
access_token The requested access token. Your app can use this token to call Microsoft Graph.
refresh_token An OAuth 2.0 refresh token. Your app can use this token acquire additional access tokens after the current access token expires. Refresh tokens are long-lived, and can be used to retain access to resources for extended periods of time. For more detail, refer to the v2.0 token reference.

3.33 4. Use the access token to call Microsoft Graph

Once you have an access token, you can use it to call Microsoft Graph by including it in the Authorization header of a request. The following request gets the profile of the signed-in user.

GET https://graph.microsoft.com/v1.0/me 
Authorization: Bearer eyJ0eXAiO ... 0X2tnSQLEANnSPHY0gKcgw
Host: graph.microsoft.com

A successful response will look similar to this (some response headers have been removed):

HTTP/1.1 200 OK
Content-Type: application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8
request-id: f45d08c0-6901-473a-90f5-7867287de97f
client-request-id: f45d08c0-6901-473a-90f5-7867287de97f
OData-Version: 4.0
Duration: 727.0022
Date: Thu, 20 Apr 2017 05:21:18 GMT
Content-Length: 407

{
    "@odata.context":"https://graph.microsoft.com/v1.0/$metadata#users/$entity",
    "id":"12345678-73a6-4952-a53a-e9916737ff7f",
    "businessPhones":[
        "+1 555555555"
    ],
    "displayName":"Chris Green",
    "givenName":"Chris",
    "jobTitle":"Software Engineer",
    "mail":null,
    "mobilePhone":"+1 5555555555",
    "officeLocation":"Seattle Office",
    "preferredLanguage":null,
    "surname":"Green",
    "userPrincipalName":"ChrisG@contoso.onmicrosoft.com"
}

3.34 5. Use the refresh token to get a new access token

Access tokens are short lived, and you must refresh them after they expire to continue accessing resources. You can do so by submitting another POST request to the /token endpoint, this time providing the refresh_token instead of the code.

3.34.1 Request

// Line breaks for legibility only

POST /common/oauth2/v2.0/token HTTP/1.1
Host: https://login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded

client_id=6731de76-14a6-49ae-97bc-6eba6914391e
&scope=user.read%20mail.read
&refresh_token=OAAABAAAAiL9Kn2Z27UubvWFPbm0gLWQJVzCTE9UkP3pSx1aXxUjq...
&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F
&grant_type=refresh_token
&client_secret=JqQX2PNo9bpM0uEihUPzyrh      // NOTE: Only required for web apps
Parameter Description
client_id required The Application ID that the registration portal (apps.dev.microsoft.com) assigned your app.
grant_type required Must be refresh_token.
scope required A space-separated list of permissions (scopes). The permissions requested must be equivalent to or a subset of the permissions requested in the original authorization_code request.
refresh_token required The refresh_token that you acquired during the token request.
redirect_uri required The same redirect_uri value that was used to acquire the authorization_code.
client_secret required for web apps The application secret that you created in the app registration portal for your app. It should not be used in a native app, because client_secrets cannot be reliably stored on devices. It is required for web apps and web APIs, which have the ability to store the client_secret securely on the server side.

3.34.2 Response

A successful token response will look similar to the following.

{
    "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1Q...",
    "token_type": "Bearer",
    "expires_in": 3599,
    "scope": "user.read%20mail.read",
    "refresh_token": "AwABAAAAvPM1KaPlrEqdFSBzjqfTGAMxZGUTdM0t4B4...",
}
Parameter Description
access_token The requested access token. The app can use this token in calls to Microsoft Graph.
token_type Indicates the token type value. The only type that Azure AD supports is Bearer
expires_in How long the access token is valid (in seconds).
scope The permissions (scopes) that the access_token is valid for.
refresh_token A new OAuth 2.0 refresh token. You should replace the old refresh token with this newly acquired refresh token to ensure your refresh tokens remain valid for as long as possible.

3.35 Supported app scenarios and additional resources

You can call Microsoft Graph on behalf of a user from the following kinds of apps:

  • Native/Mobile apps
  • Web apps
  • Single page apps (SPA)
  • Back-end Web APIs: For example, in scenarios where a client app, like a native app, implements functionality in a Web API back end. With the Azure AD v2.0 endpoint, both the client app and the back-end Web API must have the same Application ID.

For more information about supported app types with the Azure AD v2.0 endpoint, see Types of apps.

Note: Calling Microsoft Graph from a standalone web API is not currently supported by the Azure AD v2.0 endpoint. For this scenario, you need to use the Azure AD endpoint.

For more information about getting access to Microsoft Graph on behalf of a user from the Azure AD v2.0 endpoint:

3.36 Azure AD endpoint considerations

There are several differences between using the Azure AD endpoint and the Azure AD v2.0 endpoint. For example:

  • You use the Azure portal to configure your app. For more information about configuring apps with the Azure portal, see Integrating applications with Azure Active Directory: Adding an application
  • Your app will require a different application ID (client ID) for each platform.
  • If your app is a multi-tenant app, you must explicitly configure it to be multi-tenant at the Azure portal.
  • With the Azure AD endpoint, all permissions that your app needs must be configured by the developer. The Azure AD endpoint does not support dynamic (incremental) consent.
  • The Azure AD endpoint uses a resource parameter in authorization and token requests to specify the resource, such as Microsoft Graph, for which it wants permissions. The endpoint does not support the scope parameter.
  • The Azure AD endpoint does not expose a specific endpoint for administrator consent. Instead apps use the prompt=admin_consent parameter in the authorization request to obtain administrator consent for an organization. For more information, see Triggering the Azure AD consent framework at runtime in Integrating applications with Azure Active Directory.

For more information about getting access to Microsoft Graph on behalf of a user from the Azure AD endpoint:

  • For information about using the Azure AD endpoint with different kinds of apps, see the Get Started links in the Azure Active Directory developers guide. The guide contains links to overview topics, code walk-throughs, and protocol documentation for different kinds of app supported by the Azure AD endpoint.
  • For information about the Active Directory Authentication Library (ADAL) and server middleware available for use with the Azure AD endpoint, see Azure Active Directory Authentication Libraries.

4 Calling the Microsoft Graph API

To access and manipulate a Microsoft Graph resource, you call and specify the resource URLs using one of the following operations:

  • GET
  • POST
  • PATCH
  • PUT
  • DELETE

All Microsoft Graph API requests use the following basic URL pattern:

    https://graph.microsoft.com/{version}/{resource}?[query_parameters]

For this URL:

  • https://graph.microsoft.com is the Microsoft Graph API endpoint.
  • {version} is the target service version, for example, v1.0 or beta.
  • {resource} is resource segment or path, such as:
  • users, groups, devices, organization
  • The alias me, which resolves to the signed-in user
  • The resources belonging to a user, such as me/events, me/drive or me/messages
  • The alias myOrganization, which resolves to the tenant of the organization signed-in user
  • [query_parameters] represents additional query parameters such as $filter and $select.

Optionally, you can also specify the tenant as part of your request.
When using me, do not specify the tenant.
For a list of common requests, see Overview of Microsoft Graph.

4.1 Microsoft Graph API metadata

The metadata document ($metadata) is published at the service root.
For example, you can view the service document for the v1.0 and beta versions via the following URLs.

Microsoft Graph API v1.0 metadata.

    https://graph.microsoft.com/v1.0/$metadata

Microsoft Graph API beta metadata.

    https://graph.microsoft.com/beta/$metadata

The metadata allows you to see and understand the data model of the Microsoft Graph, including the entity types and sets, complex types, and enums that make up the request and response packets sent to and from Microsoft Graph.
You can use the metadata to understand the realtionships between entities in Microsoft Graph and establish URLs that navigate between entities.
This navigation-based interconnectedness gives Microsoft Graph its unique character.

Path URL resource names, query parameters, and action parameters and values are case insensitive.
However, values you assign, entity IDs, and other base64-encoded values are case sensitive.

The following sections show a few basic programming pattern calls to the Microsoft Graph API.

To view the information about a user, you get the User entity from the users collection to the specific user identified by its identifier, using an HTTPS GET request.
For a User entity, either the id or userPrincipalName property can be used as the identifier.
The following example request uses the userPrincipalName value as the user’s id.

GET https://graph.microsoft.com/v1.0/users/john.doe@contoso.onmicrosoft.com HTTP/1.1
Authorization : Bearer <access_token>

If successful, you should get a 200 OK response containing the user resource representation in the payload, as shown as follows:

HTTP/1.1 200 OK
content-type: application/json;odata.metadata=minimal
content-length: 982

{
    "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users/$entity",
    "id": "c95e3b3a-c33b-48da-a6e9-eb101e8a4205",
    "city": "Redmond",
    "country": "USA",
    "department": "Help Center",
    "displayName": "John Doe",
    "givenName": "John",
    "userPrincipalName": "john.doe@contoso.onmicrosoft.com",

    ... 
}

4.3 Project from an entity to properties

To retrieve only the user’s biographical data, such as the user’s provided About me description and their skill set, you can add the select query parameter to the previous request.
For example:

GET https://graph.microsoft.com/v1.0/users/john.doe@contoso.onmicrosoft.com?$select=displayName,aboutMe,skills HTTP/1.1
Authorization : Bearer <access_token>

The successful response returns the 200 OK status and a payload of the following format:

HTTP/1.1 200 OK
content-type: application/json;odata.metadata=minimal
content-length: 169

{
    "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users/$entity",
    "aboutMe": "A cool and nice guy.",
    "displayName": "John Doe",
    "skills": [
        "n-Lingual",
        "public speaking",
        "doodling"
    ]
}

Here, instead of the entire property sets on the user entity, only the aboutMe, displayName, and skills properties are returned.

4.4 Traverse to another resource via relationship

A manager holds a directReports relationship with the other users reporting to him or her.
To query the list of the direct reports of a user, you can use the following HTTPS GET request to navigate to the intended target via relationship traversal.

GET https://graph.microsoft.com/v1.0/users/john.doe@contoso.onmicrosoft.com/directReports HTTP/1.1
Authorization : Bearer <access_token>

The successful response returns the 200 OK status and a payload of the following format:

HTTP/1.1 200 OK
content-type: application/json;odata.metadata=minimal
content-length: 152
    
{
    "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#directoryObjects/$entity",
    "@odata.type": "#microsoft.graph.user",
    "id": "c37b074d-fe9d-4e68-83ad-b4401d3be174",
    "department": "Sales & Marketing",
    "displayName": "Bonnie Kearney",

    ...
}

Similarly, you can follow a relationship to navigate to related resources.
For example, the user => messages relationship enables traversal from an Azure AD User to a set of Outlook mail messages.
The following example shows how to do this in a REST API call:

GET https://graph.microsoft.com/v1.0/me/messages HTTP/1.1
Authorization : Bearer <access_token>

The successful response returns the 200 OK status and a payload of the following format:

HTTP/1.1 200 OK
content-type: application/json;odata.metadata=minimal
odata-version: 4.0
content-length: 147
    
{
  "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('john.doe%40contoso.onmicrosoft.com')/Messages",
  "@odata.nextLink": "https://graph.microsoft.com/v1.0/me/messages?$top=1&$skip=1",
  "value": [
    {
      "@odata.etag": "W/\"FwAAABYAAABMR67yw0CmT4x0kVgQUH/3AAJL+Kej\"",
      "id": "<id-value>",
      "createdDateTime": "2015-11-14T00:24:42Z",
      "lastModifiedDateTime": "2015-11-14T00:24:42Z",
      "changeKey": "FwAAABYAAABMR67yw0CmT4x0kVgQUH/3AAJL+Kej",
      "categories": [],
      "receivedDateTime": "2015-11-14T00:24:42Z",
      "sentDateTime": "2015-11-14T00:24:28Z",
      "hasAttachments": false,
      "subject": "Did you see last night's game?",
      "body": {
        "ContentType": "HTML",
        "Content": "<content>"
      },
      "BodyPreview": "it was great!",
      "Importance": "Normal",
            
       ...
    }
  ]
}

4.5 Project from entities to properties

In addition to projection from a single entity to its properties, you can also apply the similar select query option to an entity collection to project them to a collection of some of their properties.
For example, to query the name of the signed-in user’s drive items, you can submit the following HTTPS GET request:

GET https://graph.microsoft.com/v1.0/me/drive/root/children?$select=name HTTP/1.1
Authorization : Bearer <access_token>

The successful response returns a 200 OK status code and a payload containing the names and types of the shared files, as shown in the following example:

{
  "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('john.doe%40contoso.onmicrosoft.com')/drive/root/children(name,type)",
  "value": [
    {
      "@odata.etag": "\"{896A8E4D-27BF-424B-A0DA-F073AE6570E2},2\"",
      "name": "Shared with Everyone"
    },
    {
      "@odata.etag": "\"{B39D5D2E-E968-491A-B0EB-D5D0431CB423},1\"",
      "name": "Documents"
    },
    {
      "@odata.etag": "\"{9B51EA38-3EE6-4DC1-96A6-230E325EF054},2\"",
      "name": "newFile.txt"
    }
  ]
}

4.6 Query a subset of users with the filtering query option

To find the employees of a specific job title within an organization, you can navigate from the users collection and then specify a filter query option.
An example is shown as follows:

GET https://graph.microsoft.com/v1.0/users/?$filter=jobTitle+eq+%27Helper%27 HTTP/1.1
Authorization : Bearer <access_token>

The successful response returns the 200 OK status code and a list of users with the specified job title ('Helper'), as shown in the following example:

HTTP/1.1 200 OK
content-type: application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8
odata-version: 4.0
content-length: 986

{
    "@odata.context": "https://graph.microsoft.com/v1.0/contoso.onmicrosoft.com/$metadata#users",
    "value": [
        {
            "id": "c95e3b3a-c33b-48da-a6e9-eb101e8a4205",
            "city": "Redmond",
            "country": "USA",
            "department": "Help Center",
            "displayName": "Jane Doe",
            "givenName": "Jane",
            "jobTitle": "Helper",
            ......
            "mailNickname": "Jane",
            "mobile": null,
            "otherMails": [
                "jane.doe@contoso.onmicrosoft.com"
            ],
            ......
            "surname": "Doe",
            "usageLocation": "US",
            "userPrincipalName": "help@contoso.onmicrosoft.com",
            "userType": "Member"
        },
        
        ...
    ]
}

4.7 Call actions or functions

Microsoft Graph also supports actions and functions to manipulate resources in ways that are not a simple fit with standard HTTP methods.
For example, the following HTTPS POST request lets the signed-in user (me) send an email message:

POST https://graph.microsoft.com/v1.0/me/sendMail HTTP/1.1
authorization: bearer <access_token>
content-type: application/json
content-length: 96

{
  "message": {
    "subject": "Meet for lunch?",
    "body": {
      "contentType": "Text",
      "content": "The new cafeteria is open."
    },
    "toRecipients": [
      {
        "emailAddress": {
          "address": "garthf@a830edad9050849NDA1.onmicrosoft.com"
        }
      }
    ],
    "attachments": [
      {
        "@odata.type": "#Microsoft.OutlookServices.FileAttachment",
        "name": "menu.txt",
        "contentBytes": "bWFjIGFuZCBjaGVlc2UgdG9kYXk="
      }
    ]
  },
  "saveToSentItems": "false"
}

The request payload contains the input to the sendMail action, which is also defined in the $metadata.

4.8 Use Microsoft Graph client libraries

Like the power and ease of SDKs? While you can always call Microsoft Graph using the REST API, we also provide SDKs for many popular platforms.

Explore our SDKs.

5 Changelog for Microsoft Graph

This changelog covers what’s changed in Microsoft Graph, including the v1.0 and beta endpoint Microsoft Graph APIs.

For details about known issues with Microsoft Graph APIs, see Known issues.

5.1 August 2017

5.1.1 People

Change type Version Description
Addition v1.0 Added the People APIs to v1.0. For details about the People API, see Get relevant information about people.

5.1.2 Group lifecycle policy

Change type Version Description
Addition Beta Added groupLifecyclePolicy entity.
Addition Beta Added the following APIs for group lifecycle policy: create, list, get, update, delete, add group, remove group, and renew a group.
Addition Beta Added List groupLifecylePolicies function to group entity.

5.1.3 OneNote

Change type Version Description
Addition v1.0 and Beta Added the onenote navigation property to site.
Addition Beta Added the target siteCollectionId and target siteId parameters for the copy operations. For example: CopyNotebook.

5.2 July 2017

5.2.1 Group settings

Change type Version Description
Addition v1.0 Added support for group settings.<br/>New resource types: groupSetting, groupSettingTemplate, settingValue, and settingTemplateValue
Change v1.0 Added property classification and navigation property settings to group

5.2.2 Intune APIs

Change type Version Description
Addition Beta Added the assign action on iosMobileAppConfiguration
Addition Beta Added the syncDevice action on managedDevice
Change Beta Added the appsInstallAllowList, appsLaunchBlockList and appsHideList properties to the androidGeneralDeviceConfiguration entity
Change Beta Added the disableAppEncryptionIfDeviceEncryptionIsEnabled property to the androidManagedAppProtection entity
Change Beta Added the disableAppEncryptionIfDeviceEncryptionIsEnabled property to the defaultManagedAppProtection entity
Change Beta Added the complianceGracePeriodExpirationDateTime property to the deviceComplianceDeviceStatus entity
Change Beta Added the complianceGracePeriodExpirationDateTime property to the deviceComplianceSettingState entity
Change Beta Added the complianceGracePeriodExpirationDateTime property to the deviceConfigurationDeviceStatus entity
Change Beta Added the subscriptions property to the deviceManagement entity
Change Beta Added the version property to the deviceManagementExchangeConnector entity
Change Beta Added the utcTimeOffsetInMinutes property to the iosUpdateConfiguration entity
Change Beta Added the complianceGracePeriodExpirationDateTime property to the iosUpdateDeviceStatus entity
Change Beta Added the preSharedKey property to the macOSWiFiConfiguration entity
Change Beta Added the phoneNumber, androidSecurityPatchLevel and userDisplayName properties to the managedDevice entity
Change Beta Added the userName, deviceModel, platform and complianceGracePeriodExpirationDateTime properties to the managedDeviceMobileAppConfigurationDeviceStatus entity
Change Beta Added the userPrincipalName property to the mobileAppInstallStatus entity
Change Beta Added the overrideDefaultRule property to the onPremisesConditionalAccessSettings entity
Change Beta Added the userPrincipalName property to the userAppInstallStatus entity
Change Beta Added the connectAppBlockAutoLaunch, deviceAccountBlockExchangeServices, deviceAccountEmailAddress, deviceAccountExchangeServerAddress, deviceAccountRequirePasswordRotation, deviceAccountSessionInitiationProtocolAddress, settingsBlockMyMeetingsAndFiles, settingsBlockSessionResume, settingsBlockSigninSuggestions, settingsDefaultVolume, settingsScreenTimeoutInMinutes, settingsSessionTimeoutInMinutes and settingsSleepTimeoutInMinutes properties to the windows10TeamGeneralConfiguration entity
Change Beta Added the deploymentSummary navigation property to the defaultManagedAppProtection entity
Change Beta Added the settingName, userId, userName, userEmail and currentValue properties to the deviceCompliancePolicySettingState complex type
Change Beta Added the settingName, userId, userName, userEmail and currentValue properties to the deviceConfigurationSettingState complex type
Change Beta Added the unknownCount property to the deviceOperatingSystemSummary complex type

5.3 June 2017

5.3.1 Project Rome

Change type Version Description
Addition Beta Added the following resources and APIs:<br/>Activity<br/>Create or replace an activity<br/>Delete an activity<br/>History item<br/>Create or replace a history item<br/>Delete a history item

5.3.2 Outlook calendar

Change type Version Description
Addition v1.0 Promoted the following 4 calendar properties to v1.0: canEdit, canShare, canViewPrivateItems, and owner.

5.3.3 Intune APIs

Change type Version Description
Addition Beta Added new entities:<br/>defaultDeviceCompliancePolicy<br/>deviceConfigurationUserStateSummary<br/>deviceManagementScriptDeviceState<br/>deviceManagementScriptRunSummary<br/>deviceManagementScriptUserState<br/>iosUpdateDeviceStatus<br/>windowsManagedDevice<br/>windowsManagementAppHealthState<br/>windowsManagementAppHealthSummary<br/>
Addition Beta Added new complex types:<br/>bitLockerFixedDrivePolicy<br/>bitLockerRecoveryOptions<br/>bitLockerRemovableDrivePolicy<br/>deleteUserFromSharedAppleDeviceActionResult<br/>iosNetworkUsageRule<br/>
Deletion Beta Removed the following entities:<br/>deviceManagementScriptState<br/>
Deletion Beta Removed the wipeByDeviceTag action on user
Change Beta Added the innerAuthenticationProtocolForEapTtls, innerAuthenticationProtocolForPeap and outerIdentityPrivacyTemporaryValue properties to the androidEnterpriseWiFiConfiguration entity
Change Beta Removed the nonEapAuthenticationMethodForEapTtls, nonEapAuthenticationMethodForPeap and enableOuterIdentityPrivacy properties from the androidEnterpriseWiFiConfiguration entity
Change Beta Added the deployedAppCount property to the androidManagedAppProtection entity
Change Beta Removed the instanceDisplayName and settingPlatform properties from the complianceSettingStateSummary entity
Change Beta Added the deployedAppCount property to the defaultManagedAppProtection entity
Change Beta Added the excludeGroup property to the deviceCompliancePolicyGroupAssignment entity
Change Beta Removed the instanceDisplayName and settingPlatform properties from the deviceCompliancePolicySettingStateSummary entity
Change Beta Removed the devicePlatform property from the deviceComplianceSettingState entity
Change Beta Added the assignmentStatus, assignmentProgress and assignmentErrorMessage properties to the deviceConfiguration entity
Change Beta Added the intuneBrand property to the deviceManagement entity
Change Beta Added the enforceSignatureCheck and fileName properties to the deviceManagementScript entity
Change Beta Added the innerAuthenticationProtocolForEapTtls and outerIdentityPrivacyTemporaryValue properties to the iosEnterpriseWiFiConfiguration entity
Change Beta Removed the nonEapAuthenticationMethodForEapTtls and enableOuterIdentityPrivacy properties from the iosEnterpriseWiFiConfiguration entity
Change Beta Added the classroomAppForceUnpromptedScreenObservation, keyboardBlockDictation, networkUsageRules and wiFiConnectOnlyToConfiguredNetworks properties to the iosGeneralDeviceConfiguration entity
Change Beta Added the deployedAppCount property to the iosManagedAppProtection entity
Change Beta Added the preSharedKey property to the iosWiFiConfiguration entity
Change Beta Added the innerAuthenticationProtocolForEapTtls and outerIdentityPrivacyTemporaryValue properties to the macOSEnterpriseWiFiConfiguration entity
Change Beta Removed the nonEapAuthenticationMethodForEapTtls and enableOuterIdentityPrivacy properties from the macOSEnterpriseWiFiConfiguration entity
Change Beta Removed the lastModifiedTime and deployedAppCount properties from the managedAppPolicy entity
Change Beta Added the serialNumber property to the managedDevice entity
Change Beta Removed the managementAgents property from the managedDevice entity
Change Beta Added the deployedAppCount property to the targetedManagedAppConfiguration entity
Change Beta Added the bitLockerFixedDrivePolicy and bitLockerRemovableDrivePolicy properties to the windows10EndpointProtectionConfiguration entity
Change Beta Added the enterpriseCloudPrintDiscoveryEndPoint, enterpriseCloudPrintOAuthAuthority, enterpriseCloudPrintOAuthClientIdentifier, enterpriseCloudPrintResourceIdentifier, enterpriseCloudPrintDiscoveryMaxLimit, enterpriseCloudPrintMopriaDiscoveryResourceIdentifier, edgeBlockAddressBarDropdown, edgeBlockCompatibilityList, edgeClearBrowsingDataOnExit, edgeAllowStartPagesModification, edgeDisableFirstRunPage, edgeBlockLiveTileDataCollection and edgeSyncFavoritesWithInternetExplorer properties to the windows10GeneralConfiguration entity
Change Beta Added the availableVersion property to the windowsManagementApp entity
Change Beta Removed the onboardingStatus, deployedVersion and lastModifiedTime properties from the windowsManagementApp entity
Change Beta Added the packageIdentityName property to the windowsStoreForBusinessApp entity
Change Beta Added the mobileAppIdentifierDeployments and deploymentSummary navigation properties to the androidManagedAppProtection entity
Change Beta Added the mobileAppIdentifierDeployments navigation property to the defaultManagedAppProtection entity
Change Beta Added the deviceConfigurationUserStateSummaries and iosUpdateStatuses navigation properties to the deviceManagement entity
Change Beta Removed the complianceSettingStateSummaries navigation property from the deviceManagement entity
Change Beta Added the runSummary, deviceRunStates and userRunStates navigation properties to the deviceManagementScript entity
Change Beta Removed the runStates navigation property from the deviceManagementScript entity
Change Beta Added the mobileAppIdentifierDeployments and deploymentSummary navigation properties to the iosManagedAppProtection entity
Change Beta Removed the mobileAppIdentifierDeployments and deploymentSummary navigation properties from the managedAppPolicy entity
Change Beta Added the mobileAppIdentifierDeployments and deploymentSummary navigation properties to the targetedManagedAppConfiguration entity
Change Beta Added the healthSummary and healthStates navigation properties to the windowsManagementApp entity
Change Beta Added the applicationId, appName, platformId, userFailures and deviceFailures properties to the appInstallationFailure complex type
Change Beta Added the encryptionMethod, startupAuthenticationRequired, startupAuthenticationBlockWithoutTpmChip, startupAuthenticationTpmUsage, startupAuthenticationTpmPinUsage, startupAuthenticationTpmKeyUsage, startupAuthenticationTpmPinAndKeyUsage, recoveryOptions and prebootRecoveryEnableMessageAndUrl properties to the bitLockerSystemDrivePolicy complex type
Change Beta Removed the settingName, userId, userName, userEmail and currentValue properties from the deviceCompliancePolicySettingState complex type
Change Beta Removed the settingName, userId, userName, userEmail and currentValue properties from the deviceConfigurationSettingState complex type
Change Beta Added the windowsCommercialId and windowsCommercialIdLastModifiedTime properties to the deviceManagementSettings complex type
Change Beta Added the address property to the vpnServer complex type

5.4 May 2017

5.4.1 Application API changes

Change type Version Description
Change Beta Application API update. This is first set of changes including property renaming and restructuring of the application entity.<br/>New entities: api, informationalUrl, installedClient, permissionScope, preauthorizedApplication, web.<br/>Removed properties: addIns, appRoles, availableToOtherOrganizations, knownClientApplications, oauth2AllowUrlPathMatching, recordConsentConditions.<br/>Renamed properties: appId to id, identifierUris to applicationAliases, availableToOtherTenants to orgRestrictions, mainLogo to logo, oauth2Permissions to publishedPermissionsScopes, publicClient to allowPublicClient, replyUrls to redirectUrls.<br/>New properties: tags.

5.4.2 Remove Deprecated Planner API

Change type Version Description
Deletion Beta Removed the following entities:<br/>task<br/>plan<br/>bucket<br/>taskDetails<br/>planDetails<br/>taskBoardTaskFormat<br/>planTaskBoard

5.4.3 Project Rome

Change type Version Description
Addition Beta Added support for Project Rome, including getting a list of devices, sending a command to a device, and checking the status of a command.
Addition Beta Added support for user activities and historyItems, including upserting an activity and upserting a historyItem.

5.4.4 Administrative units property changes

Change type Version Description
Change Beta Changed roleMemberInfo property type to identity for scopedRoleMembership entity
Change Beta Changed navigation property scopedAdministratorOf to scopedRoleMemberOf for user entity
Change Beta Changed navigation property scopedAdministrators to scopedRoleMembers for administrativeUnit entity
Change Beta Changed navigation property scopedAdministrators to scopedMembers for directoryRole entity

5.4.5 Add users and groups webhook support in preview

Change type Version Description
Change Beta Added support to webhooks for users and groups.

5.4.6 Add delta query to v1.0

Change type Version Description
Addition v1.0 Add delta function support to V1.0. Add to the following entities to perform delta query:<br/>contact<br/>contactFolder<br/>event<br/>group<br/>mailFolder<br/>message<br/>user<br/>See the following for examples:<br/>Get incremental changes to groups<br/>Get incremental changes to messages in a folder<br/>Get incremental changes to users
Change Beta Add additional optional query filtering capability (by id) to users and groups.

5.4.7 Added user resource support for deleted items

Change type Version Description
Addition Beta Added support for restoring and permanently deleting users.

5.4.8 Added OnPremisesProvisioningError

Change type Version Description
Addition beta New entity: OnPremisesProvisioningError
Change beta Added OnPremisesProvisioningError property to user, group, and orgcontact

5.4.9 Added deletedDateTime property

Change type Version Description
Change beta Added deletedDateTime property to user entity.
Change beta Added deletedDateTime property to group entity.
Change beta Added deletedDateTime property to application entity.

5.4.10 Added domain operations to v1.0

Change type Version Description
Addition V1.0 Added operations on domains.<br/>New entities:</br>domain<br/>domainDnsRecord<br/>domainDnsCnameRecord<br/>domainDnsMxRecord<br/>domainDnsSrvRecord<br/>domainDnsTxtRecord<br/>domainDnsUnavailableRecord<br/>New actions:</br>verify

5.4.11 Added contracts to v1.0

Change type Version Description
Addition V1.0 New entity:</br>contract

5.4.12 Added licenseDetails to v1.0

Change type Version Description
Addition v1.0 New entity:</br>licenseDetails
Change v1.0 New licensedetails navigation property on users

5.4.13 Drive API

Change type Version Description
Addition v1.0 Added the baseItem resource type, consisting of basic properties from driveItem.
Addition v1.0 and Beta Added the sourceItemId property to thumbnail. <br/> Added the siteUrl property to sharepointIds. <br/> Added the sharedBy and sharedDateTime properties to shared. <br/> Added the shared property to remoteItem. <br/> Added the sharepointIds property to drive and itemReference. <br/> Added lastAccessedDateTime to fileSystemInfo. <br/> Added the driveItem and site navigation properties to sharedDriveItem. <br/> Added the parentReference property to baseItem.
Change v1.0 and Beta Changed driveItem and sharedDriveItem to inherit from baseItem. <br/> Marked identity as an Open Type.
Change Beta Added the configuratorUrl and webHtml properties to sharingLink. <br/> Added the folderView resource type and the view property to the folder resource type. <br/> Added the listItem navigation property to driveItem. <br/> Added the list navigation property to drive.

5.4.14 Extensions (open extensions)

Change type Version Description
Addition v1.0 Support for openTypeExtension in the following resources - device, group,organization, user.
Addition v1.0 and beta When the user is signed-in with a personal Microsoft account, support for open extensions in the following resources - event, post, group, message, contact, and user. (This is in addition to these resources, plus device, group, organization and user, supporting open extensions when the user signs in using a work or school account.)
Addition v1.0 and beta Support for $expand to get open extensions in the following resources: device, group,organization, post, user.
Addition Beta Support for $expand to get open extensions in administrativeUnit.

5.4.15 Extensions (schema extensions)

Change type Version Description
Addition v1.0 New resource schemaExtension and CRUD methods to manage extension definitions for the following resources: contact, device, event, group, message, organization, post, user. Note that support for administrativeUnit is still limited to the beta version as before.
Addition v1.0 The existing POST, GET, and PATCH methods of the following resources - contact, device, event, group, message, organization, post, user - now support adding, getting, and updating or deleting custom data stored as schema extensions in the corresponding resource instances.
Addition v1.0 and beta You can now use $filter to look for resource instances with properties that match specific extension property values, such as extension name. See this example for details.
Change v1.0 and beta Deleting a schema extension definition no longer affects accessing custom data that has been added based on that definition.
Change v1.0 and beta You can now set a schema extension complex type to null, to remove a schema extension from a resource instance.

5.4.16 Group

Change type Version Description
Addition v1.0 and beta Added the drives and sites navigation properties to group.

5.4.17 Insights APIs

Change type Version Description
Addition Beta Added Shared API.<br />New resources:<br />sharingDetail <br />insightIdentity <br />
Addition Beta Added Used API.<br />New resources:<br />usageDetails <br />
Change Beta New Type property in the:<br />resourceVisualization resource. <br />
Deletion Beta Removed the following entities:<br/>workingWith<br/>trendingAround<br/>

5.4.18 Intune APIs

Change type Version Description
Addition Beta Added new entities:<br/>androidForWorkMobileAppConfiguration<br/>cartToClassAssociation<br/>deviceCompliancePolicySettingStateSummary<br/>eBookInstallSummary<br/>eBookVppGroupAssignment<br/>iosUpdateConfiguration<br/>remoteAssistancePartner<br/>windows10EndpointProtectionConfiguration<br/>windowsDeviceMalwareState<br/>windowsInformationProtectionAppLearningSummary<br/>windowsMalwareInformation<br/>windowsProtectionState<br/>
Addition Beta Added new complex types:<br/>androidPermissionAction<br/>bitLockerSystemDrivePolicy<br/>defenderDetectedMalwareActions<br/>settingSource<br/>
Addition Beta Added the assign action on managedEBook
Addition Beta Added the beginOnboarding action on remoteAssistancePartner
Addition Beta Added the disconnect action on remoteAssistancePartner
Deletion Beta Removed the following entities:<br/>outlookTask<br/>outlookTaskFolder<br/>outlookTaskGroup<br/>outlookUser<br/>windowsManagementAppHealthState<br/>
Deletion Beta Removed the following complex types:<br/>applePushNotificationCertificateSetting<br/>eventCreationOptions<br/>
Change Beta Added the workProfilePasswordBlockFingerprintUnlock, workProfilePasswordBlockTrustAgents, workProfilePasswordExpirationDays, workProfilePasswordMinimumLength, workProfilePasswordMinutesOfInactivityBeforeScreenTimeout, workProfilePasswordPreviousPasswordBlockCount, workProfilePasswordSignInFailureCountBeforeFactoryReset, workProfilePasswordRequiredType and workProfileRequirePassword properties to the androidForWorkGeneralDeviceConfiguration entity
Change Beta Added the subjectAlternativeNameFormatString property to the androidForWorkPkcsCertificateProfile entity
Change Beta Added the subjectNameFormatString and subjectAlternativeNameFormatString properties to the androidForWorkScepCertificateProfile entity
Change Beta Added the kioskModeManagedApps property to the androidGeneralDeviceConfiguration entity
Change Beta Removed the kioskModeManagedAppId property from the androidGeneralDeviceConfiguration entity
Change Beta Added the subjectAlternativeNameFormatString property to the androidPkcsCertificateProfile entity
Change Beta Added the subjectNameFormatString and subjectAlternativeNameFormatString properties to the androidScepCertificateProfile entity
Change Beta Removed the hexColor property from the calendar entity
Change Beta Added the setting and platformType properties to the complianceSettingStateSummary entity
Change Beta Removed the windowsManagementAppEnabled property from the deviceAppManagement entity
Change Beta Added the userName, deviceModel and platform properties to the deviceComplianceDeviceStatus entity
Change Beta Added the userPrincipalName and deviceModel properties to the deviceComplianceSettingState entity
Change Beta Added the platformType, setting, userId and userEmail properties to the deviceComplianceSettingState entity
Change Beta Added the inGracePeriodCount property to the deviceCompliancePolicyDeviceStateSummary entity
Change Beta Added the userName, deviceModel and platform properties to the deviceConfigurationDeviceStatus entity
Change Beta Removed the creationOptions property from the event entity
Change Beta Removed the isDelegated property from the eventMessage entity
Change Beta Removed the unseenConversationsCount and unseenMessagesCount properties from the group entity
Change Beta Added the settingXml and settings properties to the iosMobileAppConfiguration entity
Change Beta Added the subjectAlternativeNameFormatString property to the iosPkcsCertificateProfile entity
Change Beta Added the subjectAlternativeNameFormatString property to the iosScepCertificateProfile entity
Change Beta Added the systemIntegrityProtectionEnabled property to the macOSCompliancePolicy entity
Change Beta Added the subjectAlternativeNameFormatString property to the macOSScepCertificateProfile entity
Change Beta Added the complianceGracePeriodExpirationDateTime, userPrincipalName. and imei properties to the managedDevice entity
Change Beta Removed the settingXml and settings properties from the managedDeviceMobileAppConfiguration entity
Change Beta Added the useSharedComputerActivation, updateChannel, officePlatformArchitecture and localesToInstall properties to the officeSuiteApp entity
Change Beta Removed the applePushNotificationCertificateSetting property from the organization entity
Change Beta Changed the following properties on the post entity:<br/>sender from optional to required<br/>
Change Beta Added the compliantUserCount, nonCompliantUserCount, remediatedUserCount, errorUserCount, unknownUserCount, conflictUserCount and notApplicableUserCount properties to the softwareUpdateStatusSummary entity
Change Beta Added the bluetoothAllowedServices, bluetoothBlockPrePairing, cellularData, defenderDetectedMalwareActions, defenderPotentiallyUnwantedAppAction, lockScreenAllowTimeoutConfiguration, lockScreenBlockCortana, lockScreenBlockToastNotifications, lockScreenTimeoutInSeconds, passwordBlockSimple, privacyAutoAcceptPairingAndConsentPrompts, privacyBlockInputPersonalization, startMenuHideChangeAccountSettings, startMenuHideHibernate, startMenuHideLock, startMenuHideShutDown, startMenuHideSignOut, startMenuHideSleep, startMenuHideSwitchAccount, settingsBlockAppsPage, settingsBlockGamingPage, windowsSpotlightBlockConsumerSpecificFeatures, windowsSpotlightBlocked, windowsSpotlightBlockOnActionCenter, windowsSpotlightBlockTailoredExperiences, windowsSpotlightBlockThirdPartyNotifications, windowsSpotlightBlockWelcomeExperience, windowsSpotlightBlockWindowsTips, windowsSpotlightConfigureOnLockScreen and connectedDevicesServiceBlocked properties to the windows10GeneralConfiguration entity
Change Beta Removed the automaticUpdateMode, automaticUpdateSchedule, automaticUpdateTime, prereleaseFeatures, experienceBlockWindowsSpotlight, experienceBlockWindowsTips and experienceBlockConsumerSpecificFeatures properties from the windows10GeneralConfiguration entity
Change Beta Added the subjectAlternativeNameFormatString property to the windows10PkcsCertificateProfile entity
Change Beta Added the subjectNameFormatString and subjectAlternativeNameFormatString properties to the windows81SCEPCertificateProfile entity
Change Beta Added the indexingEncryptedStoresOrItemsBlocked and smbAutoEncryptedFileExtensions properties to the windowsInformationProtection entity
Change Beta Changed the following properties on the windowsInformationProtection entity:<br/>rightsManagementServicesTemplateId from required to optional<br/>
Change Beta Changed the following properties on the windowsMobileMSI entity:<br/>productCode from required to optional<br/>
Change Beta Added the subjectNameFormatString and subjectAlternativeNameFormatString properties to the windowsPhone81SCEPCertificateProfile entity
Change Beta Added the mobileAppConfigurations navigation property to the deviceAppManagement entity
Change Beta Added the cartToClassAssociations, deviceCompliancePolicySettingStateSummaries, remoteAssistancePartners, windowsInformationProtectionAppLearningSummaries and windowsMalwareInformation navigation properties to the deviceManagement entity
Change Beta Added the eBook navigation property to the eBookGroupAssignment entity
Change Beta Added the windowsProtectionState navigation property to the managedDevice entity
Change Beta Added the installSummary navigation property to the managedEBook entity
Change Beta Removed the outlook navigation property from the user entity
Change Beta Removed the healthStates navigation property from the windowsManagementApp entity
Change Beta Added the androidForWorkRestrictions property to the defaultDeviceEnrollmentRestrictions complex type
Change Beta Added the userPrincipalName and sources properties to the deviceCompliancePolicySettingState complex type
Change Beta Added the userPrincipalName and sources properties to the deviceConfigurationSettingState complex type
Change Beta Added the settingName, userId, userName, userEmail and currentValue properties to the deviceConfigurationSettingState complex type
Change Beta Removed the archiveFolder property from the mailboxSettings complex type

5.4.19 Outlook calendar

Change type Version Description
Addition v1.0 and beta For findMeetingTimes, added new enum value unrestricted that you specify as the activityDomain property, part of the timeConstraint parameter. This lets findMeetingTimes look for times appropriate for the type of activity you’re scheduling for. See details in the request body section.
Addition Beta Support getting an event body in plain text, as an alternative to the default HTML format. See get and list events for details.

5.4.20 Outlook mail

Change type Version Description
Change Beta Support getting a message body in plain text, as an alternative to the default HTML format. See get and list events for details.

5.4.21 Outlook tasks

Change type Version Description
Addition Beta New outlook navigation property added to user, to access Outlook tasks.
Addition Beta New entities - outlookuser, outlookTaskGroup, outlookTaskFolder, and outlookTask - and their methods support organizing and accessing Outlook tasks.
Addition Beta Outlook tasks support attachments (attachment, fileAttachment, itemAttachment, and referenceAttachment resources).
Addition Beta Outlook tasks support extended properties (singleValueLegacyExtendedProperty and multiValueLegacyExtendedProperty resources).

5.4.22 Planner APIs

Change type Version Description
Addition v1.0 Added Planner API.<br />New resources:<br />plannerPlan <br />plannerTask <br />plannerPlanDetails <br />plannerTaskDetails <br />plannerBucket <br />plannerAssignedToTaskBoardTaskFormat <br />plannerBucketTaskBoardTaskFormat <br />plannerProgressTaskBoardTaskFormat

5.4.23 SharePoint sites

Change type Version Description
Addition v1.0 The sites resource is now avaialble in the v1.0 endpoint.<br/> Added the site and siteCollection resource types.
Change beta The format of the identifier for the site resource has changed. This is a breaking change in the beta API.
Removed beta The sharePoint entity has been removed from the beta API. The functionality is now available from the sites collection.

5.4.24 SharePoint Lists

Change type Version Description
Change beta Removed the sharepoint navigation properties. Sites are now accessed directly through the sites navigation property. <br/> Removed the fieldDefinition resource. It has been replaced by columnDefinition. <br/> Removed the siteCollectionId and siteId properties from site. Use sharepointIds instead. <br/> Removed the listItemId property from listItem. Use sharepointIds instead. <br/> Renamed the columnSet property on listItem to fields. <br/> Changed site resources to use the SharePoint hostname as part of their ID.
Addition beta Added the booleanColumn, calculatedColumn, choiceColumn, dateTimeColumn, lookupColumn, numberColumn, personOrGroupColumn, and textColumn resource types. <br/> Added the displayName property to site. <br/> Added the columns navigation property to site. <br/> Added the list and listItem navigation properties to sharedDriveItem. <br/> Added the sharepointIds property to list and listItem, and site. <br/> Added the columnDefinition resource type.

5.5 April 2017

5.5.1 Administrative units property changes

Change type Version Description
Change Beta Adminstrative unit APIs will be updated in preview (beta). The first set of changes will be applied on May 3, 2017. The changes include the following property renaming:<br />- roleMemberInfo complex type to identity complex type for the scopedRoleMembership entity<br />- scopedAdministratorOf navigation property to scopedRoleMemberOf for the user entity<br />- scopedAdministrators navigation property to scopedRoleMembers for the administrativeUnit entity<br />- scopedAdministrators navigation property to scopedMembers for the directoryRole entity

5.5.2 Application and servicePrincipal API changes

Change type Version Description
Change Beta The application and servicePrincipal APIs will be updated in preview (beta). The first set of changes will be applied on May 15, 2017. The changes include property renaming and restructuring. Some properties (such as appRoles and addIns) will not be available until the changes are completed. The changes will be released in preview (beta) prior to releasing to v1.0.

5.5.3 Added preview support for Cloud Solution Provider developers

Change type Version Description
Addition Beta Added new preview capability to allow Cloud Solution Provider pre-consented applications to call Microsoft Graph, described in a new authorization topic.

5.5.4 Added onPremises properties to user entity

Change type Version Description
Addition Beta Added new onPremises properties onPremisesDomainName, OnPremisesSamAccountName, and onPremisesUserPrincipalName to the user entity.

5.5.5 New Planner APIs and an update to the group visibility property

Change type Version Description
Change Beta Added HiddenMembership as an additional value for the visibility property to the Group entity
Addition Beta Added new Planner API.<br />New resources:<br />plannerPlan <br />plannerTask <br />plannerPlanDetails <br />plannerTaskDetails <br />plannerBucket <br />plannerAssignedToTaskBoardTaskFormat <br />plannerBucketTaskBoardTaskFormat <br />plannerProgressTaskBoardTaskFormat

5.5.6 Intune APIs

Change type Version Description
Addition Beta Added new entities:<br/>androidForWorkCompliancePolicy<br/>deviceComplianceSettingState<br/>deviceInstallState<br/>deviceManagementScript<br/>deviceManagementScriptGroupAssignment<br/>deviceManagementScriptState<br/>eBookGroupAssignment<br/>iosVppEBook<br/>managedEBook<br/>userInstallStateSummary<br/>windowsManagementApp<br/>windowsManagementAppHealthState<br/>
Addition Beta Added new complex types:<br/>dailySchedule<br/>hourlySchedule<br/>iosBookmark<br/>iosWebContentFilterAutoFilter<br/>iosWebContentFilterBase<br/>iosWebContentFilterSpecificWebsitesAccess<br/>runSchedule<br/>sharedAppleDeviceUser<br/>windows10NetworkProxyServer<br/>
Addition Beta Added the requestRemoteAssistance action on managedDevice
Addition Beta Added the cleanWindowsDevice action on managedDevice
Addition Beta Added the logoutSharedAppleDeviceActiveUser action on managedDevice
Addition Beta Added the deleteUserFromSharedAppleDevice action on managedDevice
Addition Beta Added the assign action on deviceManagementScript
Addition Beta Added the syncLicenses action on appleVolumePurchaseProgramToken
Addition Beta Added the getTopMobileApps function on mobileApp collection
Addition Beta Added the downloadApplePushNotificationCertificateSigningRequest function on applePushNotificationCertificate
Addition Beta Added the getDeviceComplianceSettingStates function on deviceManagement
Addition Beta Added the deviceConfigurationUserActivity function on reportRoot
Addition Beta Added the deviceConfigurationDeviceActivity function on reportRoot
Deletion Beta Removed the following complex types:<br/>enterpriseCloudResource<br/>windowsInformationProtectionAppRule<br/>windowsInformationProtectionAppRuleAppLockerPolicyFileTemplate<br/>windowsInformationProtectionAppRuleDesktopTemplate<br/>windowsInformationProtectionAppRuleStoreAppTemplate<br/>windowsInformationProtectionAppRuleTemplate<br/>windowsInformationProtectionCorporateNetworkLocation<br/>windowsInformationProtectionProtectedLocation<br/>windowsInformationProtectionProtectedLocationEnterpriseCloudResources<br/>windowsInformationProtectionProtectedLocationEnterpriseInternalProxyServers<br/>windowsInformationProtectionProtectedLocationEnterpriseIPv4Ranges<br/>windowsInformationProtectionProtectedLocationEnterpriseIPv6Ranges<br/>windowsInformationProtectionProtectedLocationEnterpriseNetworkDomainNames<br/>windowsInformationProtectionProtectedLocationEnterpriseProxyServers<br/>windowsInformationProtectionProtectedLocationNeutralResources<br/>
Change Beta Added the deviceSharingAllowed property to the androidGeneralDeviceConfiguration entity
Change Beta Removed the deviceSharingBlocked property from the androidGeneralDeviceConfiguration entity
Change Beta Added the minimumRequiredSdkVersion property to the defaultManagedAppProtection entity
Change Beta Added the windowsManagementAppEnabled property to the deviceAppManagement entity
Change Beta Added the notificationTemplateId property to the deviceComplianceActionItem entity
Change Beta Added the excludeGroup property to the deviceConfigurationGroupAssignment entity
Change Beta Changed the following properties on the iosCustomConfiguration entity:<br/>payloadFileName from required to optional<br/>
Change Beta Added the contentFilterSettings property to the iosDeviceFeaturesConfiguration entity
Change Beta Added the cellularBlockPersonalHotspot and passcodeBlockFingerprintModification properties to the iosGeneralDeviceConfiguration entity
Change Beta Added the minimumRequiredSdkVersion property to the iosManagedAppProtection entity
Change Beta Changed the following properties on the macOSCustomConfiguration entity:<br/>payloadFileName from required to optional<br/>
Change Beta Added the disableAppPinIfDevicePinIsSet, minimumRequiredOsVersion, minimumWarningOsVersion, minimumRequiredAppVersion and minimumWarningAppVersion properties to the managedAppProtection entity
Change Beta Added the remoteAssistanceSessionUrl, isEncrypted, model and manufacturer properties to the managedDevice entity
Change Beta Changed the following properties on the getMobileAppCount entity:<br/>bindingParameter from mobileApp to a collection of mobileApp<br/>status from a GUID to a String<br/>
Change Beta Added the vpnConfigurationId property to the mobileAppGroupAssignment entity
Change Beta Removed the fromEmailAddress property from the notificationMessageTemplate entity
Change Beta Added the excludedApps property to the officeSuiteApp entity
Change Beta Removed the excludedOfficeApps property from the officeSuiteApp entity
Change Beta Added the enabled property to the sharedPCConfiguration entity
Change Beta Added the networkProxyApplySettingsDeviceWide, networkProxyDisableAutoDetect, networkProxyAutomaticConfigurationUrl, networkProxyServer, bluetoothDeviceName, wiFiScanInterval, wirelessDisplayBlockProjectionToThisDevice, wirelessDisplayBlockUserInputFromReceiver, wirelessDisplayRequirePinForPairing, experienceBlockDeviceDiscovery, experienceBlockErrorDialogWhenNoSIM, experienceBlockTaskSwitcher, startMenuPinnedFolderDocuments, startMenuPinnedFolderDownloads, startMenuPinnedFolderFileExplorer, startMenuPinnedFolderHomeGroup, startMenuPinnedFolderMusic, startMenuPinnedFolderNetwork, startMenuPinnedFolderPersonalFolder, startMenuPinnedFolderPictures, startMenuPinnedFolderSettings, startMenuPinnedFolderVideos, startMenuAppListVisibility, startMenuHideFrequentlyUsedApps, startMenuHideRecentJumpLists, startMenuHideRecentlyAddedApps, startMenuHideRestartOptions, startMenuHideUserTile, startMenuHidePowerButton, startMenuLayoutEdgeAssetsXml, personalizationDesktopImageUrl and personalizationLockScreenImageUrl properties to the windows10GeneralConfiguration entity
Change Beta Changed the type of the following properties on the windowsMobileMSI entity:<br/>productCode from Guid to String<br/>
Change Beta Changed the following properties on the windowsPhone81AppX entity:<br/>phoneProductIdentifier from required to optional<br/>phonePublisherId from required to optional<br/>
Change Beta Changed the following properties on the windowsPhone81AppXBundle entity:<br/>appXPackageInformationList from required to optional<br/>
Change Beta Added the productKey and licenseType properties to the windowsStoreForBusinessApp entity
Change Beta Added the previewBuildSetting property to the windowsUpdateForBusinessConfiguration entity
Change Beta Added the windowsManagementApp and managedEBooks navigation properties to the deviceAppManagement entity
Change Beta Added the deviceManagementScripts, managedDeviceOverview and cloudPkiSubscriptions navigation properties to the deviceManagement entity
Change Beta Added the osMinimumVersion and osMaximumVersion properties to the deviceEnrollmentPlatformRestrictions complex type
Change Beta Added the isSharedDevice and sharedDeviceCachedUsers properties to the hardwareInformation complex type
Change Beta Changed the following properties on the omaSettingBase64 complex type:<br/>fileName from required to optional<br/>
Change Beta Changed the following properties on the omaSettingStringXml complex type:<br/>fileName from required to optional<br/>

5.6 March 2017

5.6.1 Intune APIs

Change type Version Description
Addition Beta Added new entities:<br/>androidForWorkApp<br/>androidForWorkAppConfigurationSchema<br/>androidForWorkSettings<br/>androidForWorkVpnConfiguration<br/>applePushNotificationCertificate<br/>complianceSettingStateSummary<br/>deviceCompliancePolicyDeviceStateSummary<br/>deviceCompliancePolicyState<br/>deviceConfigurationDeviceStateSummary<br/>deviceConfigurationState<br/>enterpriseCodeSigningCertificate<br/>iosEduDeviceConfiguration<br/>managedDeviceCertificateState<br/>managedDeviceMobileAppConfigurationDeviceSummary<br/>managedDeviceMobileAppConfigurationUserSummary<br/>mdmWindowsInformationProtectionPolicy<br/>mobileAppInstallSummary<br/>mobileAppProvisioningConfigGroupAssignment<br/>mobileThreatDefenseConnector<br/>officeSuiteApp<br/>settingStateDeviceSummary<br/>softwareUpdateStatusSummary<br/>symantecCodeSigningCertificate<br/>windowsDefenderAdvancedThreatProtectionConfiguration<br/>windowsInformationProtection<br/>windowsInformationProtectionAppLockerFile<br/>windowsInformationProtectionPolicy<br/>windowsMobileMSI<br/>
Addition Beta Added new complex types:<br/>androidForWorkAppConfigurationExample<br/>androidForWorkAppConfigurationExampleJson<br/>androidForWorkAppConfigurationSchemaItem<br/>deviceCompliancePolicySettingState<br/>deviceConfigurationSettingState<br/>deviceExchangeAccessStateSummary<br/>edgeSearchEngine<br/>edgeSearchEngineBase<br/>edgeSearchEngineCustom<br/>excludedApps<br/>iosEduCertificateSettings<br/>ipRange<br/>windowsInformationProtectionApp<br/>windowsInformationProtectionCloudResource<br/>windowsInformationProtectionCloudResourceCollection<br/>windowsInformationProtectionDesktopApp<br/>windowsInformationProtectionIPRangeCollection<br/>windowsInformationProtectionResourceCollection<br/>windowsInformationProtectionStoreApp<br/>
Addition Beta Added the requestSignupUrl action on androidForWorkSettings
Addition Beta Added the completeSignup action on androidForWorkSettings
Addition Beta Added the syncApps action on androidForWorkSettings
Addition Beta Added the unbind action on androidForWorkSettings
Addition Beta Added the assign action on iosLobAppProvisioningConfiguration
Addition Beta Added the recoverPasscode action on managedDevice
Addition Beta Added the removeApplePushNotificationCertificate action on organization
Addition Beta Added the updateMobileAppIdentifierDeployments action on iosManagedAppProtection
Addition Beta Added the updateMobileAppIdentifierDeployments action on androidManagedAppProtection
Addition Beta Added the updateMobileAppIdentifierDeployments action on targetedManagedAppConfiguration
Addition Beta Added the updateTargetedSecurityGroups action on iosManagedAppProtection
Addition Beta Added the updateTargetedSecurityGroups action on androidManagedAppProtection
Addition Beta Added the updateTargetedSecurityGroups action on windowsInformationProtection
Addition Beta Added the updateTargetedSecurityGroups action on windowsInformationProtectionPolicy
Addition Beta Added the updateTargetedSecurityGroups action on mdmWindowsInformationProtectionPolicy
Addition Beta Added the wipeManagedAppRegistrationByDeviceTag action on user
Addition Beta Added the getTopMobileApps function on mobileApp
Addition Beta Added the verifyWindowsEnrollmentAutoDiscovery function on deviceManagement
Deletion Beta Removed the following entities:<br/>appProvisioningConfigGroupAssignment<br/>defaultManagedAppConfiguration<br/>enterpriseCertificate<br/>managedDeviceMobileAppProvisioningConfigurationDeviceStatus<br/>symantecCertificate<br/>windows10WindowsInformationProtectionConfiguration<br/>
Deletion Beta Removed the following complex types:<br/>mobileAppInstallSummary<br/>windowsArchitecture<br/>windowsDeviceType<br/>
Change Beta Added the webBrowserBlockPopups property to the androidGeneralDeviceConfiguration entity
Change Beta Removed the webBrowserAllowPopups property from the androidGeneralDeviceConfiguration entity
Change Beta Added the appIdentifier property to the androidStoreApp entity
Change Beta Removed the applicationCount, failedApplicationCount and appInstallFailures properties from the appReportingOverviewStatus entity
Change Beta Added the sharedIPadMaximumUserCount and enableSharedIPad properties to the depEnrollmentProfile entity
Change Beta Added the shareTokenWithSchoolDataSyncService and lastSyncErrorCode properties to the depOnboardingSetting entity
Change Beta Added the pendingCount, successCount, errorCount, failedCount, lastUpdateDateTime and configurationVersion properties to the deviceComplianceDeviceOverview entity
Change Beta Removed the numberOfPendingDevices, numberOfSucceededDevices, numberOfErrorDevices, numberOfFailedDevices, lastUpdateTime and policyRevision properties from the deviceComplianceDeviceOverview entity
Change Beta Added the pendingCount, successCount, errorCount, failedCount, lastUpdateDateTime and configurationVersion properties to the deviceComplianceUserOverview entity
Change Beta Removed the numberOfPendingUsers, numberOfSucceededUsers, numberOfErrorUsers, numberOfFailedUsers, lastUpdateTime and policyRevision properties from the deviceComplianceUserOverview entity
Change Beta Added the pendingCount, successCount, errorCount, failedCount, lastUpdateDateTime and configurationVersion properties to the deviceConfigurationDeviceOverview entity
Change Beta Removed the numberOfPendingDevices, numberOfSucceededDevices, numberOfErrorDevices, numberOfFailedDevices, lastUpdateTime and policyRevision properties from the deviceConfigurationDeviceOverview entity
Change Beta Added the pendingCount, successCount, errorCount, failedCount, lastUpdateDateTime and configurationVersion properties to the deviceConfigurationUserOverview entity
Change Beta Removed the numberOfPendingUsers, numberOfSucceededUsers, numberOfErrorUsers, numberOfFailedUsers, lastUpdateTime and policyRevision properties from the deviceConfigurationUserOverview entity
Change Beta Added the subscriptionState property to the deviceManagement entity
Change Beta Added the managedEmailProfileRequired property to the iosCompliancePolicy entity
Change Beta Added the appsSingleAppModeList property to the iosGeneralDeviceConfiguration entity
Change Beta Removed the appsSingleAppModeBundleIds property from the iosGeneralDeviceConfiguration entity
Change Beta Added the expirationDateTime property to the iosLobAppProvisioningConfiguration entity
Change Beta Removed the expiration property from the iosLobAppProvisioningConfiguration entity
Change Beta Added the passwordMinimumCharacterSetCount, osMinimumVersion, osMaximumVersion, deviceThreatProtectionEnabled, deviceThreatProtectionRequiredSecurityLevel and storageRequireEncryption properties to the macOSCompliancePolicy entity
Change Beta Removed the manifest property from the managedAndroidLobApp entity
Change Beta Added the isSupervised, exchangeLastSuccessfulSyncDateTime, exchangeAccessState and exchangeAccessStateReason properties to the managedDevice entity
Change Beta Added the deviceExchangeAccessStateSummary property to the managedDeviceOverview entity
Change Beta Removed the manifest property from the managedIOSLobApp entity
Change Beta Removed the installSummary property from the mobileApp entity
Change Beta Added the uploadState property to the mobileAppContentFile entity
Change Beta Changed the following properties on the mobileAppContentFile entity:<br/>azureStorageUriExpirationDateTime from required to optional<br/>
Change Beta Added the initiatedByUserPrincipalName, deviceOwnerUserPrincipalName, deviceIMEI and actionState properties to the remoteActionAudit entity
Change Beta Added the oneDriveDisableFileSync, safeSearchFilter, edgeSearchEngine, settingsBlockSettingsApp, settingsBlockSystemPage, settingsBlockDevicesPage, settingsBlockNetworkInternetPage, settingsBlockPersonalizationPage, settingsBlockAccountsPage, settingsBlockTimeLanguagePage, settingsBlockEaseOfAccessPage, settingsBlockPrivacyPage, settingsBlockUpdateSecurityPage, experienceBlockWindowsSpotlight, experienceBlockWindowsTips, experienceBlockConsumerSpecificFeatures, startMenuLayoutXml, startMenuMode, logonBlockFastUserSwitching and startBlockUnpinningAppsFromTaskbar properties to the windows10GeneralConfiguration entity
Change Beta Added the allowPrinting, allowScreenCapture and allowTextSuggestion properties to the windows10SecureAssessmentConfiguration entity
Change Beta Removed the blockPrinting, blockScreenCapture and blockTextSuggestion properties from the windows10SecureAssessmentConfiguration entity
Change Beta Added the identityName property to the windowsAppX entity
Change Beta Changed the type of the following properties on the windowsAppX entity:<br/>applicableArchitectures from windowsArchitecture to String<br/>
Change Beta Added the identityName property to the windowsPhone81AppX entity
Change Beta Changed the type of the following properties on the windowsPhone81AppX entity:<br/>applicableArchitectures from windowsArchitecture to String<br/>
Change Beta Added the identityName, identityPublisherHash and identityResourceIdentifier properties to the windowsUniversalAppX entity
Change Beta Changed the type of the following properties on the windowsUniversalAppX entity:<br/>applicableArchitectures from windowsArchitecture to String<br/>applicableDeviceTypes from windowsDeviceType to String<br/>
Change Beta Added the restartMode property to the windowsUpdateForBusinessConfiguration entity
Change Beta Added the managedDeviceCertificateStates navigation property to the androidForWorkScepCertificateProfile entity
Change Beta Added the managedDeviceCertificateStates navigation property to the androidScepCertificateProfile entity
Change Beta Added the enterpriseCodeSigningCertificates, symantecCodeSigningCertificate, sideLoadingKeys, managedAppPolicies, iosManagedAppProtections, androidManagedAppProtections, defaultManagedAppProtections, targetedManagedAppConfigurations, mdmWindowsInformationProtectionPolicies, windowsInformationProtectionPolicies, managedAppRegistrations and managedAppStatuses navigation properties to the deviceAppManagement entity
Change Beta Removed the appReportingOverview, enterpriseCerts and symantecCert navigation properties from the deviceAppManagement entity
Change Beta Added the deviceSettingStateSummaries navigation property to the deviceCompliancePolicy entity
Change Beta Added the deviceSettingStateSummaries navigation property to the deviceConfiguration entity
Change Beta Added the termsAndConditions, androidForWorkSettings, androidForWorkAppConfigurationSchemas, applePushNotificationCertificate, softwareUpdateStatusSummary, deviceCompliancePolicyDeviceStateSummary, complianceSettingStateSummaries, deviceConfigurationDeviceStateSummaries and mobileThreatDefenseConnectors navigation properties to the deviceManagement entity
Change Beta Removed the teacherRootCertificates, teacherIdentityCertificate, studentRootCertificates and studentIdentityCertificate navigation properties from the iosEducationDeviceConfiguration entity
Change Beta Changed the type of the following properties on the iosLobAppProvisioningConfiguration entity:<br/>deviceStatuses from managedDeviceMobileAppProvisioningConfigurationDeviceStatus collection to managedDeviceMobileAppConfigurationDeviceStatus collection<br/>groupAssignments from appProvisioningConfigGroupAssignment collection to mobileAppProvisioningConfigGroupAssignment collection<br/>
Change Beta Added the managedDeviceCertificateStates navigation property to the iosScepCertificateProfile entity
Change Beta Added the managedDeviceCertificateStates navigation property to the macOSScepCertificateProfile entity
Change Beta Added the deviceConfigurationStates and deviceCompliancePolicyStates navigation properties to the managedDevice entity
Change Beta Added the deviceStatusSummary and userStatusSummary navigation properties to the managedDeviceMobileAppConfiguration entity
Change Beta Added the installSummary navigation property to the mobileApp entity
Change Beta Removed the sideLoadingKeys navigation property from the organization entity
Change Beta Added the managedDeviceCertificateStates navigation property to the windows81SCEPCertificateProfile entity
Change Beta Added the managedDeviceCertificateStates navigation property to the windowsPhone81SCEPCertificateProfile entity
Change Beta Removed the applicationId, appName, platformId, userFailures and deviceFailures properties from the appInstallationFailure complex type
Change Beta Added the displayName property to the iosHomeScreenFolderPage complex type
Change Beta Added the displayName property to the iosHomeScreenPage complex type
Change Beta Added the subjectName, description, expirationDateTime and certificate properties to the windowsInformationProtectionDataRecoveryCertificate complex type
Change Beta Removed the dataRecoveryCertificate and certificateFileName properties from the windowsInformationProtectionDataRecoveryCertificate complex type
Change Beta Added the displayName property to the windowsPackageInformation complex type
Change Beta Changed the type of the following properties on the windowsPackageInformation complex type:<br/>applicableArchitecture from windowsArchitecture to String<br/>
Change Beta Changed the following properties on the windowsPackageInformation complex type:<br/>applicableArchitecture from optional to required<br/>

5.6.2 Add contracts to Microsoft Graph

Change type Version Description
Addition Beta New resource:</br>contract

5.6.3 Add domain operations to Microsoft Graph

Change type Version Description
Addition Beta Added functions on domains.<br/>New entities:</br>domain<br/>domainDnsRecord<br/>domainDnsCnameRecord<br/>domainDnsMxRecord<br/>domainDnsSrvRecord<br/>domainDnsTxtRecord<br/>domainDnsUnavailableRecord<br/>New actions:</br>forceDelete</br>verify

5.6.4 Add custom data to Microsoft Graph using schema extensions

Change type Version Description
Addition Beta Extend Microsoft Graph with application data by using schema extensions. This is supported on the following resources:<br/>administrative unit<br/>calendar event<br/>device<br/>group<br/>message<br/>organization<br/>personal contact<br/>post<br/>user<br/>See the following example:<br/>Add custom data to groups using Schema Extensions (preview)
Addition Beta Provided an alternative way to create a schema extension definition without requiring a verified .com vanity domain. See schema extensions for details.

5.6.5 Add custom data to Microsoft Graph using open extensions

Change type Version Description
Change v1.0 and beta Renamed former “Office 365 data extensions” as “open extensions”.
Addition Beta Added resources that support open extensions: <br/>administrative unit<br/>device<br/>group<br/>organization<br/>user<br/>See the following example:<br/>Add custom data to users using open extensions (preview)

5.6.6 Directory APIs

Change type Version Description
Addition Beta Added support for restoring and permanently deleting groups.<br/>New entity: directory with deleteditems navigation property.
Addition Beta New entity:</br>Endpoint
Change Beta New endpoints navigation property on groups
Addition Beta New entity:</br>licenseDetails
Change Beta New licensedetails navigation property on users

5.6.7 Reports APIs

Change type Version Description
Addition Beta Introduced the new preview API for Office 365 Reports. You can use it to get usage reports of how people in your business are using Office 365 services. For example, you can identify who is using a service a lot and reaching quotas, or who may not need an Office 365 license at all. For more details, see report.

5.6.8 Directory APIs

Change type Version Description
Addition Beta New entity:</br>contract

5.7 February 2017

5.7.1 Intune APIs

Change type Version Description
Addition Beta Added new entities:<br/>androidForWorkCertificateProfileBase<br/>androidForWorkEasEmailProfileBase<br/>androidForWorkEnterpriseWiFiConfiguration<br/>androidForWorkGmailEasConfiguration<br/>androidForWorkNineWorkEasConfiguration<br/>androidForWorkPkcsCertificateProfile<br/>androidForWorkScepCertificateProfile<br/>androidForWorkTrustedRootCertificate<br/>androidForWorkWiFiConfiguration<br/>appleDeviceFeaturesConfigurationBase<br/>appProvisioningConfigGroupAssignment<br/>deviceComplianceUserOverview<br/>deviceConfigurationUserOverview<br/>enterpriseCertificate<br/>iosEducationDeviceConfiguration<br/>macOSDeviceFeaturesConfiguration<br/>managedAndroidLobApp<br/>managedDeviceMobileAppProvisioningConfigurationDeviceStatus<br/>managedIOSLobApp<br/>managedMobileLobApp<br/>symantecCertificate<br/>windowsAppX<br/>windowsCertificateProfileBase<br/>windowsPhone81AppX<br/>windowsPhone81AppXBundle<br/>windowsPhoneXAP<br/>windowsUniversalAppX<br/>
Addition Beta Added new complex types:<br/>airPrintDestination<br/>windowsArchitecture<br/>windowsDeviceType<br/>windowsMinimumOperatingSystem<br/>windowsPackageInformation<br/>
Addition Beta Added the assign action on the iosLobAppProvisioningConfiguration entity
Addition Beta Added the scheduleActionsForRules action on the deviceCompliancePolicy entity
Addition Beta Added the updateTargetedSecurityGroups action on the targetedManagedAppConfiguration entity
Addition Beta Added the getScopesForUser function on the resourceOperation entity
Change Beta Removed the manifest property from the androidLobApp entity
Change Beta Added the assetTagTemplate, lockScreenFootnote, homeScreenDockIcons and homeScreenPages properties to the iosDeviceFeaturesConfiguration entity
Change Beta Removed the deviceSharingAssetTagInformation, deviceSharingLockScreenFootnote, homeScreenLayoutDockIcons and homeScreenLayoutPages properties from the iosDeviceFeaturesConfiguration entity
Change Beta Added the appsSingleAppModeBundleIds property to the iosGeneralDeviceConfiguration entity
Change Beta Removed the manifest property from the iosLobApp entity
Change Beta Added the createdDateTime, description, lastModifiedDateTime, displayName and version properties to the iosLobAppProvisioningConfiguration entity
Change Beta Added the createdDateTime and lastModifiedDateTime properties to the managedAppPolicy entity
Change Beta Removed the deviceRegistrationState property from the managedDevice entity
Change Beta Added the manifest property to the mobileAppContentFile entity
Change Beta Added the osDescription and userName properties to the mobileAppInstallStatus entity
Change Beta Removed the deviceType property from the mobileAppInstallStatus entity
Change Beta Changed the type of the following properties on the mobileAppInstallStatus entity:<br/>mobileAppInstallStatusValue from Int32 to String
Change Beta Added the targetedSecurityGroupIds and targetedSecurityGroupsCount properties to the targetedManagedAppConfiguration entity
Change Beta Removed the numberOfTargetedSecurityGroups property from the targetedManagedAppConfiguration entity
Change Beta Added the id property to the user entity
Change Beta Removed the renewalThresholdPercentage, keyStorageProvider, subjectNameFormat, subjectAlternativeNameType, certificateValidityPeriodValue and certificateValidityPeriodScale properties from the windows10CertificateProfileBase entity
Change Beta Removed the renewalThresholdPercentage, keyStorageProvider, subjectNameFormat, subjectAlternativeNameType, certificateValidityPeriodValue and certificateValidityPeriodScale properties from the windows81CertificateProfileBase entity
Change Beta Removed the applyToWindows10Mobile property from the windowsPhone81GeneralConfiguration entity
Change Beta Added the enterpriseCerts, iosLobAppProvisioningConfigurations and symantecCert navigation properties to the deviceAppManagement entity
Change Beta Added the userStatusOverview navigation property to the deviceCompliancePolicy entity
Change Beta Added the userStatusOverview navigation property to the deviceConfiguration entity
Change Beta Added the groupAssignments, deviceStatuses and userStatuses navigation properties to the iosLobAppProvisioningConfiguration entity
Change Beta Changed the type of the following properties on the windows10VpnConfiguration entity:<br/>identityCertificate from windows10CertificateProfileBase to windowsCertificateProfileBase
Change Beta Added the deviceComplianceCheckinThresholdDays and isScheduledActionEnabled properties to the deviceManagementSettings complex type
Change Beta Removed the windowsCommercialId and windowsCommercialIdLastModifiedTime properties from the deviceManagementSettings complex type
Change Beta Added the bundleID, appName, publisher, enabled and showOnLockScreen properties to the iosNotificationSettings complex type
Change Beta Removed the bundleIdentifier, notificationsEnabled and showInLockScreen properties from the iosNotificationSettings complex type

5.8 January 2017

5.8.1 Outlook calendar

Change type Version Description
Addition v1.0 New action findMeetingTimes for the user resource.
Addition v1.0 New complex type attendeeBase which consists of a type property for the attendee type.
Addition v1.0 New complex types:<br/>attendeeAvailability<br/>locationConstraint <br/>locationConstraintItem<br/>meetingTimeSuggestion<br/>meetingTimeSuggestionsResult<br/>timeConstraint<br/>timeSlot
Change v1.0 The attendee complex type is now derived from attendeeBase, which in turn is derived from recipient. Including the inherited properties, it consists of the same status, type and emailAddress properties as before.
Addition Beta hexColor added to the calendar resource.

5.8.2 Intune APIs

Change type Version Description
Addition Beta Added new entities: <br/>appReportingOverviewStatus<br/>deviceComplianceDeviceOverview<br/>deviceConfigurationDeviceOverview<br/>deviceManagementExchangeOnpremisesPolicy<br/>iosDeviceFeaturesConfiguration<br/>iosEducationDeviceConfiguration<br/>iosLobAppProvisioningConfiguration<br/>onpremisesConditionalAccessSettings<br/>sharedPCConfiguration<br/>windows10EnterpriseModernAppManagementConfiguration<br/>windows10SecureAssessmentConfiguration<br/>windows10WindowsInformationProtectionConfiguration
Addition Beta Added new complex types: <br/> appInstallationFailure<br/>enterpriseCloudResource<br/>iosHomeScreenApp<br/>iosHomeScreenFolder<br/>iosHomeScreenFolderPage<br/>iosHomeScreenItem<br/>iosHomeScreenPage<br/>iosNotificationSettings<br/>iPv6Range<br/>sharedPCAccountManagerPolicy<br/>windowsInformationProtectionAppRule<br/>windowsInformationProtectionAppRuleAppLockerPolicyFileTemplate<br/>windowsInformationProtectionAppRuleDesktopTemplate<br/>windowsInformationProtectionAppRuleStoreAppTemplate<br/>windowsInformationProtectionAppRuleTemplate<br/>windowsInformationProtectionCorporateNetworkLocation<br/>windowsInformationProtectionDataRecoveryCertificate<br/>windowsInformationProtectionProtectedLocation<br/>windowsInformationProtectionProtectedLocationEnterpriseCloudResources<br/>windowsInformationProtectionProtectedLocationEnterpriseInternalProxyServers<br/>windowsInformationProtectionProtectedLocationEnterpriseIPv4Ranges<br/>windowsInformationProtectionProtectedLocationEnterpriseIPv6Ranges<br/>windowsInformationProtectionProtectedLocationEnterpriseNetworkDomainNames<br/>windowsInformationProtectionProtectedLocationEnterpriseProxyServers<br/>windowsInformationProtectionProtectedLocationNeutralResources
Deletion Beta Removed the following complex types and replaced with microsoft.graph.Json:<br/>managedAppDeploymentSummary <br/>managedAppSummary<br />
Change Beta Replaced the property type appConfigComplianceStatus with complianceStatus on the following entities: <br/>managedDeviceMobileAppConfigurationDeviceStatus<br/>managedDeviceMobileAppConfigurationUserStatus
Change Beta For resource managedAppStatusRaw, changed type of property content from managedAppSummary to Json.
Change Beta Removed the getUsersWithFlaggedAppRegistration function from the managedAppRegistration collection.
Change Beta Changed the vppToken navigation property of the iosVppApp entity to no longer be a contained collection.
Change Beta Added the deviceStatusOverview property to the deviceConfiguration and deviceCompliancePolicy entities.
Change Beta Added the appReportingOverview property to the deviceAppManagement singleton.
Change Beta Added the deviceDisplayName and userPrincipalName properties to the deviceConfigurationDeviceStatus, deviceComplianceDeviceStatus and managedDeviceMobileAppConfigurationDeviceStatus entities.
Change Beta Add the ruleName property to the deviceComplianceScheduledActionForRule entity.
Change Beta Added the devicesCount, userDisplayName and userPrincipalName properties to the deviceConfigurationUserStatus, deviceComplianceUserStatus, and managedDeviceMobileAppConfigurationUserStatus entities.
Change Beta Added the notificationMessageTemplates collection to the deviceManagement singleton.
Change Beta Added the isDefault, lastModifiedDateTime, locale, messageTemplate and subject properties to thelocalizedNotificationMessage entity.
Change Beta Added the azureActiveDirectoryDeviceId, deviceCategory, deviceRegistrationState and managementAgent properties to the managedDevice entity.
Change Beta Added the lastModifiedDateTime property to the mobileAppCategory entity.
Change Beta Added the brandingOptions, defaultLocale, displayName, fromEmailAddress, lastModifiedDateTime, localizedNotificationMessages properties to the notificationMessageTemplate entity.
Change Beta Added the appsAllowTrustedAppsSideloading, appsBlockWindowsStoreOriginatedApps, developerUnlockSetting, edgeBlockAccessToAboutFlags, edgeBlockDeveloperTools, edgeBlockExtensions, edgeBlockInPrivateBrowsing, edgeFirstRunUrl, edgeHomepageUrls, gameDvrBlocked, settingsBlockAddProvisioningPackage, settingsBlockChangeLanguage, settingsBlockChangePowerSleep, settingsBlockChangeRegion, settingsBlockChangeSystemTime, settingsBlockEditDeviceName, settingsBlockRemoveProvisioningPackage, sharedUserAppDataAllowed, smartScreenBlockPromptOverride, smartScreenBlockPromptOverrideForFiles, storageRestrictAppDataToSystemVolume, storageRestrictAppInstallToSystemVolume, webRtcBlockLocalhostIpAddress, windowsStoreBlockAutoUpdate and windowsStoreEnablePrivateStoreOnly properties to the windows10GeneralConfiguration entity.

5.9 December 2016

5.9.1 Delta query

Change type Version Description
Addition Beta A new delta function add to the following entities to perform delta query:<br/>contact<br/>contactFolder<br/>event<br/>group<br/>mailFolder<br/>message<br/>user<br/>See the following for examples:<br/>Get incremental changes to groups (preview)<br/>Get incremental changes to messages in a folder (preview)<br/>Get incremental changes to users (preview)

5.9.2 Excel APIs

Change type Version Description
Addition v1.0 Added workbookPivotTable resource, refresh and refreshAll action on pivotTables, workbookRangeView resource, visibleView action on the filtered range to return workbookRangeView to the user, get rows collection and range resource off of visibleView, columnsAfter, columnsBefore, resizedRange, rowsAbove, and rowsBelow functions off of range resource, and new table properties.

5.9.3 Intune APIs

Change type Version Description
Addition Beta Added resources and method APIs for Microsoft Intune. This is a large set of resources and methods to support the public preview of Intune on Azure Portal. For information about the Intune service, see the Intune documentation. For information about the Intune resources and APIs, see Working with Intune in Microsoft Graph.

5.10 October 2016

5.10.1 Authorization provider

Change type Version Description
Addition v1.0 and beta The v2.0 auth endpoint now supports the client_credentials OAuth grant, which can be used for daemon & long running processes in business scenarios.
Addition v1.0 and beta The v2.0 auth endpoint now supports permission scopes that require administrator’s consent, via the admin consent endpoint.
Addition v1.0 and beta The v2.0 auth endpoint now supports administrative consent for all users in a tenant, via the admin consent endpoint.

5.10.2 Invitation APIs

Change type Version Description
Addition Beta Added invitedUserType property to the invitation entity type, that defines the type of user (Guest or Member) that is invited.
Deletion Beta We will be removing the invitedToGroups property from the invitation entity-type on 11/11/2016. This means that you will no longer be able to add an invited user to a group using this API. Instead, use the add member API to add a user to a group.

5.11 September 2016

5.11.1 Azure AD application proxy

Change type Version Description
Addition Beta Azure AD Application Proxy APIs are now available in the Microsoft Graph beta endpoint. These APIs allow for secure publishing of on-premises applications to users outside the corporate network using Azure AD as the common control plane for access. You can use the published APIs to write applications that can retrieve and update various aspects of application proxy, such as connectors, connectorGroups and the onPremisesPublishing settings of an application.

5.11.2 Drive

Change type Version Description
Addition Beta Added shared collection to allow accessing shared driveItems by shareId or sharing URL.
Addition Beta Added search function to a drive, which allows searching for more items than just those in the drive’s root folder.

5.11.3 DriveItem

Change type Version Description
Addition Beta Added support for createUploadSession, which allows uploading files larger than 4 MB to OneDrive, OneDrive for Business, and SharePoint document libraries.
Addition Beta Added sharepointIds property to driveItem that returns traditional SharePoint API identifiers for driveItems stored in SharePoint.
Addition Beta Added additional properties on remoteItem.
Addition Beta Added the quickXorHash value for files in OneDrive for Business.
Addition Beta Added scope to the createSharingLink to allow creating company sharable links or anonymous sharing links.

5.11.4 Extended properties

Change type Version Description
Addition v1.0 Extended properties are now supported by the following resources: message, mailFolder, event, calendar, contact, contactFolder, group event, group calendar, group post.

5.11.5 Groups

Added support for dynamic group membership through the public preview API, including the additions listed in the following table.

Change type Version Description
Addition Beta Added membershipRule property contains rules that controls the memberships for this group, if the group is a dynamic group.
Addition Beta Added membershipRuleProcessingState property to control whether dynamic membership processing is on or paused for this group.
Addition Beta Set the groupTypes property to contain “DynamicMembership” to light up the dynamic groups capability for this group.
Addition Beta Added preferredLanguage property to indicate the preferred language for an Office 365 group.
Addition Beta Added theme property to specify an Office 365 group’s color theme.

5.11.6 Hybrid deployment support

Change type Version Description
Addition v1.0 Apps can use v1.0 Outlook Mail, Calendar, and Contacts APIs to access on-premises mailboxes in a hybrid deployment with Exchange 2016 Cumulative Update 3 (CU3). Find more details about REST API support in specific hybrid deployments. Note: If you’re using these sets of API in v1.0, you can now find your apps, including production apps, working for on-premises mailboxes that meet the specific hybrid deployment requirements. This capability is only in preview.

5.11.7 IdentityRiskEvents

Change type Version Description
Change Beta As part of the schema change where the type of two location properties is being replaced by a new complex type in the identityRiskEvents endpoint, the following properties are changed/added in the identityRiskEvents endpoint:</br>location changed from Edm.String to ComplexType signInLocation.<br/>previousLocation changed from Edm.String to ComplexType signInLocation.<br/>signInLocation new ComplexType that contains city, state, countryOrRegion and geoCoordinates properties.<br/>geoCoordinates new ComplexType that contains latitude and longitude properties.

5.11.8 Invitation manager

Change type Version Description
Addition Beta Invitation manager APIs are now available in the Microsoft Graph beta endpoint. You can use invitation manager APIs to create an invite, in order to add an external user to the organization. As part of the invitation, you can also choose to add the invited user to an Office 365 group. For more details, see invitation manager.

5.11.9 OneDrive

Change type Version Description
Addition v1.0 Added CreateUploadSession method on driveItem, which allows large file and resumable uploads.
Addition v1.0 Added properties for tracking SharePoint IDs on items from SharePoint (sharepointIds) and a property to identify root folders (root).
Addition v1.0 Added Shares root collection, which can be used with shareIds or sharing links to access shared items in OneDrive and SharePoint. Returns a new type, sharedDriveItem.
Addition v1.0 Added Invite method on driveItem, which allows adding permissions to items.
Addition v1.0 Added Search method on drive, which allows searching across items in the drive and shared items.
Addition v1.0 Added processingMetadata property on file complex type quickXorHash property on hashes complex type.
Addition v1.0 Added quickXorHash property on hashes complex type.

5.11.10 Outlook calendar

Change type Version Description
Addition v1.0 Added the onlineMeetingUrl property to the event resource.
Addition Beta Added forward action to the event resource.
Addition Beta Added the following properties to the calendar resource to support calendar sharing: canEdit, canShare, canViewPrivateItems, isShared, isShareWithMe, and owner.

5.11.11 Outlook mail

Change type Version Description
Addition v1.0 Added the mailboxSettings complex type, which includes the automaticRepliesSetting, timeZone, and language properties.
Addition v1.0 Added the mailboxSettings property to the user resource.
Addition Beta Added support for creating, listing, getting, and deleting one or more instances of mention in a message. Mentions support calling out to get the attention of other users in a message.
Addition Beta Added support for the getMailTips action to get any MailTips for specific recipients. Added the following resources: automaticRepliesMailTips, mailTips, mailTipsError.

5.11.12 Query parameters

Change type Version Description
Change Beta Query parameters without $ prefixes are supported as of 09/26/16. The $ prefix in query parameters is optional. For details, see the Supporting query parameters without $ prefixes in Microsoft Graph blog post.

5.11.13 SharePoint

Change type Version Description
Addition Beta Access to SharePoint sites and lists by ID or path/URL.
Addition Beta Support for listing, creating, getting, and deleting instances of listItem.

5.11.14 Users

Change type Version Description
Addition Beta Added refreshTokensValidFromDateTime read-only property to indicate when refresh or session tokens are valid from. Any tokens issued before this time are invalid, and any attempt to use them would force a new sign-in for the user.
Addition Beta Added showInAddressList property to control if the Outlook global address list should contain this user.
Addition Beta Added invalidateAllRefreshTokens service action that invalidates all of the user’s refresh and session tokens issued to applications, by resetting the refreshTokensValidFromDateTime user property to the current date-time.

5.11.15 Webhooks

Change type Version Description
Addition Beta Added Drive root items to Webhooks as a resource that is available to subscribe to.

5.12 August 2016

5.12.1 Contacts

Change type Version Description
Addition Beta As part of the schema change where a few properties are being removed and corresponding collections are being added to contacts endpoint, the following properties have been added to the contacts endpoint: Websites Collection(ComplexType: Website),Phones Collection (ComplexType: Phone), PostalAddress Collection(ComplexType: PhysicalAddress). For details, see the Upcoming changes to Contacts and People APIs blog post.
Deletion Beta As part of the schema change where a few properties are being removed and corresponding collections are being added to contacts endpoint, the following properties have been removed from the contacts endpoint: BusinessHomePage,HomePhones, MobilePhone1, BusinessPhones, HomeAddress, BusinessAddress, OtherAddress. For details, see the Upcoming changes to Contacts and People APIs blog post.

5.12.2 Excel APIs

Change type Version Description
Addition v1.0 Excel REST API on Microsoft Graph is generally available. Now you can build rich and deep integrations with Excel workbooks in Office 365. See the Power your apps with the new Excel REST API on the Microsoft Graph blog post for more details.

5.12.3 People

Change type Version Description
Change Beta Property WebSite is renamed to Websites. For details, see Upcoming changes to Contacts and People APIs.

5.12.4 Privileged Identity Management

Change type Version Description
Addition Beta Privileged Identity Management (PIM) REST APIs now are available in the Microsoft Graph beta endpoint. Privileged Identity Management provides just in time activation for privileged Azure AD organizational roles such as Global Administrator, Billing Administrator, and so on. You can use the published APIs to write applications that retrieve and update privileged role assignments, and activate users into roles. For details, see Microsoft Graph: Azure AD Privileged Identity Management Preview APIs available in Beta and Azure AD Privileged Identity Management.

5.13 July 2016

5.13.1 Administrative Units

Change type Version Description
Addition Beta Introduced the new Administrative Unites preview API. Administrative units allow organizations to subdivide their Azure Active Directory, and delegate administrative duties to those subdivisions. Subdivisions can represent regions, departments, cost centers, etc. This can now be managed through the Microsoft Graph API.

5.14 June 2016

5.14.1 IdentityRiskEvents

Change type Version Description
Addition Beta Introduced the new IdentityRiskEvents preview API. This API works in conjunction with Azure Active Directory Identity Protection. You can use it to query risk events generated by Identity Protection. For more details, see the Introduction of a new preview API to Microsoft Graph: IdentityRiskEvents blog post.

5.14.2 Subscriptions

Change type Version Description
Addition Beta App-only scopes are now supported for mail and contacts subscriptions.

5.15 May 2016

5.15.1 Calendar

Change type Version Description
Breaking change Beta Changes to the findMeetingTimes API. For more information, see the Microsoft Graph findMeetingTimes API update blog post. This change took effect May 19th, 2016.

5.15.2 Contact

Change type Version Description
Addition v1.0 Added extensions, which is abstract type to support the OData v4 open type openTypeExtension.

5.15.3 Directory

Change type Version Description
Breaking change Beta settingTemplateId is renamed to templateId. This change will take effect May 19th, 2016.

5.15.4 Event

Change type Version Description
Addition v1.0 Added extensions, which is abstract type to support the OData v4 open type openTypeExtension.

5.15.5 EventMessages

Change type Version Description
Addition v1.0 Added inferenceClassification and extensions to eventMessages.
Addition Beta Added responseRequested to eventMessageRequest.

5.15.6 Messages

Change type Version Description
Addition v1.0 Added inferenceClassification and extensions to messages.
Addition Beta Added wellknownname to contactFolder.

5.15.7 Post

Change type Version Description
Addition v1.0 Added extensions, which is abstract type to support the OData v4 open type openTypeExtension.

5.15.8 User

Change type Version Description
Addition v1.0 Added inferenceClassification resource type.
Addition Beta Added timeZone to mailboxsettings.
Addition Beta Added API _findMeetingTimes_to user.|

5.16 April 2016

5.16.1 General

Change type Version Description
Addition v1.0 and Beta Added support for honoring Accept-Encoding:gzip.
Addition v1.0 Added support for cast segment in expand path. For example, ‘https://graph.microsoft.com/v1.0/me/messages?$expand=microsoft.graph.eventMessage/event’.
Addition Beta Added support for PATCH request against structural properties. For example: ‘PATCH /me/mailboxSettings’.
Addition Beta Azure Active Directory is now used as a fallback for /beta/users/id/photo requests when Outlook is unable to service the request, for example when the user has no mailbox license or the tenant does not have an Exchange Online subscription. NOTE: this fallback is available for both GET and PATCH.
Addition Beta Added support for cast segment in expand path. For example: ‘https://graph.microsoft.com/v1.0/me/messages?$expand=microsoft.graph.eventMessage/event’.

5.16.2 OneDrive

Change type Version Description
Fix v1.0 Fixed the issue that OneDrive createLink requests failing with 500 and “Unsupported extension property type.”

5.17 March 2016

5.17.1 Calendar

Change type Version Description
Addition Beta Added singleValueExtendedProperties and multiValueExtendedProperties properties.
Addition Beta Added suggestionHint property to meetingTimeCandidate.
Addition Beta Added locationUri property to location.
Addition Beta Added type and postOfficeBox to physicalAddress.
Change Beta findMeetingTimes now takes new parameter ReturnSuggestionHints.
Change Beta findMeetingTimes now returns a collection of meetingTimeCandidate.

5.17.2 Drive

Change type Version Description
Addition v1.0 and beta Added recent function to list a set of items that have been recently used by the signed in user. This list includes items that are in the user’s drive as well as items they have access tofrom other drives. Example: GET /me/drive/recent.
Addition v1.0 and beta Added sharedWithMe function to list the set of items that are shared with the current user. Example: GET /me/drive/sharedWithMe.

5.17.3 DriveItem

Change type Version Description
Addition v1.0 and beta Added remoteItem type to provide a link to an item in another drive.
Addition v1.0 and beta Added sharingInvitation type to provide details of any associated sharing invitation for this permission.
Addition v1.0 and beta Added delta function to track changes to items in a drive. Example: GET /me/drive/items/{item-id}/delta
Addition v1.0 and beta Added copy that creates a copy of a driveItem (including any children), under a new parent or with a new name. Example: POST /me/drive/items/{item-id}/copy.
Addition v1.0 and beta conflictBehavior instance attributes is now applicable to driveItem.
Addition Beta Added invite function to send a sharing invitation to an existing item. A sharing invitation creates a unique sharing link and sends an email to the recipient of the invitation that includes the sharing link. Example: POST /drive/items/{item-id}/invite.

5.17.4 Event

Change type Version Description
Addition Beta Added new property onlineMeetingUrl and new method cancel.

5.17.5 Event messages

Change type Version Description
Addition Beta Added startDateTime, endDateTime, location, type, recurrence, isOutOfDate, conversationIndex, unsubscribe, unsubscribeData, unsubscribeEnabled and flag properties to eventmessage object.
Addition Beta Added singleValueExtendedProperties and multiValueExtendedProperties properties.
Addition Beta Added new method unsubscribe.

5.17.6 Excel

Change type Version Description
Addition Beta We are adding new Excel REST APIs that let you read and modify data in an Excel workbook. It is now possible to build smart apps that allows users to get value out of the content stored in an Excel workbook by providing insights into the data. Take advantage of analytical powers of Excel, create tables and charts and extract visually appealing chart image - all from within your app. For details, see Working with Excel in Microsoft Graph.

5.17.7 General

Change type Version Description
Addition v1.0 and beta Improved error message when resolving tenant alias and rejected JWT (AAD) tokens.
Addition v1.0 and beta The location of the authorization service endpoint is now returned in the www-authenticate header when a request is received with an empty bearer token.
Addition v1.0 and beta The ability to filter on an entity’s id property is now fixed. Example: GET https://graph.microsoft.com/v1.0/users?$filter=id+eq+'x’<br/>Previously, any POST requests to service actions and functions require prefixing the action or function name with the microsoft.graph prefix. For example: POST https://graph.microsoft.com/v1.0/me/Microsoft.Graph.getMemberGroups.<br/>The prefix is now no longer required (although it can still be specified). So the following would now also work: POST https://graph.microsoft.com/v1.0/me/getMemberGroups.
Change Beta Cleaned up subscription property names.
Addition Beta We’ve added the capability to discover (through directorySettingTemplates) and override the default behavior (by creating a setting from the template) for entities and their associated functionality. Initially this only template provided is to control behaviors on Office groups.

5.17.8 Mail folder

Change type Version Description
Addition Beta Added wellKnownName and userConfigurations properties.
Addition Beta Added singleValueExtendedProperties and multiValueExtendedProperties properties

5.17.9 Messages

Change type Version Description
Addition v1.0 Added mobilePhone property.
Addition v1.0 and beta Added internetMessageId property. The message ID in the format specified by RFC2822.
Change Beta Renamed mobilePhone1 property to mobilePhone.
Change Beta createReply and _createReplyAll_take new parameter Message and comment.|
|Change|Beta|createForward takes new parameter Message, ToRecipients and comment.|
|Change|Beta|reply, replyAll and forward take new parameter Message.|

5.17.10 Permission

Change type Version Description
Addition v1.0 and beta Added sharingInvitation property to provide details of any associated sharing invitation for this permission.

5.17.11 Person

Change type Version Description
Addition Beta Added new properties birthday, personNotes, isFavorite, phones, permission, postalAddresses,websites,yomiCompany, department, profession, mailboxType and personType.
Addition Beta Added new enum types physicalAddressType, webSite, phone and webSiteType.

5.17.12 Reference attachment

Change type Version Description
Addition Beta Added new properties sourceUrl, providerType, thumbnailUrl, previewUrl, permission and isFolder.
Addition Beta Added singleValueExtendedProperties and multiValueExtendedProperties properties.
Addition Beta Added new enum types referenceAttachmentProvider and referenceAttachmentPermission.

5.17.13 Subscriptions

Change type Endpoint Description
Addition v1.0 Webhooks are now GA on V1.0 endpoint via the /Subscriptions resource. Create, Read, Renew and Delete subscriptions to receive notifications on data from Outlook and Office 365 group conversations.

5.17.14 User

Change type Version Description
Addition Beta Added mailboxSettings property and corresponding types.

5.18 February 2016

5.18.1 DriveItem

Change type Version Description
Addition v1.0 and beta New remoteItem property on driveItem for Microsoft accounts.

5.18.2 General

Change type Version Description
Change v1.0 and beta -/me/drive now works for both Microsoft accounts and Work and School accounts.
Change v1.0 and beta Drive requests for accounts whose OneDrive storage was provisioned on demand work more reliably and work in more scenarios where tenant default SharePoint sites use non-standard names.
Deletion Beta Removed various unimplemented types from the beta schema to more closely match the 1.0 schema.

5.18.3 Subscriptions

Change type Version Description
Addition Beta notificationUrl validation on subscription creation. For details, see Microsoft Graph WebHooks Update - January 2016.
Addition Beta Subscription entities can now be deleted: DELETE https://graph.microsoft.com/beta/subscriptions/

5.18.4 Users

Change type Version Description
Change v1.0 and beta displayName is now returned for Microsoft accounts.

5.19 January 2016

5.19.1 Contacts

Change type Version Description
Addition v1.0 Added mobilePhone property to personal contacts entity-set.

5.19.2 directoryObjects

Change type Version Description
Fix v1.0 and beta Fixed calling actions that are bound to directoryObjects, which were failing with the following error: The return type from the operation is not possible with the given entity set. This applies to the following actions: microsoft.graph.checkMemberObjects, microsoft.graph.getMemberObjects, microsoft.graph.checkMemberGroups, microsoft.graph.assignLicense, microsoft.graph.changePassword.

5.20 December 2015

5.20.1 Contacts

Change type Version Description
Addition Beta Added mobilePhone property to personal contacts entity-set.

5.20.2 General

Change type Version Description
Fix v1.0 and beta Fixed requests using $filter expressions that specified the same property more than once, which were failing with the following 500 error: An item with the same key has already been added.
Fix v1.0 and beta Fixed case insensitivity for action parameter names and values.
Fix v1.0 and beta Fixed request processing for payloads containing null values for some embedded complex properties, which were failing with a null reference exception.
Addition v1.0 and beta Added support for complex type property sorting and filtering.
Addition v1.0 and beta Added authorization_uri property in the www-authenticate header on a 401 response. This uri can be used to start the token acquisition flow.
Addition v1.0 and beta Improved error messages across users and groups.

5.20.3 Groups

Change type Version Description
Fix v1.0 and beta Fixed calling the following group actions: microsoft.graph.addFavorite, microsoft.graph.removeFavorite and microsoft.graph.resetUnseenCount.

5.20.4 Messages

Change type Version Description
Addition Beta Added eventMessageRequest subtype of eventMessage and startDateTime, endDateTime, location, type, recurrence and isOutOfDate properties to eventMessage type.

5.20.5 Users

Change type Version Description
Fix v1.0 and beta Fixed being able to select certain user properties on other users, when referencing the user by user principal name (UPN). For example: https://graph.microsoft.com/v1.0/users/anotherUser@contoso.com?$select=aboutMe
Fix v1.0 and beta Fixed calling the microsoft.graph.reminderView user bound function, which was failing with the following error: Could not find a property named businessPhones on type Microsoft.OutlookServices.Reminder.
Fix v1.0 and beta Fixed user creation and update (POST/PATCH /v1.0/users), which was failing with a 400 error.

6 Get incremental changes to events in a calendar view

A calendar view is a collection of events in a date/time range from the default calendar (../me/calendarview)
or some other calendar of the user’s. By using delta query, you can get
new, updated, or deleted events in a calendar view.
The returned events may include occurrences and exceptions of a recurring series,
and single instances. The delta data enables you to maintain
and synchronize a local store of a user’s events,
without having to fetch the entire set of the user’s events from the server every time.

Delta query supports both full synchronization that retrieves all the events in the specified calendar view,
and incremental synchronization that retrieves those events that have changed in the calendar view since
the last synchronization. Typically, you would do an initial full synchronization, and
subsequently, get incremental changes to that calendar view periodically.

6.1 Track event changes in a calendar view

Delta query for events is specific to a calendar and date/time range that you specify (i.e., a calendar view). To track the changes in multiple calendars,
you need to track each calendar individually.

Tracking event changes in a calendar view typically is a round of one or more GET requests with
the delta function. The initial GET
request is very much like the way you list a calendarView,
except that you include the delta function:

GET /me/calendarView/delta?startDateTime={start_datetime}&endDateTime={end_datetime}

A GET request with the delta function returns either:

  • A nextLink (that contains a URL with a delta function call and a skipToken), or
  • A deltaLink (that contains a URL with a delta function call and deltaToken).

These tokens are state tokens which encode the refs/remotes/microsoftgraph/master
startDateTime and endDateTime parameters, and any other query parameter
in your initial delta query GET request.

State tokens are completely opaque to the client.
To proceed with a round of change tracking, simply copy and apply the nextLink or
deltaLink URL returned from the last GET
request to the next delta function call for that same calendar view. A deltaLink returned in a response
signifies that the current round of change tracking is complete. You can save and use the deltaLink URL
when you begin the next round.

See the example below to learn how to use these nextLink and
deltaLink URLs.

6.1.1 Use query parameters in a delta query for calendar view

  • Include the startDateTime and endDateTime parameters to define a date/time range for your calendar view.
  • $select is not supported.

6.1.2 Optional request header

Each delta query GET request returns a collection of one or more events in the response. You can optionally specify
the request header, Prefer: odata.maxpagesize={x}, to set the maximum number of events in a response.

6.2 Example to synchronize events in a calendar view

The following example shows a series of 3 requests to synchronize the user’s default calendar in a specific time range.
There are 5 events in that calendar view.

For brevity, the sample responses show only a subset of the properties for an event. In an actual call, most event properties
are returned.

See also what you’ll do in the next round.

6.2.1 Step 1: sample initial request

In this example, the specified calendar view is being synchronized for the first time, so the initial sync request does not include any state token.
This round will return all the events in that calendar view.

The first request specifies the following:

  • Date/time values for the startDateTime and endDateTime parameters.
  • The optional request header, odata.maxpagesize, returning 2 events at a time.

<!– {
“blockType”: “request”,
“name”: “get_calendarview_delta_1”
}–>

GET https://graph.microsoft.com/v1.0/me/calendarview/delta?startdatetime=2016-12-01T00:00:00Z&enddatetime=2016-12-30T00:00:00Z HTTP/1.1
Prefer: odata.maxpagesize=2

6.2.2 Sample initial response

The response includes two events and a @odata.nextLink response header with a skipToken.
The nextLink URL indicates there are more events in the calendar view to get.

<!– {
“blockType”: “response”,
“truncated”: true,
: “microsoft.graph.event”,
“isCollection”: true
} –>

HTTP/1.1 200 OK
Content-type: application/json

{
    "@odata.context":"https://graph.microsoft.com/v1.0/$metadata#Collection(event)",
    "@odata.nextLink":"https://graph.microsoft.com/v1.0/me/calendarview/delta?$skiptoken=R0usmcCM996atia_s",
    "value":[
        {
            "@odata.type":"#microsoft.graph.event",
            "@odata.etag":"W/\"EZ9r3czxY0m2jz8c45czkwAAFXcvIQ==\"",
            "subject":"Plan shopping list",
            "body":{
                "contentType":"html",
                "content":""
            },
            "start":{
                "dateTime":"2016-12-09T20:30:00.0000000",
                "timeZone":"UTC"
            },
            "end":{
                "dateTime":"2016-12-09T22:00:00.0000000",
                "timeZone":"UTC"
            },
            "attendees":[

            ],
            "organizer":{
                "emailAddress":{
                    "name":"Fanny Downs",
                    "address":"fannyd@contoso.onmicrosoft.com"
                }
            },      
            "id":"AAMkADNVxRAAA="
        },
        {
            "@odata.type":"#microsoft.graph.event",
            "@odata.etag":"W/\"EZ9r3czxY0m2jz8c45czkwAAFXcvIg==\"",
            "subject":"Pick up car",
            "body":{
                "contentType":"html",
                "content":""
            },
            "start":{
                "dateTime":"2016-12-10T01:00:00.0000000",
                "timeZone":"UTC"
            },
            "end":{
                "dateTime":"2016-12-10T02:00:00.0000000",
                "timeZone":"UTC"
            },
            "attendees":[

            ],
            "organizer":{
                "emailAddress":{
                    "name":"Fanny Downs",
                    "address":"fannyd@contoso.onmicrosoft.com"
                }
            },
            "id":"AAMkADVxSAAA="
        }
    ]
}

6.2.3 Step 2: sample second request

The second request specifies the nextLink URL returned from the previous response. Notice that it no longer has to specify
the same startDateTime and endDateTime parameters as in the initial request, as the skipToken in the nextLink URL encodes and includes them.

<!– {
“blockType”: “request”,
“name”: “get_calendarview_delta_2”
}–>

GET https://graph.microsoft.com/v1.0/me/calendarview/delta?$skiptoken=R0usmcCM996atia_s HTTP/1.1
Prefer: odata.maxpagesize=2

6.2.4 Sample second response

The second response returns the next 2 events in the calendar view and another nextLink, indicating there are
more events to get from the calendar view.

<!– {
“blockType”: “response”,
“truncated”: true,
: “microsoft.graph.event”,
“isCollection”: true
} –>

HTTP/1.1 200 OK
Content-type: application/json

{
    "@odata.context":"https://graph.microsoft.com/v1.0/$metadata#Collection(event)",
    "@odata.nextLink":"https://graph.microsoft.com/v1.0/me/calendarview/delta?$skiptoken=R0usmci39OQxqJrxK4",
    "value":[
        {
            "@odata.type":"#microsoft.graph.event",
            "@odata.etag":"W/\"EZ9r3czxY0m2jz8c45czkwAAFXcvIw==\"",
            "subject":"Get food",
            "body":{
                "contentType":"html",
                "content":""
            },
            "start":{
                "dateTime":"2016-12-10T19:30:00.0000000",
                "timeZone":"UTC"
            },
            "end":{
                "dateTime":"2016-12-10T21:30:00.0000000",
                "timeZone":"UTC"
            },
            "attendees":[

            ],
            "organizer":{
                "emailAddress":{
                    "name":"Fanny Downs",
                    "address":"fannyd@contoso.onmicrosoft.com"
                }
            },
            "id":"AAMkADVxTAAA="
        },
        {
            "@odata.type":"#microsoft.graph.event",
            "@odata.etag":"W/\"EZ9r3czxY0m2jz8c45czkwAAFXcvJA==\"",
            "subject":"Prepare food",
            "body":{
                "contentType":"html",
                "content":""
            },
            "start":{
                "dateTime":"2016-12-10T22:00:00.0000000",
                "timeZone":"UTC"
            },
            "end":{
                "dateTime":"2016-12-11T00:00:00.0000000",
                "timeZone":"UTC"
            },
            "attendees":[

            ],
            "organizer":{
                "emailAddress":{
                    "name":"Fanny Downs",
                    "address":"fannyd@contoso.onmicrosoft.com"
                }
            },
            "id":"AAMkADVxUAAA="
        }
    ]
}

6.2.5 Step 3: sample third request

The third request continues to use the latest nextLink returned from the last sync request.

<!– {
“blockType”: “request”,
“name”: “get_calendarview_delta_3”
}–>

GET https://graph.microsoft.com/v1.0/me/calendarview/delta?$skiptoken=R0usmci39OQxqJrxK4 HTTP/1.1
Prefer: odata.maxpagesize=2

6.2.6 Sample third and final response

The third response returns the only remaining event in the calendar view, and a deltaLink URL which indicates
synchronization is complete for this calendar view. Save and use the deltaLink URL to
synchronize that calendar view in the next round.

<!– {
“blockType”: “response”,
“truncated”: true,
: “microsoft.graph.event”,
“isCollection”: true
} –>

HTTP/1.1 200 OK
Content-type: application/json

{
    "@odata.context":"https://graph.microsoft.com/v1.0/$metadata#Collection(event)",
    "@odata.deltaLink":"https://graph.microsoft.com/v1.0/me/calendarview/delta?$deltatoken=R0usmcMDNGg0J1E",
    "value":[
        {
            "@odata.type":"#microsoft.graph.event",
            "@odata.etag":"W/\"EZ9r3czxY0m2jz8c45czkwAALZu97g==\"",
            "subject":"Rest!",
            "body":{
                "contentType":"html",
                "content":""
            },
            "start":{
                "dateTime":"2016-12-12T02:00:00.0000000",
                "timeZone":"UTC"
            },
            "end":{
                "dateTime":"2016-12-12T07:30:00.0000000",
                "timeZone":"UTC"
            },
            "location":{
                "displayName":"Home"
            },
            "attendees":[

            ],
            "organizer":{
                "emailAddress":{
                    "name":"Fanny Downs",
                    "address":"fannyd@contoso.onmicrosoft.com"
                }
            },
            "id":"AAMkADj1HuAAA="
        }
    ]
}

6.2.7 The next round: sample first request

Using the deltaLink from the last request in the last round,
you will be able to get only those events that have changed (by being added, deleted, or updated) in that calendar view since then.
Your first request in the next round will look like the following, assuming you prefer to keep the same maximum page size in the response:

<!– {
“blockType”: “request”,
“name”: “get_calendarview_delta_next”
}–>

GET https://graph.microsoft.com/v1.0/me/calendarview/delta?$deltatoken=R0usmcMDNGg0J1E HTTP/1.1
Prefer: odata.maxpagesize=2

6.2.8 The next round: sample first response

<!– {
“blockType”: “response”,
“truncated”: true,
: “microsoft.graph.event”,
“isCollection”: true
} –>

HTTP/1.1 200 OK
Content-type: application/json

{
    "@odata.context":"https://graph.microsoft.com/v1.0/$metadata#Collection(event)",
    "@odata.deltaLink":"https://graph.microsoft.com/v1.0/me/calendarview/delta?$deltatoken=R0usmcFuQtZdtpk4",
    "value":[
        {
            "@odata.type":"#microsoft.graph.event",
            "@odata.etag":"W/\"EZ9r3czxY0m2jz8c45czkwAALZu97w==\"",
            "subject":"Attend service",
            "body":{
                "contentType":"html",
                "content":""
            },
            "start":{
                "dateTime":"2016-12-25T06:00:00.0000000",
                "timeZone":"UTC"
            },
            "end":{
                "dateTime":"2016-12-25T07:30:00.0000000",
                "timeZone":"UTC"
            },
            "location":{
                "displayName":"Chapel of Saint Ignatius",
                "address":{
                    "type":"unknown",
                    "street":"900 Broadway",
                    "city":"Seattle",
                    "state":"WA",
                    "countryOrRegion":"United States",
                    "postalCode":""
                },
                "coordinates":{
                    "latitude":47.6105,
                    "longitude":-122.321
                }
            },
            "attendees":[

            ],
            "organizer":{
                "emailAddress":{
                    "name":"Fanny Downs",
                    "address":"fannyd@contoso.onmicrosoft.com"
                }
            },
            "id":"AAMkADj1HvAAA="
        }
    ]
}

6.3 See also

7 Get incremental changes for groups

Delta query lets you query for additions, deletions, or updates to groups, by way of a series of delta function calls. Delta query enables you discover changes to groups
without having to fetch the entire set of groups from Microsoft Graph and compare changes.

Clients using synchronizing groups with a local profile store can use Delta Query for both their initial full synchronization along with incremental synchronizations in the future. Typically, a client would do an initial full synchronization of all the groups in a tenant, and subsequently, get incremental changes to groups periodically.

7.1 Tracking group changes

Tracking group changes is a round of one or more GET requests with the delta function. You make a GET
request much like the way you list groups, except that you include the following:

  • The delta function.
  • A state token (deltaToken or skipToken) from the previous GET delta function call.

7.2 Example

The following example shows a series requests to track changes to groups:

  1. Initial request and response
  2. nextLink request and response
  3. Final nextLink request and response
  4. deltaLink request and deltaLink response

7.3 Initial request

To begin tracking changes in the group resource, you make a request including the delta function on the group resource.

Note the following:

  • The optional $select query parameter is included in the request to demonstrate how query parameters are automatically included in future requests.
  • The initial request does not include a state token. State tokens will be used in subsequent requests.
GET https://graph.microsoft.com/v1.0/groups/delta?$select=displayName,description

7.4 Initial response

If successful, this method returns 200 OK response code and group collection object in the response body. Assuming the entire set of groups is too large, the response will also include a nextLink state token.

In this example, a nextLink URL is returned indicating there are additional pages of data to be retrieved in the session. The $select query parameter from the initial request is encoded into the nextLink URL.

HTTP/1.1 200 OK
Content-type: application/json

{
  "@odata.context":"https://graph.microsoft.com/v1.0/$metadata#groups(displayName,description)",
  "@odata.nextLink":"https://graph.microsoft.com/v1.0/groups/delta?$skiptoken=pqwSUjGYvb3jQpbwVAwEL7yuI3dU1LecfkkfLPtnIjvB7XnF_yllFsCrZJ",
  "value": [
    {
      "displayName":"TestGroup1",
      "description":"Employees in test group 1",
      "id":"c2f798fd-f95d-4623-8824-63aec21fffff"
    },
    {
      "displayName":"TestGroup2",
      "description":"Employees in test group 2",
      "id":"ec22655c-8eb2-432a-b4ea-8b8a254bffff"
    }
  ]
}

The second request specifies the skipToken returned from the previous response. Notice the $select parameter is not required, as the skipToken encodes and includes it.

GET https://graph.microsoft.com/v1.0/groups/delta?$skiptoken=pqwSUjGYvb3jQpbwVAwEL7yuI3dU1LecfkkfLPtnIjvB7XnF_yllFsCrZJ

The response contains a nextLink and another skipToken, indicating there are more groups available. You continue making requests using the nextLink URL until a deltaLink URL is returned in the response.

HTTP/1.1 200 OK
Content-type: application/json

{
  "@odata.context":"https://graph.microsoft.com/v1.0/$metadata#groups",
  "@odata.nextLink":"https://graph.microsoft.com/v1.0/groups/delta?$skiptoken=pqwSUjGYvb3jQpbwVAwEL7yuI3dU1LecfkkfLPtnIjtQ5LOhVoS7qQG_wdVCHHlbQpga7",
  "value": [
    {
      "displayName":"TestGroup3",
      "description":"Employees in test group 3",
      "id":"2e5807ce-58f3-4a94-9b37-ffff2e085957"
    },
    {
      "displayName":"TestGroup4",
      "description":"Employees in test group 4",
      "id":"421e797f-9406-4934-b778-4908421e3505"
    }
  ]
}

The third request continues to use the latest skipToken returned from the last sync request.

GET https://graph.microsoft.com/v1.0/groups/delta?$skiptoken=ppqwSUjGYvb3jQpbwVAwEL7yuI3dU1LecfkkfLPtnIjtQ5LOhVoS7qQG_wdVCHHlbQpga7

When the deltaLink URL is returned, there is no more data about the existing state of the resource to be returned. For future requests, the application uses the deltaLink URL to learn about changes to the resource. Save the deltaToken and use it in the request URL to discover changes to groups.

HTTP/1.1 200 OK
Content-type: application/json

{
  "@odata.context":"https://graph.microsoft.com/v1.0/$metadata#groups",
  "@odata.deltaLink":"https://graph.microsoft.com/v1.0/groups/delta?$deltatoken=sZwAFZibx-LQOdZIo1hHhmmDhHzCY0Hs6snoIHJCSIfCHdqKdWNZ2VX3kErpyna9GygROwBk-rqWWMFxJC3pw",
  "value": [
    {
      "displayName":"TestGroup5",
      "description":"Employees in test group 5",
      "id":"bed7f0d4-750e-4e7e-ffff-169002d06fc9"
    },
    {
      "displayName":"TestGroup6",
      "description":"Employees in test group 6",
      "id":"421e797f-9406-ffff-b778-4908421e3505"
    }
  ]
}

Using the deltaToken from the last response, you will be able to get changed (by being added, deleted, or updated) groups since the last request.

GET https://graph.microsoft.com/v1.0/groups/delta?$deltatoken=sZwAFZibx-LQOdZIo1hHhmmDhHzCY0Hs6snoIHJCSIfCHdqKdWNZ2VX3kErpyna9GygROwBk-rqWWMFxJC3pw

If no changes have occurred, the same deltatoken is returned with no results.

HTTP/1.1 200 OK
Content-type: application/json

{
  "@odata.context":"https://graph.microsoft.com/v1.0/$metadata#groups",
  "@odata.deltaLink":"https://graph.microsoft.com/v1.0/groups/delta?$deltatoken=sZwAFZibx-LQOdZIo1hHhmmDhHzCY0Hs6snoIHJCSIfCHdqKdWNZ2VX3kErpyna9GygROwBk-rqWWMFxJC3pw",
  "value": []
}

If changes have occurred, the same deltatoken is returned including a collection of changed groups.

HTTP/1.1 200 OK
Content-type: application/json

{
  "@odata.context":"https://graph.microsoft.com/v1.0/$metadata#groups",
  "@odata.deltaLink":"https://graph.microsoft.com/v1.0/groups/delta?$deltatoken=sZwAFZibx-LQOdZIo1hHhmmDhHzCY0Hs6snoIHJCSIfCHdqKdWNZ2VX3kErpyna9GygROwBk-rqWWMFxJC3pw",
  "value": [
    {
      "displayName":"TestGroup7",
      "description":"Employees in test group 7",
      "id":"f764235c-ffff-4843-a14a-1d8826967260"
    }
  ]
}

7.11 See also

Microsoft Graph delta query overview.

8 Get incremental changes to messages in a folder

Delta query lets you query for additions, deletions, or updates to messages in a folder, by way of a series of
delta function calls. Delta data enables you to maintain
and synchronize a local store of a user’s messages,
without having to fetch the entire set of the user’s messages from the server every time.

Delta query supports both full synchronization that retrieves all of the messages in a folder (for example, the user’s Inbox),
and incremental synchronization that retrieves all of the messages that have changed in that folder since
the last synchronization. Typically, you would do an initial full synchronization of all the messages in a folder, and
subsequently, get incremental changes to that folder periodically.

8.1 Track message changes in a folder

Delta query is a per-folder operation. To track the changes of the messages in a folder hierarchy, you need to track each folder individually.

Tracking message changes in a mail folder typically is a round of one or more GET requests with the delta function. The initial GET
request is very much like the way you get messages,
except that you include the delta function:

GET https://graph.microsoft.com/v1.0/me/mailFolders/{id}/messages/delta

A GET request with the delta function returns either:

  • A nextLink (that contains a URL with a delta function call and a skipToken), or
  • A deltaLink (that contains a URL with a delta function call and deltaToken).

These tokens are state tokens that are completely opaque to the client.
To proceed with a round of change tracking, simply copy and apply the URL returned from the last GET
request to the next delta function call for the same folder. A deltaLink returned in a response
signifies that the current round of change tracking is complete. You can save and use the deltaLink URL
when you begin the next round.

See the example below to learn how to use the nextLink and
deltaLink URLs.

8.1.1 Use query parameters in a delta query for messages

  • You can use a $select query parameter as in any GET request to specify only the properties your need for best performance. The
    id property is always returned.
  • Delta query support $select, $top, and $expand for messages.
  • There is limited support for $filter and $orderby:
  • The only supported $filter expresssions are $filter=receivedDateTime+ge+{value}
    or $filter=receivedDateTime+gt+{value}.
  • The only supported $orderby expression is $orderby=receivedDateTime+desc. If you do not include
    an $orderby expression, the return order is not guaranteed.
  • There is no support for $search.

8.1.2 Optional request header

Each delta query GET request returns a collection of one or more messages in the response. You can optionally specify
the request header, Prefer: odata.maxpagesize={x}, to set the maximum number of messages in a response.

<!–

8.1.3 Iterative process

A typical round to track message changes goes like this:

  1. Make the initial GET request with the mandatory Prefer: odata.track-changes header. If this is your very first delta query
    for messages in that folder, don’t provide any state token. If the messages support tracking changes, following the iterative
    process (steps 2-6) described below will return the entire set of messages in that folder.

  2. Check if the first response returns the Preference-Applied: odata.track-changes header,
    which confirms your resource supports tracking changes. Stop if you don’t receive the response header.

  3. If you receive a skipToken (in an _ response header) in the response, you should continue to track the
    additional messages that have changed (added, deleted, or updated). Make a second GET request, using the URL returned
    in , which includes a skipToken.

  4. The second request will return additional messages that have changed, and either a skipToken if there are more changed messages,
    or a deltaToken if all the changed messages have been returned.

  5. If you receive a skipToken from the last GET request, continue getting the changes by sending a next GET call, similar to step 3.

  6. When you eventually receive a detlaToken (in an @odata.deltaLink_ response header) in the response from a GET, stop. This
    round of change tracking is complete.

  7. Save the deltaToken. The next time you track changes for the same folder, make a GET request
    similar to step 1, except that now you can use this deltaToken to get just the delta data (messages that have been added, deleted or updated)
    since the completion of the very first round.

–>

8.2 Example to synchronize messages in a folder

The following example shows a series of 3 requests to synchronize a specific folder which contains 5 messages:

See also what you’ll do in the next round.

8.2.1 Sample initial request

In this example, the specified folder is being synchronized for the first time, so the initial sync request does not include any state token.
This round will return all the messages in that folder.

The first request specifies the following:

  • A $select parameter to return the Subject and Sender properties for each message in the response.
  • The optional request header, odata.maxpagesize, returning 2 messages at a time.

<!– {
“blockType”: “request”,
“name”: “get_messages_delta_1”
}–>

GET https://graph.microsoft.com/v1.0/me/mailfolders('AQMkADNkNAAAgEMAAAA')/messages/delta?$select=Subject,Sender HTTP/1.1
Prefer: odata.maxpagesize=2

8.2.2 Sample initial response

The response includes two messages and an @odata.nextLink response header.
The nextLink URL indicates there are more messages in the folder to get.

<!– {
“blockType”: “response”,
“truncated”: true,
: “microsoft.graph.message”,
“isCollection”: true
} –>

{
    "@odata.context":"https://graph.microsoft.com/v1.0/$metadata#Collection(message)",
    "@odata.nextLink":"https://graph.microsoft.com/v1.0/me/mailfolders('AQMkADNkNAAAgEMAAAA')/messages/delta?$skiptoken=GwcBoTmPuoTQWfcsAbkYM",
    "value":[
        {
            "@odata.type":"#microsoft.graph.message",
            "@odata.etag":"W/\"CQAAABYAAAARn2vdzPFjSbaPPxzjlzOTAAASsKZz\"",
            "subject":"Holiday hours update",
            "sender":{
                "emailAddress":{
                    "name":"Dana Swope",
                    "address":"danas@contoso.onmicrosoft.com"
                }
            },
            "id":"AAMkADNkNAAASq35xAAA="
        },
        {
            "@odata.type":"#microsoft.graph.message",
            "@odata.etag":"W/\"CQAAABYAAAARn2vdzPFjSbaPPxzjlzOTAAAEfYB/\"",
            "subject":"Holiday promotion sale",
            "sender":{
                "emailAddress":{
                    "name":"Fanny Downs",
                    "address":"fannyd@contoso.onmicrosoft.com"
                }
            },
            "id":"AQMkADNkNAAAVRMKAAAAA=="
        }
    ]
}

8.2.3 Sample second request

The second request specifies the nextLink URL returned from the previous response. Notice that it no longer has to specify
the same $select parameter as in the initial request, as the skipToken in the nextLink URL encodes and includes it.

<!– {
“blockType”: “request”,
“name”: “get_messages_delta_2”
}–>

GET https://graph.microsoft.com/v1.0/me/mailfolders('AQMkADNkNAAAgEMAAAA')/messages/delta?$skiptoken=GwcBoTmPuoTQWfcsAbkYM HTTP/1.1
Prefer: odata.maxpagesize=2

8.2.4 Sample second response

The second response returns the next 2 messages in the folder and another nextLink, indicating there are
more messages to get from the folder.

<!– {
“blockType”: “response”,
“truncated”: true,
: “microsoft.graph.message”,
“isCollection”: true
} –>

{
    "@odata.context":"https://graph.microsoft.com/v1.0/$metadata#Collection(message)",
    "@odata.nextLink":"https://graph.microsoft.com/v1.0/me/mailfolders('AQMkADNkNAAAgEMAAAA')/messages/delta?$skiptoken=GwcBoTmPKILK4jLH7mAd1lLU",
    "value":[
        {
            "@odata.type":"#microsoft.graph.message",
            "@odata.etag":"W/\"CQAAABYAAAARn2vdzPFjSbaPPxzjlzOTAAAEfYB+\"",
            "subject":"New or modified user account information",
            "sender":{
                "emailAddress":{
                    "name":"Randi Welch",
                    "address":"randiw@contoso.onmicrosoft.com"
                }
            },
            "id":"AQMkADNkNAAAgWJAAAA"
        },
        {
            "@odata.type":"#microsoft.graph.message",
            "@odata.etag":"W/\"CQAAABYAAAARn2vdzPFjSbaPPxzjlzOTAAAEfYB9\"",
            "subject":"New or modified user account information",
            "sender":{
                "emailAddress":{
                    "name":"Randi Welch",
                    "address":"randiw@contoso.onmicrosoft.com"
                }
            },
            "id":"AQMkADNkNAAAgWHAAAA"
        }
    ]
}

8.2.5 Sample third request

The third request continues to use the latest nextLink URL returned from the last sync request.

<!– {
“blockType”: “request”,
“name”: “get_messages_delta_3”
}–>

GET https://graph.microsoft.com/v1.0/me/mailfolders('AQMkADNkNAAAgEMAAAA')/messages/delta?$skiptoken=GwcBoTmPKILK4jLH7mAd1lLU HTTP/1.1
Prefer: odata.maxpagesize=2

8.2.6 Sample third and final response

The third response returns the only remaining message in the folder, and a deltaLink URL which indicates
synchronization is complete for the time being for this folder. Save and use the deltaLink URL to
synchronize the same folder in the next round.

<!– {
“blockType”: “response”,
“truncated”: true,
: “microsoft.graph.message”,
“isCollection”: true
} –>

{
    "@odata.context":"https://graph.microsoft.com/v1.0/$metadata#Collection(message)",
    "@odata.deltaLink":"https://graph.microsoft.com/v1.0/me/mailfolders('AQMkADNkNAAAgEMAAAA')/messages/delta?$deltatoken=GwcBoTmPuoGNlgXgF1nyUNMXY",
    "value":[
        {
            "@odata.type":"#microsoft.graph.message",
            "@odata.etag":"W/\"CQAAABYAAAARn2vdzPFjSbaPPxzjlzOTAAAEfYB8\"",
            "subject":"You've joined the Customer Manager group",
            "sender":{
                "emailAddress":{
                    "name":"Customer Managers team",
                    "address":"customer_managers@contoso.onmicrosoft.com"
                }
            },
            "id":"AQMkADNkNAAAgWFAAAA"
        }
    ]
}

8.2.7 The next round

Using the deltaLink from the last request in the last round,
you will be able to get only those messages that have changed (by being added, deleted, or updated) in that folder since then.
Your first request in the next round will look like the following, assuming you prefer to keep the same maximum page size in the response:

<!– {
“blockType”: “request”,
“name”: “get_messages_delta_next”
}–>

GET https://graph.microsoft.com/v1.0/me/mailfolders('AQMkADNkNAAAgEMAAAA')/messages/delta?$deltatoken=GwcBoTmPuoGNlgXgF1nyUNMXY HTTP/1.1
Prefer: odata.maxpagesize=2

8.3 See also

9 Use delta query to track changes in Microsoft Graph data

Delta query enables applications to discover newly created, updated, or deleted entities without performing a full read of the target resource with every request. Microsoft Graph applications can use delta query to efficiently synchronize changes with a local data store.

9.1 Use delta query to track changes in a resource collection

The typical call pattern is as follows:

  1. The application begins by calling a GET request with the delta function on the desired resource.
  2. Microsoft Graph sends a response containing the requested resource and a state token.

    a. If a nextLink URL is returned, there may be additional pages of data to be retrieved in the session. The application continues making requests using the nextLink URL to retrieve all pages of data until a deltaLink URL is returned in the response.

    b. If a deltaLink URL is returned, there is no more data about the existing state of the resource to be returned. For future requests, the application uses the deltaLink URL to learn about changes to the resource.

  3. When the application needs to learn about changes to the resource, it makes a new request using the deltaLink URL received in step 2. This request may be made immediately after completing step 2 or when the application checks for changes.
  4. Microsoft Graph returns a response describing changes to the resource since the previous request, and either a nextLink URL or a deltaLink URL.

9.1.1 State tokens

A delta query GET response always includes a URL specified in a nextLink or deltaLink response header.
The nextLink URL includes a skipToken, and a deltaLink URL includes a deltaToken.

These tokens are opaque to the client. The following details are what you need to know about them:

  • Each token reflects the state and represents a snapshot of the resource in that round of change tracking.
  • The state tokens also encode and include other query parameters (such as $select)
    specified in the initial delta query request. Therefore, it’s not required to repeat them in subsequent delta query requests.
  • When carrying out delta query, you can copy and apply the nextLink or deltaLink URL to the next delta function call without having to inspect the contents of the URL, including its state token.

9.1.2 Optional query parameters

If a client uses a query parameter, it must be specified in the initial request. Microsoft Graph automatically encodes the specified parameter into the nextLink or deltaLink provided in the response. The calling application only needs to specify their desired query parameters once upfront. Microsoft Graph adds the specified parameters automatically for all subsequent requests.

For users and groups, there are restrictions on using some query parameters:

  • If a $select query parameter is used, the parameter indicates that the client prefers to only track changes on the properties or relationships specified in the $select statement. If a change occurs to a property that is not selected, the resource for which that property changed does not appear in the delta response after a subsequent request.
  • $expand is not supported.

For users and groups beta (preview) APIs, scoping filters allow you to track changes to one or more specific users or groups by objectId. For example, the following request: https://graph.microsoft.com/beta/groups/delta/?$filter= id eq ‘477e9fc6-5de7-4406-bb2a-7e5c83c9ae5f’ or id eq ‘004d6a07-fe70-4b92-add5-e6e37b8acd8e’ returns changes for the groups matching the ids specified in the query filter.

9.2 Resource representation in the delta query response

  • Newly created instances of a supported resource are represented in the delta query response using their standard representation.

  • Updated instances are represented by their id with at least the properties that have been updated, but additional properties may be included.

  • Relationships on users and groups are represented as annotations on the standard resource representation. These annotations use the format propertyName@delta. The annotations are included in the response of the initial delta query request.

Removed instances are represented by their id and an @removed object. The @removed object may include additional information about why the instance was removed. For example, : {“reason”: “changed”}.

Possible @removed reasons can be changed or deleted.

  • Changed indicates the item was deleted and can be restored from deletedItems.
  • Deleted indicates the item is deleted and cannot be restored.

@removed object can be returned in the initial delta query response and in tracked (deltaLink) responses. Clients using delta query requests should be designed to handle these object in the responses.

9.3 Supported resources

Delta query is currently supported for the following resources:

Resource collection API
Events in a calendar view (date range) of the primary calendar delta function of the event resource
Groups delta function of the group resource
Mail folders delta function of the mailFolder resource
Messages in a folder delta function of the message resource
Personal contact folders delta function of the contactFolder resource
Personal contacts in a folder delta function of the contact resource
Users delta function of the user resource
Drive items* delta function of the driveItem resource

* The usage pattern for OneDrive resources is similar to the other supported resources with some minor syntax differences. Delta query for drives will be updated in the future to be consistent with other resource types. For more detail about the current syntax, please see:
https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/api/item_delta

9.4 Prerequisites

The same permissions that are required to read a specific resource are also required to perform delta query on that resource.

9.5 Delta query request examples

Delta query lets you query for additions, deletions, or updates to users, by way of a series of delta function calls. Delta query enables you discover changes to users without having to fetch the entire set of users from Microsoft Graph and compare changes.

Clients using synchronizing users with a local profile store can use Delta Query for both their initial full synchronization along with incremental synchronizations in the future. Typically, a client would do an initial full synchronization of all the users in a tenant, and subsequently, get incremental changes to users periodically.

9.6 Tracking user changes

Tracking user changes is a round of one or more GET requests with the delta function. You make a GET request much like the way you list users, except that you include the following:

  • The delta function.
  • A state token (deltaToken or skipToken) from the previous GET delta function call.

9.7 Example

The following example shows a series requests to track changes to users:

  1. Initial request and response
  2. nextLink request and response
  3. Final nextLink request and response
  4. deltaLink request and deltaLink response

9.8 Initial request

To begin tracking changes in the user resource, you make a request including the delta function on the user resource.

Note the following:

  • The optional $select query parameter is included in the request to demonstrate how query parameters are automatically included in future requests.
  • The initial request does not include a state token. State tokens will be used in subsequent requests.
GET https://graph.microsoft.com/v1.0/users/delta?$select=displayName,givenName,surname

9.9 Initial response

If successful, this method returns 200 OK response code and user collection object in the response body. Assuming the entire set of users is too large, the response will also include a nextLink state token.

In this example, a nextLink URL is returned indicating there are additional pages of data to be retrieved in the session. The $select query parameter from the initial request is encoded into the nextLink URL.

HTTP/1.1 200 OK
Content-type: application/json

{
  "@odata.context":"https://graph.microsoft.com/v1.0/$metadata#users(displayName,givenName,surname)",
  "@odata.nextLink":"https://graph.microsoft.com/v1.0/users/delta?$skiptoken=oEBwdSP6uehIAxQOWq_3Ksh_TLol6KIm3stvdc6hGhZRi1hQ7Spe__dpvm3U4zReE4CYXC2zOtaKdi7KHlUtC2CbRiBIUwOxPKLa",
  "value": [
    {
      "displayName":"Testuser1",
      "givenName":"John",
      "surname":"Doe",
      "id":"ffff7b1a-13b6-477b-8c0c-380905cd99f7"
    },
    {
      "displayName":"Testuser2",
      "givenName":"Jane",
      "surname":"Doe",
      "id":"605d1257-ffff-40b6-8e6f-528a53f5dc55"
    }
  ]
}

The second request specifies the skipToken returned from the previous response. Notice the $select parameter is not required, as the skipToken encodes and includes it.

GET https://graph.microsoft.com/v1.0/users/delta?$skiptoken=oEBwdSP6uehIAxQOWq_3Ksh_TLol6KIm3stvdc6hGhZRi1hQ7Spe__dpvm3U4zReE4CYXC2zOtaKdi7KHlUtC2CbRiBIUwOxPKLa

The response contains a nextLink and another skipToken, indicating there are more users available. You continue making requests using the nextLink URL until a deltaLink URL is returned in the response.

HTTP/1.1 200 OK
Content-type: application/json

{
  "@odata.context":"https://graph.microsoft.com/v1.0/$metadata#users",
  "@odata.nextLink":"https://graph.microsoft.com/v1.0/users/delta?$skiptoken=pqwSUjGYvb3jQpbwVAwEL7yuI3dU1LecfkkfLPtnIjtQ5LOhVoS7qQG_wdVCHHlbQpga7",
  "value": [
    {
      "displayName":"Testuser3",
      "givenName":"Pat",
      "surname":"Doe",
      "id":"d8c37826-ffff-4cae-b348-e2725b1e814b"
    },
    {
      "displayName":"Testuser4",
      "givenName":"Meghan",
      "surname":"Doe",
      "id":"8b1ee412-cd8f-4d59-ffff-24010edb9f1f"
    }
  ]
}

The third request continues to use the latest skipToken returned from the last sync request.

GET https://graph.microsoft.com/v1.0/users/delta?$skiptoken=oEBwdSP6uehIAxQOWq_3Ksh_TLol6KIm3stvdc6hGhaOYDE2VPA4vxIPA90-P6OzGd6Rvku5fDgBRIGS

When the deltaLink URL is returned, there is no more data about the existing state of the resource to be returned. For future requests, the application uses the deltaLink URL to learn about changes to the resource. Save the deltaToken and use it in the request URL to discover changes to users.

HTTP/1.1 200 OK
Content-type: application/json

{
  "@odata.context":"https://graph.microsoft.com/v1.0/$metadata#users",
  "@odata.deltaLink":"https://graph.microsoft.com/v1.0/users/delta?$deltatoken=oEcOySpF_hWYmTIUZBOIfPzcwisr_rPe8o9M54L45qEXQGmvQC6T2dbL-9O7nSU-njKhFiGlAZqewNAThmCVnNxqPu5gOBegrm1CaVZ-ZtFZ2tPOAO98OD9y0ao460",
  "value": [
    {
      "displayName":"Testuser5",
      "givenName":"Al",
      "surname":"Doe",
      "id":"25dcffff-959e-4ece-9973-e5d9b800e8cc"
    },
    {
      "displayName":"Testuser6",
      "givenName":"Sam",
      "surname":"Doe",
      "id":"f6ede700-27d0-4c42-bfb9-4dffff43c74a"
    }
  ]
}

Using the deltaToken from the last response, you will be able to get changed (by being added, deleted, or updated) users since the last request.

GET https://graph.microsoft.com/v1.0/users/delta?$deltatoken=oEcOySpF_hWYmTIUZBOIfPzcwisr_rPe8o9M54L45qEXQGmvQC6T2dbL-9O7nSU-njKhFiGlAZqewNAThmCVnNxqPu5gOBegrm1CaVZ-ZtFZ2tPOAO98OD9y0ao460

If no changes have occurred, the same deltatoken is returned with no results.

HTTP/1.1 200 OK
Content-type: application/json

{
  "@odata.context":"https://graph.microsoft.com/v1.0/$metadata#users",
  "@odata.deltaLink":"https://graph.microsoft.com/v1.0/users/delta?$deltatoken=oEcOySpF_hWYmTIUZBOIfPzcwisr_rPe8o9M54L45qEXQGmvQC6T2dbL-9O7nSU-njKhFiGlAZqewNAThmCVnNxqPu5gOBegrm1CaVZ-ZtFZ2tPOAO98OD9y0ao460",
  "value": []
}

If changes have occurred, the same deltatoken is returned including a collection of changed users.

HTTP/1.1 200 OK
Content-type: application/json

{
  "@odata.context":"https://graph.microsoft.com/v1.0/$metadata#users",
  "@odata.deltaLink":"https://graph.microsoft.com/v1.0/users/delta?$deltatoken=oEcOySpF_hWYmTIUZBOIfPzcwisr_rPe8o9M54L45qEXQGmvQC6T2dbL-9O7nSU-njKhFiGlAZqewNAThmCVnNxqPu5gOBegrm1CaVZ-ZtFZ2tPOAO98OD9y0ao460",
  "value": [
    {
      "displayName":"Testuser7",
      "givenName":"Joe",
      "surname":"Doe",
      "id":"25dcffff-959e-4ece-9973-e5d9b800e8cc"
    },
    {
      "id":"8ffff70c-1c63-4860-b963-e34ec660931d",
      "@removed": {
         "reason": "changed"
      }
    }
  ]
}

9.16 See also

Microsoft Graph delta query overview.

10 Sovereign cloud deployments

This article provides information about the different sovereign cloud instances of Microsoft Graph and the capabilities that are available to developers.

10.1 Microsoft Graph operated by 21Vianet in China

This section provides information about Microsoft Graph operated by 21Vianet, and the capabilities that are available to developers.

10.1.1 Microsoft Graph service root endpoints

Microsoft Graph operated by 21Vianet Microsoft Graph
https://microsoftgraph.chinacloudapi.cn https://graph.microsoft.com

10.1.2 Microsoft Graph Explorer

Microsoft Graph Explorer in China Microsoft Graph Explorer
https://developer.microsoft.com/zh-cn/graph/graph-explorer-china https://developer.microsoft.com/graph/graph-explorer

10.1.3 Azure OpenID Connect and OAuth2.0

The endpoints used to acquire tokens for sign-in or to call Microsoft Graph operated by 21Vianet differ from those of other offerings.

| Microsoft Graph operated by 21Vianet | Microsoft Graph|
|—————————|—————-|
| https://login.chinacloudapi.cn | https://login.microsoftonline.com|

Use https://login.chinacloudapi.cn/common/oauth2/authorize to authenticate the user and https://login.chinacloudapi.cn/common/oauth2/token to acquire a token for your app to call Microsoft Graph operated by 21Vianet.

Note: The latest v2.0 authorization and token endpoints are NOT available for use with Microsoft Graph operated by 21Vianet.

Apps can only access organizational data and not consumer data via the https://microsoftgraph.chinacloudapi.cn** endpoint. Apps should use the https://graph.microsoft.com** endpoint to access consumer data.

10.1.4 Service capabilities offered by Microsoft Graph operated by 21Vianet

The following Microsoft Graph features are generally available (on the /v1.0 endpoint):

  • Users
  • Groups
  • Files
  • Mail
  • Calendar
  • Personal Contacts
  • Create, read, update, and delete (CRUD) operations
  • Cross-origin resource sharing (CORS) support.

The following Microsoft Graph features are also available in preview (on the /beta endpoint):

  • Organizational Contacts
  • Applications
  • Service Principals
  • Directory schema extensions
  • Webhooks

11 Microsoft Graph error responses and resource types

<!–In this article:

<a name=“msg_error_response”> </a> –>

Errors in Microsoft Graph are returned using standard HTTP status codes, as well as a JSON error
response object.

11.1 HTTP status codes

The following table lists and describes the HTTP status codes that can be returned.

Status code Status message Description
400 Bad Request Cannot process the request because it is malformed or incorrect.
401 Unauthorized Required authentication information is either missing or not valid for the resource.
403 Forbidden Access is denied to the requested resource. The user might not have enough permission.
404 Not Found The requested resource doesn’t exist.
405 Method Not Allowed The HTTP method in the request is not allowed on the resource.
406 Not Acceptable This service doesn’t support the format requested in the Accept header.
409 Conflict The current state conflicts with what the request expects. For example, the specified parent folder might not exist.
410 Gone The requested resource is no longer available at the server.
411 Length Required A Content-Length header is required on the request.
412 Precondition Failed A precondition provided in the request (such as an if-match header) does not match the resource’s current state.
413 Request Entity Too Large The request size exceeds the maximum limit.
415 Unsupported Media Type The content type of the request is a format that is not supported by the service.
416 Requested Range Not Satisfiable The specified byte range is invalid or unavailable.
422 Unprocessable Entity Cannot process the request because it is semantically incorrect.
429 Too Many Requests Client application has been throttled and should not attempt to repeat the request until an amount of time has elapsed.
500 Internal Server Error There was an internal server error while processing the request.
501 Not Implemented The requested feature isn’t implemented.
503 Service Unavailable The service is temporarily unavailable for maintenance or is overloaded. You may repeat the request after a delay, the length of which may be specified in a Retry-After header.
504 Gateway Timeout The server, while acting as a proxy, did not receive a timely response from the upstream server it needed to access in attempting to complete the request. May occur together with 503.
507 Insufficient Storage The maximum storage quota has been reached.
509 Bandwidth Limit Exceeded Your app has been throttled for exceeding the maximum bandwidth cap. Your app can retry the request again after more time has elapsed.

The error response is a single JSON object that contains a single property
named error. This object includes all the details of the error. You can use the information returned here instead of or in addition to the HTTP status code. The following is an example of a full JSON error body.

<!– { “blockType”: “example”, : “sample.error”, “expectError”: true, “name”: “example-error-response”} –>

{
  "error": {
    "code": "invalidRange",
    "message": "Uploaded fragment overlaps with existing data.",
    "innerError": {
      "requestId": "request-id",
      "date": "date-time"
    }
  }
}

<!–<a name=“msg_error_resource_type”> </a> –>

11.2 Error resource type

The error resource is returned whenever an error occurs in the processing of a request.

Error responses follow the definition in the
OData v4
specification for error responses.

11.2.1 JSON representation

The error resource is composed of these resources:

<!– { “blockType”: “resource”, : “sample.error” } –>

{
  "error": { "@odata.type": "odata.error" }  
}

11.2.1.1 odata.error resource type

Inside the error response is an error resource that includes the following
properties:

<!– { “blockType”: “resource”, : “odata.error”, “optionalProperties”: [ “target”, “details”, “innererror”] } –>

{
  "code": "string",
  "message": "string",
  "innererror": { "@odata.type": "odata.error" }
}

| Property name | Value | Description\ |
|:—————|:———————–|:———————————————————————————————————–|
| code | string | An error code string for the error that occured |
| message | string | A developer ready message about the error that occured. This should not be displayed to the user directly. |
| innererror | error object | Optional. Additional error objects that may be more specific than the top level error. |
<!– {
“type”: “#page.annotation”,
“description”: “Understand the error format for the API and error codes.”,
“keywords”: “error response, error, error codes, innererror, message, code”,
“section”: “documentation”,
“tocPath”: “Misc/Error Responses”
} –>

<!–<a name=“msg_code_property”> </a> –>

11.2.1.2 Code property

The code property contains one of the following possible values. Your apps should be
prepared to handle any one of these errors.

Code Description
accessDenied The caller doesn’t have permission to perform the action.
activityLimitReached The app or user has been throttled.
generalException An unspecified error has occurred.
invalidRange The specified byte range is invalid or unavailable.
invalidRequest The request is malformed or incorrect.
itemNotFound The resource could not be found.
malwareDetected Malware was detected in the requested resource.
nameAlreadyExists The specified item name already exists.
notAllowed The action is not allowed by the system.
notSupported The request is not supported by the system.
resourceModified The resource being updated has changed since the caller last read it, usually an eTag mismatch.
resyncRequired The delta token is no longer valid, and the app must reset the sync state.
serviceNotAvailable The service is not available. Try the request again after a delay. There may be a Retry-After header.
quotaLimitReached The user has reached their quota limit.
unauthenticated The caller is not authenticated.

The innererror object might recursively contain more innererror objects
with additional, more specific error codes. When handling an error, apps
should loop through all the error codes available and use the most detailed
one that they understand. Some of the more detailed codes are listed at the
bottom of this page.

To verify that an error object is an error you are expecting, you must loop
over the innererror objects, looking for the error codes you expect. For example:

public bool IsError(string expectedErrorCode)
{
    OneDriveInnerError errorCode = this.Error;
    while (null != errorCode)
    {
        if (errorCode.Code == expectedErrorCode)
            return true;
        errorCode = errorCode.InnerError;
    }
    return false;
}

For an example that shows how to properly handle errors, see
Error Code Handling.

The message property at the root contains an error message intended for the
developer to read. Error messages are not localized and shouldn’t be displayed
directly to the user. When handling errors, your code should not key off of
message values because they can change at any time, and they often contain
dynamic information specific to the failed request. You should only code
against error codes returned in code properties.

11.2.1.3 Detailed error codes

The following are some additional errors that your app might encounter within the nested
innererror objects. Apps are not required to handle these, but can if they
choose. The service might add new error codes or stop returning old ones at any
time, so it is important that all apps be able to handle the basic error codes.

Code Description
accessRestricted Access restricted to the item’s owner.
cannotSnapshotTree Failed to get a consistent delta snapshot. Try again later.
childItemCountExceeded Max limit on the number of child items was reached.
entityTagDoesNotMatch ETag does not match the current item’s value.
fragmentLengthMismatch Declared total size for this fragment is different from that of the upload session.
fragmentOutOfOrder Uploaded fragment is out of order.
fragmentOverlap Uploaded fragment overlaps with existing data.
invalidAcceptType Invalid accept type.
invalidParameterFormat Invalid parameter format.
invalidPath Name contains invalid characters.
invalidQueryOption Invalid query option.
invalidStartIndex Invalid start index.
lockMismatch Lock token does not match existing lock.
lockNotFoundOrAlreadyExpired There is currently no unexpired lock on the item.
lockOwnerMismatch Lock Owner ID does not match provided ID.
malformedEntityTag ETag header is malformed. ETags must be quoted strings.
maxDocumentCountExceeded Max limit on number of Documents is reached.
maxFileSizeExceeded Max file size exceeded.
maxFolderCountExceeded Max limit on number of Folders is reached.
maxFragmentLengthExceeded Max file size exceeded.
maxItemCountExceeded Max limit on number of Items is reached.
maxQueryLengthExceeded Max query length exceeded.
maxStreamSizeExceeded Maximum stream size exceeded.
parameterIsTooLong Parameter Exceeds Maximum Length.
parameterIsTooSmall Parameter is smaller then minimum value.
pathIsTooLong Path exceeds maximum length.
pathTooDeep Folder hierarchy depth limit reached.
propertyNotUpdateable Property not updateable.
resyncApplyDifferences Resync required. Replace any local items with the server’s version (including deletes) if you’re sure that the service was up to date with your local changes when you last sync’d. Upload any local changes that the server doesn’t know about.
resyncRequired Resync is required.
resyncUploadDifferences Resync required. Upload any local items that the service did not return, and upload any files that differ from the server’s version (keeping both copies if you’re not sure which one is more up-to-date).
serviceNotAvailable The server is unable to process the current request.
serviceReadOnly Resource is temporarily read-only.
throttledRequest Too many requests.
tooManyResultsRequested Too many results requested.
tooManyTermsInQuery Too many terms in the query.
totalAffectedItemCountExceeded Operation is not allowed because the number of affected items exceeds threshold.
truncationNotAllowed Data truncation is not allowed.
uploadSessionFailed Upload session failed.
uploadSessionIncomplete Upload session incomplete.
uploadSessionNotFound Upload session not found.
virusSuspicious This document is suspicious and may have a virus.
zeroOrFewerResultsRequested Zero or fewer results requested.

<!– ##Additional Resources##

12 Add custom data to users using open extensions

We’re going to walk you through an example to demonstrate how to use open extensions.

Imagine you’re building an application that is available on lots of different client platforms, such as desktop and mobile. You want to let users
configure their UI experience so it’s consistent no matter which device they use to sign in to your app. This is a common requirement for most apps.

For this scenario, we’re going to show you how to:

  1. Add an open extension representing some roaming profile information about the user.
  2. Query the user and return the roaming profile.
  3. Change the user’s roaming profile information (the open extension value).
  4. Delete the user’s roaming profile information.

Note: This topic shows you how to add, read, update and delete open extensions on a user resource. These methods are also supported for
the administrativeUnit, contact, device, event, group, group event, group post and organizaton resource types.
Simply update the example requests below using any of those resource types. The responses shown in the examples below may be truncated for brevity.

12.1 1. Add roaming profile information

The user signs in to the app and configures the look and feel of the app. These app settings should roam so that the user gets the same experience on
whatever device they sign in to the app from. Here we’ll see how to add the roaming profile information to a user resource.

12.1.0.0.1 Request
POST https://graph.microsoft.com/v1.0/me/extensions
Content-type: application/json
{
    "@odata.type":"microsoft.graph.openTypeExtension",
    "extensionName":"com.contoso.roamingSettings",
    "theme":"dark",
    "color":"purple",
    "lang":"Japanese"
}
12.1.0.0.2 Response
HTTP/1.1 201 Created
Content-Type: application/json
Content-length: 420

{
    "@odata.type": "#microsoft.graph.openTypeExtension",
    "extensionName": "com.contoso.roamingSettings",
    "id": "com.contoso.roamingSettings",
    "theme": "dark",
    "color": "purple",
    "lang": "Japanese"
}

12.2 2. Retrieve roaming profile information

When the user signs in to the app from another device, the app can retrieve the user’s profile details as well as their roaming settings. This can be done by getting the user’s resource and expanding the extension navigation property.

12.2.0.0.1 Request
GET https://graph.microsoft.com/v1.0/me?$select=id,displayName,mail,mobilePhone&$expand=extensions
12.2.0.0.2 Response
HTTP/1.1 200 OK
Content-Type: application/json
Content-length: 420

{
    "id": "84b80893-8749-40a3-97b7-68513b600544",
    "displayName": "John Smith",
    "mail": "john@contoso.com",
    "mobilePhone": "1-555-6589",
    "extensions": [
        {
            "@odata.type": "#microsoft.graph.openTypeExtension",
            "extensionName": "com.contoso.roamingSettings",
            "id": "com.contoso.roamingSettings",
            "theme": "dark",
            "color": "purple",
            "lang": "Japanese"
        }
    ]
}

Note: If you have multiple extensions, you can filter on the id to get the extension that you are interested in.

12.3 3. Change roaming profile information

The user may choose to change their roaming profile information. This update can be done with a PATCH on the open extension value.

12.3.0.0.1 Request
PATCH https://graph.microsoft.com/v1.0/me/extensions/com.contoso.roamingSettings
Content-type: application/json
{
    "theme":"light",
    "color":"yellow",
    "lang":"Swahili"
}
12.3.0.0.2 Response
HTTP/1.1 204 No content

12.4 4. Delete a user’s roaming profile

The user decides that they don’t want a roaming profile anymore, so they delete it. This can be done with a DELETE request on the open extension value.

12.4.0.0.1 Request
DELETE https://graph.microsoft.com/v1.0/me/extensions/com.contoso.roamingSettings
12.4.0.0.2 Response
HTTP/1.1 204 No content

12.5 See also

Microsoft Graph provides a single API endpoint that gives you access to rich people-centric data and insights through a number of resources like
user and message. There’s now a way for you to extend Microsoft Graph
with your own application data. You can add custom properties to Microsoft Graph resources without requiring an external data store.
For example, you might decide to keep your app lightweight and store app-specific user profile data in Microsoft Graph by extending the user resource.
Alternatively, you might want to retain your app’s existing user profile store, and simply add an app-specific store identifier
to the user resource.

Microsoft Graph offers two types of extensions. Choose the extension type that best suits your application needs:

  • Open extensions: A good way for developers to get started.
  • Schema extensions: A more versatile mechanism for developers who care about storing typed data, making their schema discoverable and shareable, being able to filter, and in the future, being able to perform input data validation and authorization.

Important: You should not use extensions to store sensitive personally identifiable information, such as account credentials, government identification numbers, cardholder data, financial account data, healthcare information, or sensitive background information.

12.6 Supported resources

The following table lists the resources that support open and schema extensions and indicates whether they have reached general availability (GA) (available in both the v1.0 and beta endpoints) or are in preview (available only in the beta endpoint).

Resource Open extensions Schema extensions
Administrative unit Preview only Preview only
Calendar event GA GA
Device GA GA
Group GA GA
Group calendar event GA GA
Group conversation post GA GA
Message GA GA
Organization GA GA
Personal contact GA GA
User GA GA

You can use extensions on all these resources when signed-in with a work or school account.
In addition, you can use extensions on these resources - event, post, group, message, contact, and user - when signed-in with a personal account.

12.7 Open extensions

Open extensions (formerly known as Office 365 data extensions) are
open types that offer a flexible way to
add untyped app data directly to a resource instance.

Open extensions, together with their custom data, are accessible through the extensions navigation property of the resource instance.
The extensionName property is the only pre-defined, writable property in an open extension. When creating an open extension, you must assign the extensionName property a name that is unique within the tenant.
One way to do this is to use a reverse domain name system (DNS) format that is dependent on your own domain, for example, Com.Contoso.ContactInfo.
Do not use the Microsoft domain (Com.Microsoft or Com.OnMicrosoft) in an extension name.

You can create an open extension in a resource instance and store custom data to it all in the same operation
(note known limitation below for some of the supported resources).
You can subsequently read, update, or delete
the extension and its data.

Open extension example: Add custom data to users using open extensions

12.8 Schema extensions

Schema extensions allow you to define a schema you can use to extend a resource type. First, you create your schema extension definition.
Then, use it to extend resource instances with strongly-typed custom data. In addition, you can control the status of your schema extension and let it
be discoverable by other apps. These apps can in turn use the extension for their data and build further experiences on top of it.

When creating a schema extension definition, you must provide a unique name for its id. There are two naming options:

  • If you already have a vanity .com domain that you have verified with your tenant, you can use the domain name along with the schema name
    to define a unique name, in this format {domainName}_{schemaName}. For example, if your vanity domain is contoso.com then you can define
    an id of, contoso_mySchema. This is the preferred option.
  • If you don’t have a verified vanity domain, you can just set the id to a schema name (without a domain name prefix), for example, mySchema.
    Microsoft Graph will assign a string ID for you based on the supplied name, in this format: ext{8-random-alphanumeric-chars}_{schema-name}. For example, extkvbmkofy_mySchema.

You will see this unique name in id used as the name of the complex type which will store your custom data on the extended resource instance.

Unlike open extensions, managing schema extension definitions (list, create,
get, update, and delete)
and managing their data (add, get, update, and delete data) are separate sets of API operations.

Since schema extensions are accessible as complex types in instances of the targeted resources, you can
do CRUD operations on the custom data in a schema extension in the following ways:

  • Use the resource POST method to specify custom data when creating a new resource instance.
  • Use the resource GET method to read the custom data.
  • Use the resource PATCH method to add or update custom data in an existing resource instance.
  • Use the resource PATCH method to set the complex type to null, to delete the custom data in the resource instance.

Schema extension example: Add custom data to groups using schema extensions

12.8.1 Schema extensions lifecycle

When your app creates a schema extension definition, the app is marked as the owner of that schema extension.

The owner app can move the extension through different states of a lifecycle, using a PATCH operation on its status property.
Depending on the current state, the owner app may be able to update or delete the extension. Any updates to a schema extension should always only be additive and non-breaking.

State Lifecycle state behavior
InDevelopment <ul><li>Initial state after creation. The owner app is still developing the schema extension. </li><li>In this state, only the owner app can extend resource instances with this schema definition, and only in the same directory where the owner app is registered. </li><li>Only the owner app can update the extension definition with additive changes or delete it. </li><li>The owner app can move the extension from InDevelopment to the Available state.</li></ul>
Available <ul><li>The schema extension is available for use by all apps in any tenant. </li><li>Once the owner app sets the extension to Available, any app can simply add custom data to instances of those resource types specified in the extension (as long as the app has permissions to that resource). The app can assign custom data when creating a new instance, or updating an existing instance. </li><li>Only the owner app can update the extension definition with additive changes. <br>- No app can delete the extension definition in this state. </li><li>The owner app can move the schema extension from Available to the Deprecated state.</li></ul>
Deprecated <ul><li>The schema extension definition can no longer be read or modified. </li><li>No app can view, update, add new properties, or delete the extension. </li><li>Apps can, however, still read, update, or delete existing extension property values. </li><li>The owner app can move the schema extension from Deprecated back to the Available state.</li></ul>

12.8.2 Supported property data types

The following data types are supported when defining a property in a schema extension:

Property Type Remarks
Binary 256 bytes maximum.
Boolean Not supported for messages, events and posts.
DateTime Must be specified in ISO 8601 format. Will be stored in UTC.
Integer 32-bit value. Not supported for messages, events and posts.
String 256 characters maximum.

Note: Multi-value properties are not supported.

12.8.3 Azure AD directory schema extensions

Azure AD supports a similar type of extensions, known as directory schema extensions,
on a few directoryObject resources. While you must use Azure AD Graph API to create and manage the definitions of directory schema extensions, you can use Microsoft Graph API
to add, get, update and delete data in the properties of these extensions.

12.9 Permissions

The same permissions that are required to read from or write to a specific resource are also required to read from or write to any extensions data on that resource. For example, for an app to be able to update the signed-in user’s profile with custom app data, the app must have been granted the User.ReadWrite.All permission.

Additionally, to create and manage schema extension definitions, an application must be granted the Directory.AccessAsUser.All permission.

12.10 Data limits

12.10.1 Open extension limits

The following limits apply to directory resources (such as user, group, device):

  • Each open extension can have up to 2KB of data (including the extension definition itself).
  • An application can add up to two open extensions per resource instance.

12.10.2 Schema extension limits

An application may create no more than five schema extension definitions.

12.11 Known limitations

For known limitations using extensions, see the extensions section in the known issues article.

12.12 Extension examples

Add custom data to users using open extensions

Add custom data to groups using schema extensions

12.13 See also

Office 365 domains

Adding and verifying a domain for an Office 365 tenant

13 Add custom data to groups using schema extensions

We’re going to walk you through an example to demonstrate how to use schema extensions.

Imagine you’re a developer in a Learning Management Software company called “Graph Learn” that builds training courses and materials for businesses. Office 365 groups, with their rich collaborative experiences,
is a fantastic way to deliver course content and record exercises among participants for both online courses and instructor-led courses. You may want to make
those Office 365 groups used for training courses easily identifiable as training courses, which will allow other developers to discover your groups and build rich experiences on top of your learning courses.

For this scenario, we’re going to show you how to:

  1. View available schema extension definitions that you could use.
  2. Register a schema extension definition that targets groups for training courses.
  3. Create a new group with extended data based on the schema extension definition that you just registered.
  4. Add, update, or remove custom data in an existing group based on a schema extension definition.
  5. Read back a group and the extension data.

Note: This topic shows you how to create and read schema extension values on a group resource (steps 3-5). The same methods are supported for the
administrativeUnit, device, event, message, organization, post, and user
resource types as well. So you can carry out similar operations as the example requests below on any of those resources. Note that administrativeUnit is
available only in the beta endpoint.

13.1 1. View available schema extensions

First, as a developer, you might want to find any other schema extension definitions that our app could reuse. This can be done by querying the schemaExtension resource.
In the example below, you’re going to query for a specific schema extension by id.

Notice that the extension returned in the response has Available as the status value, which indicates that any app which has permission to the resources in the targetTypes property can use and update the extension
with additive changes. In general, this operation returns any schema extensions that satisfy the specified filter regardless of status, so do check the extension status before using it.

13.1.0.0.1 Request
GET https://graph.microsoft.com/v1.0/schemaExtensions?$filter=id eq 'graphlearn_test'
13.1.0.0.2 Response
HTTP/1.1 200 OK
Content-Type: application/json
Content-length: 420
{
    "value": [
        {
            "id":"graphlearn_test",
            "description": "Yet another test schema",
            "targetTypes": [
                "User", "Group"
            ],
            "status": "Available",
            "owner": "24d3b144-21ae-4080-943f-7067b395b913",
            "properties": [
                {
                    "name": "testName",
                    "type": "String"
                }
            ]
        }
    ]
}

13.2 2. Register a schema extension definition that describes a training course

If you can’t find a schema extension that is appropriate for your needs, you can create and register a new extension definition for training courses on the group resource.

When creating a schema extension definition, you should provide a string for the id property. There are two ways to do this. The following example shows the preferred
way, which uses a vanity domain name (graphlearn.com) that has been verified with your tenant. Concatenate the verified domain name (graphlearn) with a name
for the schema extension (courses), and assign id with the resultant string, graphlearn_courses.

Then, specify a description (to enable discoverability), target types
(defining which resources this extension applies to), and the custom properties that make up the schema. In this example,
specify the courseId, courseName and courseType custom properties and their types.

See an example of the other way to assign id in the request, that requires you to provide only a schema name.

Notice that when you initially create a schema extension, its status is InDevelopment. While you’re developing the extension, you can keep it in this status,
during which only your app that created it can update it with additive changes or delete it. When you are ready to share the extension for use by other apps, set status to Available.

13.2.0.0.1 Request
POST https://graph.microsoft.com/v1.0/schemaExtensions
Content-type: application/json
{
    "id":"graphlearn_courses",
    "description": "Graph Learn training courses extensions",
    "targetTypes": [
        "Group"
    ],
    "properties": [
        {
            "name": "courseId",
            "type": "Integer"
        },
        {
            "name": "courseName",
            "type": "String"
        },
        {
            "name": "courseType",
            "type": "String"
        }
    ]
}
13.2.0.0.2 Response
HTTP/1.1 201 Created
Content-Type: application/json
Content-length: 420
{
    "id": "graphlearn_course",
    "description": "Graph Learn training courses extensions",
    "targetTypes": [
        "Group"
    ],
    "status": "InDevelopment",
    "owner": "24d3b144-21ae-4080-943f-7067b395b913",
    "properties": [
        {
            "name": "courseId",
            "type": "Integer"
        },
        {
            "name": "courseName",
            "type": "String"
        },
        {
            "name": "courseType",
            "type": "String"
        }
    ]
}

13.3 3. Create a new group with extended data

Create a new group and extend it with extra data using the graphlearn_courses schema extension definition that we just registered. This is a standard POST
to the group resource, with the additional graphlearn_courses complex type extension defined in the request body. The response will not mirror back any data extensions.
We need to explicitly $select the extension by name using a GET operation.

13.3.0.0.1 Request
POST https://graph.microsoft.com/v1.0/groups
Content-type: application/json
{
    "displayName": "New Managers March 2017",
    "description": "New Managers training course for March 2017",
    "groupTypes": ["Unified"],
    "mailEnabled": true,
    "mailNickname": "newMan201703",
    "securityEnabled": false,
    "graphlearn_courses": {
        "courseId":"123",
        "courseName":"New Managers",
        "courseType":"Online"
    }
}
13.3.0.0.2 Response
HTTP/1.1 201 Created
Content-Type: application/json
Content-length: 420
{
    "id": "dfc8016f-db97-4c47-a582-49cb8f849355",
    "createdDateTime": "2017-02-09T00:17:05Z",
    "description": "New Managers training course for March 2017",
    "displayName": "New Managers March 2017",
    "groupTypes": [
        "Unified"
    ],
    "mail": "newMan201703@graphlearn.com",
    "mailEnabled": true,
    "mailNickname": "newMan201703",
    "securityEnabled": false,
    "theme": null,
    "visibility": "Public"
}

13.4 4. Add, update, or remove custom data in an existing group

You can extend and add custom data to an existing group instance with the additional graphlearn_courses complex type extension defined in the body of a PATCH request.

13.4.0.0.1 Request
PATCH https://graph.microsoft.com/v1.0/groups/dfc8016f-db97-4c47-a582-49cb8f849355
Content-type: application/json
Content-length: 230
{
    "graphlearn_courses":{
        "courseId":"123",
        "courseName":"New Managers",
        "courseType":"Online"
    }   
}
13.4.0.0.2 Response
HTTP/1.1 204 No Content

If you want to update the values of the extension data, put the entire extension complex type in the body of a PATCH request (similar to adding custom data to an existing resource).

You can also remove custom data added to a resource instance by setting the corresponding extension property to null.

To remove a schema extension from a resource instance, set the extension complex type in that instance to null.

13.5 5. Get a group and its extension data

A handy way to look for a group (or groups) is to use $filter to match for specific extension property values,
such as an extension name or ID.

Then, to get the custom data in a group, use $select to include the extension by name (in this case by graphlearn_courses).

The following example looks for the group that has the graphlearn_courses extension with a courseId property value matching 123, and gets the
group properties displayName, id, and description, and the custom data in the graphlearn_courses extension. (In the actual query, make sure you apply URL encoding as necessary.)

13.5.0.1 Request

GET https://graph.microsoft.com/v1.0/groups?$filter=graphlearn_courses/courseId eq ‘123’&$select=displayName,id,description,graphlearn_courses
13.5.0.1.1 Response
HTTP/1.1 200 OK
Content-Type: application/json
Content-length: 326
{
  "value": [
    {
      "displayName": "New Managers March 2017",
      "id": "14429ae5-3e74-41a2-9fa8-028fbb984637",
      "description": "New Managers training course for March 2017",
      "graphlearn_courses": {
        "@odata.type": "#microsoft.graph.ComplexExtensionValue",
        "courseId":"123",
        "courseName":"New Managers",
        "courseType":"Online"
      }
    }
  ]
}

13.6 See also

# Featured scenarios for Microsoft Graph

Check out some common and featured scenarios for working with the Microsoft Graph API. Explore the topics in this section, and try out some of the popular requests listed in the following table. The links take you to our Graph Explorer.

Operation URL
GET my profile https://graph.microsoft.com/v1.0/me
GET my files https://graph.microsoft.com/v1.0/me/drive/root/children
GET my photo https://graph.microsoft.com/v1.0/me/photo/$value
GET my mail https://graph.microsoft.com/v1.0/me/messages
GET my high importance email https://graph.microsoft.com/v1.0/me/messages?$filter=importance%20eq%20'high'
GET my calendar events https://graph.microsoft.com/v1.0/me/events
GET my manager https://graph.microsoft.com/v1.0/me/manager
GET last user to modify file foo.txt https://graph.microsoft.com/v1.0/me/drive/root/children/foo.txt/lastModifiedByUser
GET Office365 groups I’m member of https://graph.microsoft.com/v1.0/me/memberOf/$/microsoft.graph.group?$filter=groupTypes/any(a:a%20eq%20'unified')
GET users in my organization https://graph.microsoft.com/v1.0/users
GET groups in my organization https://graph.microsoft.com/v1.0/groups
GET people related to me https://graph.microsoft.com/v1.0/me/people
GET items trending around me https://graph.microsoft.com/beta/me/insights/trending
GET my notes https://graph.microsoft.com/beta/me/onenote/notebooks

13.8 Next steps

Try out some more calls in the Graph Explorer, and use our quick start to get up and running fast. Learn more about how to use the API to build your first app.

14 Find possible meeting times on the Outlook calendar

In a workplace or school, looking for a common time and place to meet often incurs overhead. Microsoft Graph applications can use
findMeetingTimes to identify any possible meeting times that satisfy time, location, and other constraints.

The findMeetingTimes action lets you specify conditions such as the meeting date/time range, duration, optional or required attendees, and
nature of the activity (activityDomain). The action takes into account the attendees’ and organizer’s normal work schedules and free/busy status, and suggests
times that are appropriate for the participants and type of activity. For instance, suggestions for a work-related activity always occur
during the work hours of the organizer and attendees, and suggestions where required attendees are available are ordered higher up in the suggested list.

In Office 365, work hours and time zones are configurable per mailbox. The findMeetingTimes action handles time zone variations among the organizer
and attendees. By default, findMeetingTimes returns suggestions in UTC. You can use the following request header to have findMeetingTimes return suggestions
expressed in a specific time zone.

Prefer: outlook.timezone="{time-zone-string}}"

Especially useful for larger meetings, you can specify a percentage (minimumAttendeePercentage) for a quorum and have findMeetingTimes return suggestions
only if that minimum attendee availability is met.

If findMeetingTimes cannot suggest any meeting times, it indicates a specific reason (emptySuggestionsReason), such as the organizer or a required attendee not available.
Based on this value, you can better adjust the parameters and call findMeetingTimes again.

Note The findMeetingTimes action is currently available to Office 365 work or school mailboxes, but not personal, outlook.com mailboxes.

14.1 Example

The following example shows how to use findMeetingTimes to return possible times for 2 users to meet for a couple of hours, taking into
account the users’ free/busy and work schedules, and the attendee being away for part of the time. Because there are only 2 users for this meeting, suggestions
require 100% attendance. The following shows the users’ free/busy schedule.

14.1.1 Organizer’s calendar

The organizer’s work calendar for April 17-21 showing free-busy times

14.1.2 Attendee’s calendar

The attendee’s work calendar for April 17-21 showing free-busy times

The example makes 2 calls to findMeetingTimes:

  1. The first call looks in the date range of April 18-20.
    As the attendee is out-of-office on April 18-19, and there is no commonly available time on April 20, the first call returns no suggestions
    with the reason (emptySuggestionsReason) that attendees are not available.
  2. The second call looks for availability on April 21 and returns a suggestion of 2-4pm.

The two calls to findMeetingTimes include the following parameters. All parameters for findMeetingTimes are optional.

  • attendees: one attendee, Fanny Downs, set as required for the type property
  • locationConstraint: does not require any location suggestion
  • timeConstraint: the first call looks in the date/time range of April 18, 9am to April 20, 5pm; after the first call fails to suggest any times, the second call looks at April 21, 9am to 5pm
  • meetingDuration: two hours
  • returnSuggestionReasons: this example requires a reason for each suggestion
  • minimumAttendeePercentage: 100%, as the attendee must be able to attend for any suggested time

14.1.3 First request

Look for a 2-hour free time slot for both users over April 18-20.

<!– {
“blockType”: “request”,
“name”: “findmeetingtimes_example_first”
}–>

POST https://graph.microsoft.com/v1.0/me/findMeetingTimes
Prefer: outlook.timezone="Pacific Standard Time"
Content-type: application/json

{ 
  "attendees": [ 
    { 
      "type": "required",  
      "emailAddress": { 
        "name": "Fanny Downs",
        "address": "fannyd@contoso.onmicrosoft.com" 
      } 
    }
  ],  
  "locationConstraint": { 
    "isRequired": "false",  
    "suggestLocation": "false",  
    "locations": [ 
      { 
        "resolveAvailability": "false",
        "displayName": "Conf room Hood" 
      } 
    ] 
  },  
  "timeConstraint": {
    "activityDomain":"work", 
    "timeslots": [ 
      { 
        "start": { 
          "dateTime": "2017-04-18T09:00:00",  
          "timeZone": "Pacific Standard Time" 
        },  
        "end": { 
          "dateTime": "2017-04-20T17:00:00",  
          "timeZone": "Pacific Standard Time" 
        } 
      } 
    ] 
  },  
  "meetingDuration": "PT2H",
  "returnSuggestionReasons": "true",
  "minimumAttendeePercentage": "100"
}

14.1.4 First response

There is no 2-hour time slot during the work hours of April 18-20 when both users are available.
<!– {
“blockType”: “response”,
“truncated”: true,
: “microsoft.graph.meetingTimeSuggestionsResult”,
“isCollection”: false
} –>

HTTP/1.1 200 OK
Content-type: application/json
Preference-Applied: outlook.timezone="Pacific Standard Time"
Content-Length: 184

{
    "@odata.context":"https://graph.microsoft.com/v1.0/$metadata#microsoft.graph.meetingTimeSuggestionsResult",
    "emptySuggestionsReason":"AttendeesUnavailable",
    "meetingTimeSuggestions":[

    ]
}

14.1.5 Second request

Look for a 2-hour time slot on April 21.
<!– {
“blockType”: “request”,
“name”: “findmeetingtimes_example_second”
}–>

POST https://graph.microsoft.com/v1.0/me/findMeetingTimes
Prefer: outlook.timezone="Pacific Standard Time"
Content-type: application/json

{ 
  "attendees": [ 
    { 
      "type": "required",  
      "emailAddress": { 
        "name": "Fanny Downs",
        "address": "fannyd@contoso.onmicrosoft.com" 
      } 
    }
  ],  
  "locationConstraint": { 
    "isRequired": "false",  
    "suggestLocation": "false",  
    "locations": [ 
      { 
        "resolveAvailability": "false",
        "displayName": "Conf room Hood" 
      } 
    ] 
  },  
  "timeConstraint": {
    "activityDomain":"work", 
    "timeslots": [ 
      { 
        "start": { 
          "dateTime": "2017-04-21T09:00:00",  
          "timeZone": "Pacific Standard Time" 
        },  
        "end": { 
          "dateTime": "2017-04-21T17:00:00",  
          "timeZone": "Pacific Standard Time" 
        } 
      } 
    ] 
  },  
  "meetingDuration": "PT2H",
  "returnSuggestionReasons": "true",
  "minimumAttendeePercentage": "100"
}

14.1.6 Second response

The second findMeetingTimes request suggests April 21, 2-4pm for both users to meet.
<!– {
“blockType”: “response”,
“truncated”: true,
: “microsoft.graph.meetingTimeSuggestionsResult”,
“isCollection”: false
} –>

HTTP/1.1 200 OK
Content-type: application/json
Preference-Applied: outlook.timezone="Pacific Standard Time"
Content-Length: 714

{
    "@odata.context":"https://graph.microsoft.com/v1.0/$metadata#microsoft.graph.meetingTimeSuggestionsResult",
    "emptySuggestionsReason":"",
    "meetingTimeSuggestions":[
        {
            "confidence":100.0,
            "organizerAvailability":"free",
            "suggestionReason":"Suggested because it is one of the nearest times when all attendees are available.",
            "meetingTimeSlot":{
                "start":{
                    "dateTime":"2017-04-21T14:00:00.0000000",
                    "timeZone":"Pacific Standard Time"
                },
                "end":{
                    "dateTime":"2017-04-21T16:00:00.0000000",
                    "timeZone":"Pacific Standard Time"
                }
            },
            "attendeeAvailability":[
                {
                    "availability":"free",
                    "attendee":{
                        "type":"required",
                        "emailAddress":{
                            "address":"fannyd@contoso.onmicrosoft.com"
                        }
                    }
                }
            ],
            "locations":[
                {
                    "displayName":"Conf room Hood"
                }
            ]
        }
    ]
}

14.2 Next steps

There are times when not all attendees can attend a meeting. You can have findMeetingTimes suggest a time if the confidence for attendance reaches a certain percentage,
by specifying the minimumAttendeePercentage optional parameter. Learn more about the
confidence of a meeting suggestion
and other parameters, and apply them as appropriate for meetings of larger sizes.

After getting meeting time suggestions, you may want to:

  1. Create an event and send it as a meeting request
  2. Add an attachment to the event

15 Getting started building Microsoft Graph apps

The articles in this section provide detailed guidance on how to build apps that connect to Microsoft Graph across a variety of languages and development platforms. Each article starts with a sample starter project for the appropriate platform, and walks you through adding functionality that authenticates the user and makes a sample request to have Microsoft Graph send an email from their account. The completed project is identical to the Connect sample in the Microsoft Graph repo for that platform.

Choose the article that covers the authentication provider and development platform of your choice, and get started connecting to Microsoft Graph.

You can follow the steps in the article that covers the development platform that you choose, or, to quickly get a working solution up and running, try out the quick start experience.

To explore the finished Connect samples, see Microsoft Graph in GitHub. The following table lists the samples by authentication provider and platform, and notes whether they connect to Microsoft Graph using REST or a Microsoft Graph client library.

<table>
<tr>
<th>Platform</th>
<th>Azure AD endpoint</th>
<th>Azure AD v2.0 endpoint</th>
</tr>
<tr>
<td>Android</td>
<td>
<a href=“https://github.com/microsoftgraph/android-java-connect-sample/tree/last_v1_auth”>SDK sample</a>
</td>
<td>
<a href=“https://github.com/microsoftgraph/android-java-connect-sample”>SDK sample</a> or
<a href=“https://github.com/microsoftgraph/android-java-connect-rest-sample”>REST sample</a>
</td>
</tr>
<tr>
<td>AngularJS</td>
<td>
<a href=“https://github.com/microsoftgraph/angular-connect-rest-sample/tree/last_v1_auth”>REST sample</a>
</td>
<td>
<a href=“https://github.com/microsoftgraph/angular-connect-sample”>SDK sample</a> or
<a href=“https://github.com/microsoftgraph/angular-connect-rest-sample”>REST sample</a>
</td>
</tr>
<tr>
<td>ASP.NET</td>
<td>
<a href=“https://github.com/microsoftgraph/aspnet-connect-rest-sample/tree/last_v1_auth”>REST sample</a>
</td>
<td>
<a href=“https://github.com/microsoftgraph/aspnet-connect-sample”>SDK sample</a> or
<a href=“https://github.com/microsoftgraph/aspnet-connect-rest-sample”>REST sample</a>
</td>
</tr>
<tr>
<td>iOS (Obj-C)</td>
<td>
<a href=“https://github.com/microsoftgraph/ios-objectivec-connect-rest-sample”>REST sample</a>
</td>
<td>
<a href=“https://github.com/microsoftgraph/ios-objectivec-connect-sample”>SDK sample</a>
</td>
</tr>
<tr>
<td>iOS (Swift)</td>
<td>
<a href=“https://github.com/microsoftgraph/ios-swift-connect-rest-sample”>REST sample</a>
</td>
<td>
<a href=“https://github.com/microsoftgraph/ios-swift-connect-sample”>SDK sample</a>
</td>
</tr>
<tr>
<td>NodeJS</td>
<td>
<a href=“https://github.com/microsoftgraph/nodejs-connect-rest-sample/tree/last_v1_auth”>REST sample</a>
</td>
<td>
<a href=“https://github.com/microsoftgraph/nodejs-connect-sample”>SDK sample</a> or
<a href=“https://github.com/microsoftgraph/nodejs-connect-rest-sample”>REST sample</a>
</td>
</tr>
<tr>
<td>PHP</td>
<td>
<a href=“https://github.com/microsoftgraph/php-connect-rest-sample/tree/last_v1_auth”>REST sample</a>
</td>
<td>
<a href=“https://github.com/microsoftgraph/php-connect-sample”>SDK sample</a> or
<a href=“https://github.com/microsoftgraph/php-connect-rest-sample”>REST sample</a>
</td>
</tr>
<tr>
<td>Python</td>
<td>
<a href=“https://github.com/microsoftgraph/python3-connect-rest-sample”>REST sample</a>
</td>
<td>
</td>
</tr>
<tr>
<td>Ruby</td>
<td>
<a href=“https://github.com/microsoftgraph/ruby-connect-rest-sample/tree/last_v1_auth”>REST sample</a>
</td>
<td>
<a href=“https://github.com/microsoftgraph/ruby-connect-rest-sample”>REST sample</a>
</td>
</tr>
<tr>
<td>UWP</td>
<td>
<a href=“https://github.com/microsoftgraph/uwp-csharp-connect-rest-sample/tree/last_v1_auth”>REST sample</a>
</td>
<td>
<a href=“https://github.com/microsoftgraph/uwp-csharp-connect-sample”>SDK sample</a> or
<a href=“https://github.com/microsoftgraph/uwp-csharp-connect-rest-sample”>REST sample</a>
</td>
</tr>
<tr>
<td>Xamarin</td>
<td>
</td>
<td>
<a href=“https://github.com/microsoftgraph/xamarin-csharp-connect-sample”>SDK sample</a>
</td>
</tr>
</table>

15.1 See also

16 Use REST APIs to access mailboxes in Exchange hybrid deployments (preview)

Microsoft Graph has always provided access to customer mailboxes in the cloud on Exchange Online as part of Office 365.
Exchange 2016 Cumulative Update 3 (CU3), released in September 2016 for Exchange on-premises servers, adds support for
REST API integration with Office 365. If your app uses v1.0 of the
Mail,
Calendar, or
Contacts API, you will now also find a seamless
authentication and application experience in hybrid deployments, regardless of whether the mailbox
is on-premises or in the cloud, provided that the deployment meets specific requirements.

Behind the scenes, when Microsoft Graph identifies that a REST API call is attempting to access an on-premises
mailbox in a hybrid deployment, it proxies the REST request to an on-premises REST endpoint which then processes
the request. This discovery makes accessing the REST API possible.

Note: The ability to use these REST APIs in hybrid deployments is currently in preview.

Only v1.0 of the Mail, Calendar and Contacts API are available for mailboxes in hybrid deployments. Other v1.0 API sets,
such as the Groups API, or APIs in other versions,
are not. If you attempt to use an API that is not part of the supported set in a hybrid deployment, you will get the following error message:

“REST APIs for this mailbox are currently in preview. You can find more information about the preview REST APIs at https://dev.outlook.com.”

16.1 Requirements for the REST API to work in hybrid deployments

Microsoft Graph provides openness (open standards support like JSON, OAUTH and ODATA, connecting from most popluar platforms)
and flexibility (granular, tightly scoped permissions to access user data).
If your organization is interested in enabling Microsoft Graph app development and is currently in or considering a hybrid deployment,
be aware of the following deployment requirements:

  • Mailbox requirements

  • All on-premises mailboxes that will use the REST APIs must be located on databases located on Exchange 2016 CU3 servers. 

  • Infrastructure requirements

  • All Exchange 2016 servers must be upgraded to CU3 or later.
  • On-premises Active Directory must synchronize with Azure Active Directory.
  • Any Exchange 2013 servers coexisting in the same load-balanced array with Exchange 2016 servers must be removed from the array.

  • Networking requirements

  • From a DNS perspective, the Autodiscover namespace and on-premises client namespace must have Internet DNS records.
  • If you have a firewall or application gateway that inspects and restricts access, update the appropriate settings to allow discovery and access.

IT administrators can find more information in the following resources:

17 Get started with Microsoft Graph in an iOS App

Building apps for enterprise customers? Your app may not work if your enterprise customer turns on enterprise mobility security features like <a href=“https://azure.microsoft.com/en-us/documentation/articles/active-directory-conditional-access-device-policies/” target=“_newtab“>conditional device access</a>. In this case, you may not know and your customers may experience errors.

To support all enterprise customers across all enterprise scenarios, you must use the Azure AD endpoint and manage your apps using the Azure Management Portal. For more information, see Deciding between the Azure AD and Azure AD v2.0 endpoints.

This article describes the tasks required to get an access token from the Azure AD v2.0 endpoint and call Microsoft Graph. It walks you through the code inside the Office 365 Connect Sample for iOS (SDK) to explain the main concepts that you have to implement in an app that uses Microsoft Graph. It describes how to access Microsoft Graph by using the Microsoft Graph SDK for iOS.

You can download the version of the app that you’ll create from this GitHub repo:

The following image shows the app you’ll create.

Connect sample walkthrough, shows connecting and sending a mail in the app

The workflow will be to connect/authenticate to Microsoft Graph, sign in with your work or personal account, and finally send a mail to a recipient.

Don’t feel like building an app? Use the Microsoft Graph quick start to get up and running fast.

17.1 Prerequisites

To get started, you’ll need:

17.2 Register the app

  1. Sign into the App Registration Portal using either your personal or work or school account.
  2. Select Add an app.
  3. Enter a name for the app, and select Create application.

    The registration page displays, listing the properties of your app.

  4. Under Platforms, select Add platform.
  5. Select Mobile platform.
  6. Copy the Client Id to the clipboard. You’ll need to enter this value into the sample app.

    The app id is a unique identifier for your app.

  7. Select Save.

17.3 Importing the project dependencies

  1. Clone this repository, Office 365 Connect Sample for iOS Using the Microsoft Graph SDK. Remember you will use the sample in the starter-project folder and not the sample at the root of the project.
  2. Use CocoaPods to import the Microsoft Graph SDK and authentication dependencies. This sample app already contains a podfile that will get the pods into the project. Navigate to the folder starter-project in the Terminal app, and from Terminal run:

    pod install

You will receive confirmation that the pods have been imported into the project. For more information, see CocoaPods

17.4 Enable keychain sharing

For Xcode8, you need to add the keychain group or your app will fail to access keychain.
To add the keychain group:

  1. Select the project on the project manager panel in Xcode. (⌘ + 1).

  2. Select O365-iOS-Microsoft-Graph-SDK.

  3. On the Capabilities tab, enable Keychain Sharing.

  4. Add com.microsoft.O365-iOS-Microsoft-Graph-SDK to the Keychain Groups.

17.5 Authenticating with Microsoft Graph

To revisit the UI workflow, the app is going to have the user authenticate, and then they’ll have the ability to send a mail to a specified user. To make requests against the Microsoft Graph service, an authentication provider must be supplied which is capable of authenticating HTTPS requests with an appropriate OAuth 2.0 bearer token. In the sample project there’s an authentication class already stubbed out called AuthenticationProvider.m. We will add a function to request, and acquire, an access token for calling the Microsoft Graph API.

  1. Open the Xcode project workspace (O365-iOS-Microsoft-Graph-SDK.xcworkspace) in the starter-project folder, and navigate to the Authentication folder and open the file AuthenticationProvider.m. Add the following code to that class.

    -(void) connectToGraphWithClientId:(NSString *)clientId scopes:(NSArray *)scopes completion:(void (^)   (NSError *))completion{
        [NXOAuth2AuthenticationProvider setClientId:kClientId
                                          scopes:scopes];
    
    
        /**
        Obtains access token by performing login with UI, where viewController specifies the parent view controller.
        @param viewController The view controller to present the UI on.
         @param completionHandler The completion handler to be called when the authentication has completed.
        error should be non nil if there was no error, and should contain any error(s) that occurred.
         */
    
            if ([[NXOAuth2AuthenticationProvider sharedAuthProvider] loginSilent]) {
            completion(nil);
            }
            else {
                [[NXOAuth2AuthenticationProvider sharedAuthProvider] loginWithViewController:nil completion:^(NSError *error) {
                if (!error) {
                NSLog(@"Authentication successful.");
                completion(nil);
                }
             else {
                 NSLog(@"Authentication failed - %@", error.localizedDescription);
                completion(error);
                }
            }];
        }
    
    }
  2. Next add the method to the header file. Open the file AuthenticationProvider.h and add the following code to this class.

    -(void) connectToGraphWithClientId:(NSString *)clientId
                        scopes:(NSArray *)scopes
                    completion:(void (^)(NSError *error))completion;
  3. Finally we’ll call this method from ConnectViewController.m. This controller is the default view that the app loads, and there is a single button named Connect that the user will tap that will initiate the authentication process. This method takes in two parameters, the Client ID and scopes, we’ll discuss these in more detail below. Add the following action to ConnectViewController.m.

    - (IBAction)connectTapped:(id)sender {
        [self showLoadingUI:YES];   
        NSArray *scopes = [kScopes componentsSeparatedByString:@","];
        [self.authProvider connectToGraphWithClientId:kClientId scopes:scopes completion:^(NSError *error) {
            if (!error) {
                [self performSegueWithIdentifier:@"showSendMail" sender:nil];
                [self showLoadingUI:NO];
                NSLog(@"Authentication successful.");
                }
            else{
                NSLog(NSLocalizedString(@"CHECK_LOG_ERROR", error.localizedDescription));
                [self showLoadingUI:NO];
                };
            }];
    }

17.6 Send an email with Microsoft Graph

After configuring the project to be able to authenticate, the next tasks are sending a mail to a user using the Microsoft Graph API. By default the logged in user will be the recipient, but you have the ability to change it to any other recipient. The code we’ll work with here is located in the Controllers folder and in the class SendMailViewController.m. You’ll see that there is other code represented here for the UI, and a helper method to retrieve user profile information from the Microsoft Graph service. We’ll concentrate on the methods for creating a mail message and sending that message.

  1. Open SendMailViewController.m. in the Controllers folder and add the following helper method to the class:

    // Create a sample test message to send to specified user account
    -(MSGraphMessage*) getSampleMessage{
        MSGraphMessage *message = [[MSGraphMessage alloc]init];
        MSGraphRecipient *toRecipient = [[MSGraphRecipient alloc]init];
        MSGraphEmailAddress *email = [[MSGraphEmailAddress alloc]init];
    
        email.address = self.emailAddress;
        toRecipient.emailAddress = email;
    
        NSMutableArray *toRecipients = [[NSMutableArray alloc]init];
        [toRecipients addObject:toRecipient];
    
        message.subject = NSLocalizedString(@"MAIL_SUBJECT", comment: "");
    
        MSGraphItemBody *emailBody = [[MSGraphItemBody alloc]init];
        NSString *htmlContentPath = [[NSBundle mainBundle] pathForResource:@"EmailBody" ofType:@"html"];
        NSString *htmlContentString = [NSString stringWithContentsOfFile:htmlContentPath encoding:NSUTF8StringEncoding error:nil];
    
        emailBody.content = htmlContentString;
        emailBody.contentType = [MSGraphBodyType html];
        message.body = emailBody;
    
        message.toRecipients = toRecipients;
    
        return message;
    
    }
  2. Open SendMailViewController.m. Add the following send mail method to the class.

    //Send mail to the specified user in the email text field
    -(void) sendMail {   
        MSGraphMessage *message = [self getSampleMessage];
        MSGraphUserSendMailRequestBuilder *requestBuilder = [[self.graphClient me]sendMailWithMessage:message saveToSentItems:true];
        NSLog(@"%@", requestBuilder);
        MSGraphUserSendMailRequest *mailRequest = [requestBuilder request];
        [mailRequest executeWithCompletion:^(NSDictionary *response, NSError *error) {
            if(!error){
                NSLog(@"response %@", response);
                NSLog(NSLocalizedString(@"ERROR", ""), error.localizedDescription);
    
                dispatch_async(dispatch_get_main_queue(), ^{
                    self.statusTextView.text = NSLocalizedString(@"SEND_SUCCESS", comment: "");
            });
        }
        else {
            NSLog(NSLocalizedString(@"ERROR", ""), error.localizedDescription);
            self.statusTextView.text = NSLocalizedString(@"SEND_FAILURE", comment: "");
            }
        }];
    
    }

So getSampleMessage creates a draft HTML sample mail to use for demo purposes. The next method, sendMail, then takes that message and executes the request to send it. Again the default recipient is the signed-in user.

17.7 Run the app

  1. Before running the sample you’ll need to supply the client ID you received from the registration process in the section Register the app. Open AuthenticationConstants.m under the Application folder. You’ll see that the ClientID from the registration process can be added to the top of the file.:

    // You will set your application's clientId
    NSString * const kClientId    = @"ENTER_CLIENT_ID_HERE";
    NSString * const kScopes = @"https://graph.microsoft.com/Mail.Send, https://graph.microsoft.com/User.Read, offline_access";

    Note: You’ll notice that the following permission scopes have been configured for this project: https://graph.microsoft.com/Mail.Send”, “https://graph.microsoft.com/User.Read”, “offline_access”. The service calls used in this project, sending a mail to your mail account and retrieving some profile information (Display Name, Email Address) require these permissions for the app to run properly.

  2. Run the sample, tap Connect, sign in with your personal or work or school account, and grant the requested permissions.

  3. Choose the Send email button. When the mail is sent, a success message is displayed below the button.

17.8 Next steps

17.9 See also

18 Combine multiple requests in one HTTP call using JSON batching (preview)

JSON batching allows you to optimize your application by combining multiple requests into a single JSON object. For example, a client might want to compose a view of unrelated data such as:

  1. An image stored in OneDrive
  2. A list of Planner tasks
  3. The calendar for a group

Combining these three individual requests into a single batch request can save the application significant network latency.

18.1 First JSON batch request

First you construct the JSON batch request for the previous example. In this scenario, the individual requests are not interdependent in any way and therefore can be placed into the batch request in any order.

POST https://graph.microsoft.com/beta/$batch
Accept: application/json
Content-Type: application/json
{
  "requests": [
    {
      "id": "1",
      "method": "GET",
      "url": "/me/drive/root:/{file}:/content"
    },
    {
      "id": "2",
      "method": "GET",
      "url": "/me/planner/tasks"
    },
    {
      "id": "3",
      "method": "GET",
      "url": "/groups/{id}/events"
    }
  ]
}

Responses to the batched requests might appear in a different order. The id property can be used to correlate individual requests and responses.

200 OK
Content-Type: application/json
{
  "responses": [
    {
      "id": "1",
      "status": 302,
      "headers": {
        "location": "https://b0mpua-by3301.files.1drv.com/y23vmagahszhxzlcvhasdhasghasodfi"
      }
    },
    {
      "id": "3",
      "status": 401,
      "body": {
        "error": {
          "code": "Forbidden",
          "message": "..."
        }
      }
    },
    {
      "id": "2",
      "status": 200,
      "body": {
        "@odata.context": "https://graph.microsoft.com/beta/$metadata#Collection(microsoft.graph.plannerTask)",
        "value": []
      }
    }
  ]
}

18.2 Request format

Batch requests are always sent using POST to the /$batch endpoint.

A JSON batch request body consists of a single JSON object with one required property: requests. The requests property is an array of individual requests. For each individual request, the id, method, and url properties are required.

The id property functions primarily as a correlation value to associate individual responses with requests. This allows the server to process requests in the batch in the most efficient order.

The method and url properties are exactly what you would see at the start of any given HTTP request. The method is the HTTP method, and the URL is the resource URL the individual request would typically be sent to.

Individual requests can optionally also contain a headers property and a body property. Both of these properties are typically JSON objects, as shown in the previous example. In some cases, the body might be a base64 URL-encoded value rather than a JSON object - for example, when the body is an image. In these cases, the headers object must contain a value for content-type.

18.3 Response format

The response format for JSON batch requests is similar to the request format. The following are the key differences:

  • The property in the main JSON object is named responses as opposed to requests.
  • Individual responses might appear in a different order than the requests.
  • Rather than method and url, individual responses have a status property. The value of status is a number that represents the HTTP status code.

The status code on a batch response is typically 200 or 400. If the batch request itself is malformed, the status code is 400. If the batch request is parseable, the status code is 200. A 200 status code on the batch response does not indicate that the individual requests inside the batch succeeded. This is why each individual response in the responses property has a status code.

In addition to the responses property, there might be a nextLink property in the batch response. This allows Microsoft Graph to return a batch response as soon as any of the individual requests has completed. To ensure that all individual responses have been received, continue to follow the nextLink as long as it exists.

18.4 Sequencing requests with the dependsOn property

Individual requests can be executed in a specified order by using the dependsOn property. This property is an array of strings that reference the id of a different individual request. For this reason, the values for id must be unique. For example, in the following request, the client is specifying that requests 1 and 3 should be run first, then request 2, then request 4.

{
  "requests": [
    {
      "id": "1",
      "method": "GET",
      "url": "..."
    },
    {
      "id": "2",
      "dependsOn": [ "1" ],
      "method": "GET",
      "url": "..."
    },
    {
      "id": "3",
      "method": "GET",
      "url": "..."
    },
    {
      "id": "4",
      "dependsOn": [ "2" ],
      "method": "GET",
      "url": "..."
    }
  ]
}

If an individual request fails, any request that depends on that request fails with status code 424 (Failed Dependency).

18.5 Bypassing URL length limitations with batching

An additional use case for JSON batching is to bypass URL length limitations. In cases where the filter clause is complex, the URL length might surpass limitations built into browsers or other HTTP clients. You can use JSON batching as a workaround for running these requests because the lengthy URL simply becomes part of the request payload.

18.6 Known issues

For a list of current limitations related to batching, see known issues.

18.7 See also

For more information about the JSON batch request/response format, see the OData JSON Format Version 4.01 specification, section 18. Note that this specification is currently in a draft version, but is not expected to change.

19 Known issues with Microsoft Graph

This article describes known issues with Microsoft Graph. For information about the latest updates, see the Microsoft Graph changelog.

19.1 Users

19.1.1 No instant access after creation

Users can be created immediately through a POST on the user entity. An Office 365 license must first be assigned to a user, in order to get access to Office 365 services. Even then, due to the distributed nature of the service, it might take 15 minutes before files, messages and events entities are available for use for this user, through the Microsoft Graph API. During this time, apps will receive a 404 HTTP error response.

19.1.2 Photo restrictions

Reading and updating a user’s profile photo is only possible if the user has a mailbox. Additionally, any photos that may have been previously stored using the thumbnailPhoto property (using the Office 365 unified API preview, or the Azure AD Graph, or through AD Connect synchronization) are no longer accessible through the Microsoft Graph photo property of the user resource.
Failure to read or update a photo, in this case, would result in the following error:

    {
      "error": {
        "code": "ErrorNonExistentMailbox",
        "message": "The SMTP address has no mailbox associated with it."
      }
    }

19.1.3 Using delta query

For known issues using delta query, see the delta query section in this article.

19.2 Groups and Microsoft Teams

Note Microsoft Teams is currently in preview and is available only in the Microsoft Graph beta endpoint.

19.2.1 Policy

Using Microsoft Graph to create and name an Office 365 group bypasses any Office 365 group policies that are configured through Outlook Web App.

19.2.2 Permissions for groups and Microsoft Teams

Microsoft Graph exposes two permission (Group.Read.All and Group.ReadWrite.All) for access to the APIs for groups and Microsoft Teams.
These permission must be consented to by an administrator (which is a change from preview). In the future, we plan to add new permissions for groups and teams that users can consent to.

Also, only the API for core group administration and management supports access using delegated or app-only permissions. All other features of the group API support only delegated permissions.

Examples of group features that support delegated and app-only permissions:

  • Creating and deleting groups
  • Getting and updating group properties pertaining to group administration or management
  • Group directory settings, type and synchronization
  • Group owners and membership

Examples of group features that support only delegated permissions:

  • Group conversations, events, photo
  • External senders, accepted or rejected senders, group subscription
  • User favorites and unseen count
  • Microsoft Teams channels and chats.

19.2.3 Teams in Microsoft Teams (preview)

Microsoft Teams and Office 365 groups share similar functionality. All group APIs can be used with teams, with the exception that the Create group API does not currently allow you to create a team. Future API releases will support this.

19.2.4 Microsoft Teams channels (preview)

Currently, you can read and create channels, but you cannot update or delete them. Future API releases will support this.

19.2.5 Microsoft Teams chat threads and chat messages (preview)

Currently, you can create chat threads in channels, but you cannot read existing chat threads or add replies to them. Also, you cannot read or write direct chats between users that are outside the scope of a team or channel. Future API releases will add additional capabilities in this area.

19.2.6 Microsoft Teams user’s list of joined teams (preview)

Currrently, listing the teams a user has joined only works for the ‘me’ user for which the caller has delegated permissions. Future releases will support this operation for any specified user ID.

19.2.7 Adding and getting attachments of group posts

Adding attachments to group posts, listing and
getting attachments of group posts currently return the error message “The OData request is not supported.” A fix has been rolled out for both the /v1.0 and /beta versions,
and is expected to be widely available by the end of January 2016.

19.2.8 Setting the allowExternalSenders property

There is currently an issue that prevents setting the allowExternalSenders property of a group in a POST or PATCH operation, in both /v1.0 and /beta.

19.2.9 Using delta query

For known issues using delta query, see the delta query section in this article.

19.3 Calendars

19.3.1 Adding and accessing ICS-based calendars in user’s mailbox

Currently, there is partial support for a calendar based on an Internet Calendar Subscription (ICS):

  • You can add an ICS-based calendar to a user mailbox through the user interface, but not through the Microsoft Graph API.
  • Listing the user’s calendars lets you get the name, color and id properties of each calendar in the user’s default calendar group, or a specified calendar group, including any ICS-based calendars. You cannot store or access the ICS URL in the calendar resource.
  • You can also list the events of an ICS-based calendar.

19.3.2 Accessing a shared calendar

When attempting to access events in a calendar that has been shared by another user using the following operation:

GET \users('{id}')\calendars('{id}')\events

You may get HTTP 500 with the error code ErrorInternalServerTransientError. The error occurs because:

  • Historically, there are two ways that calendar sharing has been implemented, which, for the purpose of differentiating them,
    are referred to as the “old” approach and “new” approach.
  • The new approach is currently available for sharing calendars with view or edit permissions, but not with delegate permissions.
  • You can use the calendar REST API to view or edit shared calendars only if the calendars were shared using the new approach.
  • You cannot use the calendar REST API to view or edit such calendars (or their events) if the calendars were shared using the old approach.

If a calendar was shared with view or edit permissions but using the old approach, you can now work around the error and manually upgrade the calendar sharing to use the new approach.
Over time, Outlook will autmatically upgrade all shared calendars to use the new approach, including calendars shared with delegate permissions.

To manually upgrade a shared calendar to use the new approach, follow these steps:

  1. The recipient removes the calendar that was previously shared to them.
  2. The calendar owner re-shares the calendar in Outlook on the web, Outlook on iOS, or Outlook on Android.
  3. The recipient re-accepts the shared calendar using Outlook on the web. (It will be possible to use other Outlook clients soon.)
  4. The recipient verifies that the calendar has been re-shared successfully using the new approach by being able to view the shared calendar in Outlook on iOS or Outlook on Android.

A calendar shared with you in the new approach appears as just another calendar in your mailbox. You can use the calendar REST API to view or edit
events in the shared calendar, as if it’s your own calendar. As an example:

GET \me\calendars('{id}')\events

19.4 Contacts

19.4.1 Organization contacts available in only beta

Only personal contacts are currently supported. Organizational contacts are not currently supported in /v1.0, but can be found in /beta.

19.4.2 Default contacts folder

In the /v1.0 version, GET /me/contactFolders does not include the user’s default contacts folder.

A fix will be made available. Meanwhile, you can use the following list contacts query and the parentFolderId property
as a workaround to get the folder ID of the default contacts folder:

GET https://graph.microsoft.com/v1.0/me/contacts?$top=1&$select=parentFolderId

In the above query:

  1. /me/contacts?$top=1 gets the properties of a contact in the default contacts folder.
  2. Appending &$select=parentFolderId returns only the contact’s parentFolderId property, which is the ID of the default contacts folder.

19.4.3 Accessing contacts via a contact folder in beta

In the /beta version, there is currently an issue that prevents accessing a contact
by specifying its parent folder in the REST request URL, as shown in the 2 scenarios below.

  • Accessing a contact from a top level contactFolder of the user’s.
GET /me/contactfolders/{id}/contacts/{id}
GET /users/{id | userPrincipalName}/contactfolders/{id}/contacts/{id}
  • Accessing a contact contained in a child folder of a contactFolder. The example below shows one level of nesting, but a contact can be located in a child of a child and so on.
GET /me/contactFolder/{id}/childFolders/{id}/.../contacts/{id}
GET /users/{id | userPrincipalName}/contactFolders/{id}/childFolders/{id}/contacts/{id}

As an alternative, you can simply get the contact by specifying its ID as shown below,
since GET /contacts in the /beta version applies to all the contacts in the user’s mailbox:

GET /me/contacts/{id}
GET /users/{id | userPrincipalName}/contacts/{id}

19.5 Messages

19.5.1 The comment parameter for creating a draft

The comment parameter for creating a reply or forward draft (createReply,
createReplyAll, createForward)
does not become part of the body of the resultant message draft.

19.6 Drives, files and content streaming

  • First time access to a user’s personal drive through the Microsoft Graph before the user accesses their personal site through a browser leads to a 401 response.

19.7 Query parameter limitations

  • $expand limitations:
    • No support for nextLink
    • No support for more than 1 level of expand
    • No support with extra parameters ($filter, $select)
  • Multiple namespaces are not supported
  • GETs on $ref and casting is not supported on users, groups, devices, service principals and applications.
  • @odata.bind is not supported. This means that developers won’t be able to properly set the Accepted or RejectedSenders on a group.
  • @odata.id is not present on non-containment navigations (like messages) when using minimal metadata
  • Cross-workload filtering/search is not available.
  • Full-text search (using $search) is only available for some entities, like messages.

19.8 Delta query

  • OData context is sometimes returned incorrectly when tracking changes to relationships.
  • Schema extensions (legacy) are not returned with $select statement, but are returned without $select.
  • Clients cannot track changes to open extensions or registered schema extensions.

19.9 Application and servicePrincipal API changes

There are changes to the application and servicePrincipal entities currently in development. The following is a summary of current limitations and in-development API features.

Current limitations:

  • Some application properties (such as appRoles and addIns) will not be available until all changes are completed.
  • Only multi-tenant apps can be registered.
  • Updating apps is restricted to apps registered after the initial beta update.
  • Azure Active Directory users can register apps and add additional owners.
  • Support for OpenID Connect and OAuth protocols.
  • Policy assignments to an application fail.
  • Operations on ownedObjects that require appId fail (For example, users/{id|userPrincipalName}/ownedObjects/{id}/…).

In development:

  • Ability to register single tenant apps.
  • Updates to servicePrincipal.
  • Migration of existing Azure AD apps to updated model.
  • Support for appRoles, pre-authorized clients, optional claims, group membership claims, and branding
  • Microsoft account (MSA) users can register apps.
  • Support for SAML and WsFed protocols.

19.10 Extensions

19.10.1 Change tracking is not supported

Change tracking (delta query) is not supported for open or schema extension properties.

19.10.2 Creating a resource and open extension at the same time

You cannot specify an open extension at the same time you create an instance of administrativeUnit, device, group, organization or user. You must first create the instance and then specify the open extension data in a subsequent POST request on that instance.

19.10.3 Limit of 100 schema extension property values allowed per resource instance

Directory resources, such as device, group and user, currently limit the total number of schema extension property values that can be set on a resource instance, to 100.

19.11 JSON Batching

19.11.1 No nested batch

JSON batch requests must not contain any nested batch requests.

19.11.2 All individual requests must be synchronous

All requests contained in a batch request must be executed synchronously. If present, the respond-async preference will be ignored.

19.11.3 No transactions

Microsoft Graph does not currently support transactional processing of individual requests. The atomicityGroup property on individual requests will be ignored.

19.11.4 URIs must be relative

Always specify relative URIs in batch requests. Microsoft Graph then makes these URLs absolute by using the version endpoint included in the batch URL.

19.11.5 Limit on batch size

JSON batch requests are currently limited to 5 individual requests. As JSON batching matures, this limit will be raised.

19.11.6 Simplified dependencies

Individual requests can depend on other individual requests. Currently, requests can only depend on a single other request, and must follow one of these three patterns:

  1. Parallel - no individual request states a dependency in the dependsOn property.
  2. Serial - all individual requests depend on the previous individual request.
  3. Same - all individual requests that state a dependency in the dependsOn property, state the same dependency.

As JSON batching matures, these limitations will be removed.

19.12 Cloud Solution Provider apps

19.12.1 CSP apps must use Azure AD endpoint

Cloud solution provider (CSP) apps must acquire tokens from the Azure AD (v1) endpoints to successfully call Microsoft Graph in their partner-managed customers. Currently, acquiring a token through the newer Azure AD v2.0 endpoint is not supported.

Under certain circumstances, pre-consent for CSP apps may not work for some of your customer tenants.

  • For apps using delegated permissions, when using the app for the first time with a new customer tenant you might receive this error after sign-in: AADSTS50000: There was an error issuing a token.
  • For apps using application permissions, your app can acquire a token, but unexpectedly gets an access denied message when calling Microsoft Graph.

We are working to fix this issue as soon as possible, so that pre-consent will work for all your customer tenants.

In the meantime, to unblock development and testing you can use the following workaround.

NOTE: This is not a permanent solution and is only intended to unblock development. This workaround will not be required once the aforementioned issue is fixed. This workaround does not need to be undone once the fix is in place.

  1. Open an Azure AD v2 PowerShell session and connect to your customer tenant by entering your admin credentials into the sign-in window. You can download and install Azure AD PowerShell V2 from here.

    Connect-AzureAd -TenantId {customerTenantIdOrDomainName}
  2. Create the Microsoft Graph service principal.

    New-AzureADServicePrincipal -AppId 00000003-0000-0000-c000-000000000000

19.13 Functionality available only in Office 365 REST or Azure AD Graph APIs

Some functionality is not yet available in Microsoft Graph. If you don’t see the functionality you’re looking for, you can use the endpoint-specific Office 365 REST APIs. For Azure Active Directory, please refer to the Microsoft Graph or Azure AD Graph blog post on the features that are only available through Azure AD Graph API.

19.14 Feedback

Your feedback is important to us. Connect with us on Stack Overflow.

20 Get started with Microsoft Graph in a Node.js app

This article describes the tasks required to get an access token from the Azure AD v2.0 endpoint and call Microsoft Graph. It walks you through building the Microsoft Connect Sample for Node.js and explains the main concepts that you implement to use Microsoft Graph. The article describes how to access the Microsoft Graph API by using raw REST calls.

The following image shows is the app you’ll create.

The web app after login showing the Send mail button

Don’t feel like building an app? Use the Microsoft Graph quick start to get up and running fast.

To download a version of the Connect sample that uses the Azure AD endpoint, see Microsoft Graph Connect Sample for Node.js.

20.1 Prerequisites

To get started, you’ll need:

20.2 Register the application

Register an app on the Microsoft App Registration Portal. This generates the app ID and password that you’ll use to configure the app in Visual Studio.

  1. Sign into the Microsoft App Registration Portal using either your personal or work or school account.

  2. Choose Add an app.

  3. Enter a name for the app, and choose Create application.

    The registration page displays, listing the properties of your app.

  4. Copy the application ID. This is the unique identifier for your app.

  5. Under Application Secrets, choose Generate New Password. Copy the password from the New password generated dialog.

    You’ll use the application ID and application password (secret) to configure the app.

  6. Under Platforms, choose Add platform > Web.

  7. Enter *http://localhost:3000/token* as the Redirect URI.

  8. Choose Save.

20.3 Configure the project

  1. Open the starter-project folder in the sample files.

  2. In a command prompt, run the following command in the root directory of the starter project. This installs the project dependencies.

    npm install
  3. In the starter project files, open utils\config.js.

  4. In the credentials field, replace the ENTER_YOUR_CLIENT_ID and ENTER_YOUR_SECRET placeholder values with the values you just copied.

20.4 Authenticate the user and get an access token

In this step, you’ll add sign-in and token management code. But first, let’s take a closer look at the auth flow.

This app uses the authorization code grant flow with a delegated user identity. For a web application, the flow requires the application ID, secret, and redirect URI from the registered app.

The auth flow can be broken down into these basic steps:

  1. Redirect the user for authentication and consent
  2. Get an authorization code
  3. Redeem the authorization code for an access token
  4. Use the refresh token to get a new access token when the access token expires

The app uses the oauth middleware to authenticate and obtain tokens. It uses the cookie-parser middleware to cache token information in cookies. The code used to store and access token information is found in the index.js controller.

Important The simple authentication and token handling in this project is for sample purposes only. In a production app, you should construct a more robust way of handling authentication, including validation and secure token handling.

Now you’re ready to add code to call Microsoft Graph.

20.5 Call Microsoft Graph

The app calls Microsoft Graph to get user information and to send an email on the user’s behalf. These calls are initiated from the index.js controller in response to UI events.

  1. Open utils\graphHelper.js.

  2. Replace the getUserData function with the following code. This configures and sends the GET request to the /me endpoint and processes the response.

    function getUserData(accessToken, callback) {
      request
       .get('https://graph.microsoft.com/v1.0/me')
       .set('Authorization', 'Bearer ' + accessToken)
       .end((err, res) => {
         callback(err, res);
       });
    }
  3. Replace the getProfilePhoto function with the following code. This configures and sends the GET request to the /me/photo/$value endpoint and processes the response. Note that profile photos aren’t currently available for MSA accounts.

    function getProfilePhoto(accessToken, callback) {
      // Get the profile photo of the current user (from the user's mailbox on Exchange Online).
      // This operation in version 1.0 supports only work or school mailboxes, not personal mailboxes.
      request
       .get('https://graph.microsoft.com/v1.0/me/photo/$value')
       .set('Authorization', 'Bearer ' + accessToken)
       .end((err, res) => {
         // Returns 200 OK and the photo in the body. If no photo exists, returns 404 Not Found.
         callback(err, res.body);
       });
    }
  4. Replace the uploadFile function with the following code. This configures and sends the PUT request to the /me/drive/root/children/mypic.jpg/content endpoint. If the file exists, this requests updates the content. If it doesn’t exist, it creates the file and uploads the contents of the profile photo.

    function uploadFile(accessToken, file, callback) {
      // This operation only supports files up to 4MB in size.
      // To upload larger files, see `https://developer.microsoft.com/graph/docs/api-reference/v1.0/api/item_createUploadSession`.
      request
       .put('https://graph.microsoft.com/v1.0/me/drive/root/children/mypic.jpg/content')
       .send(file)
       .set('Authorization', 'Bearer ' + accessToken)
       .set('Content-Type', 'image/jpg')
       .end((err, res) => {
         // Returns 200 OK and the file metadata in the body.
         callback(err, res.body);
       });
    }
  5. Replace the getSharingLink function with the following code. This configures and sends the GET request to the /me/drive/items/{file id}/createLink endpoint and processes the result. The result is a sharing link to the file that will be included in the message.

    function getSharingLink(accessToken, id, callback) {
      request
       .post('https://graph.microsoft.com/v1.0/me/drive/items/' + id + '/createLink')
       .send({ type: 'view' })
       .set('Authorization', 'Bearer ' + accessToken)
       .set('Content-Type', 'application/json')
       .end((err, res) => {
         // Returns 200 OK and the permission with the link in the body.
         callback(err, res.body.link);
       });
    }
  6. Replace the postSendMail function with the following code. This configures and sends the POST request to the /me/sendMail endpoint and processes the response.

    function postSendMail(accessToken, message, callback) {
      request
       .post('https://graph.microsoft.com/v1.0/me/sendMail')
       .send(message)
       .set('Authorization', 'Bearer ' + accessToken)
       .set('Content-Type', 'application/json')
       .set('Content-Length', message.length)
       .end((err, res) => {
         // Returns 202 if successful.
         // Note: If you receive a 500 - Internal Server Error
         // while using a Microsoft account (outlook.com, hotmail.com or live.com),
         // it's possible that your account has not been migrated to support this flow.
         // Check the inner error object for code 'ErrorInternalServerTransientError'.
         // You can try using a newly created Microsoft account or contact support.
         callback(err, res);
       });
    }
  7. Open utils\emailer.js.

  8. Replace the wrapEmail function with the following code. This builds the payload that represents the email message to send.

    function wrapEmail(content, recipient, file) {
      const attachments = [{
        '@odata.type': '#microsoft.graph.fileAttachment',
        ContentBytes: file,
        Name: 'mypic.jpg'
      }];
      const emailAsPayload = {
        Message: {
          Subject: 'Welcome to Microsoft Graph development with Node.js and the Microsoft Graph Connect sample',
          Body: {
            ContentType: 'HTML',
            Content: content
          },
          ToRecipients: [
            {
              EmailAddress: {
                Address: recipient
              }
            }
          ]
        },
        SaveToSentItems: true,
        Attachments: attachments
      };
      return emailAsPayload;
    }

20.6 Run the app

  1. In a command prompt, run the following command in the root directory of the starter project.

    npm start
  2. In a browser, navigate to *http://localhost:3000* and choose the Connect to Office 365 button.

  3. Sign in and grant the requested permissions.

  4. Optionally edit the recipient’s email address, and then choose the Send mail button. When the mail is sent, a Success message is displayed below the button.

20.7 Next steps

20.8 See also

21 Call Office 365 services in Visual Studio 2017 with the Microsoft Graph API

You can use the Connected Services in Visual Studio to configure your app to call the Microsoft Graph API. This article describes how to get a signed in user’s profile photo, upload it to OneDrive, and send an email with a sharing link to the photo.

21.1 Get set up

To use the Office 365 Connected Services with Microsoft Graph, you’ll need to do the following:

  • Download the Visual Studio 2017 Preview, if you haven’t already. If you’re using an earlier version of Visual Studio, you can use Visual Studio 2017 Preview side by side with your current version.

  • Get an Office 365 subscription. To get a free trial, join the Office 365 Developer program.

21.2 Get the starter project

Download the Microsoft Graph ASP.NET Connected Services Sample. This sample includes the references that you need to authenticate against Microsoft Graph. After you download the starter project, unzip, and open the sample in Visual Studio 2017 Preview.

21.3 Add the Connected Service

You’re now ready to add the Microsoft Graph service to your Visual Studio project.

  1. In Solution Explorer, choose Connected Services to open the Connected Services tab.

  2. Choose the Access Office 365 Services with Microsoft Graph provider. Follow the wizard. Select the following permissions (you can change the permisssions later):

    • For the File APIs, set permissions to Have full access to your files.
    • For the Mail APIs, set permissions to Send mail as you.
    • For the User APIs, set permissions to Sign you in and read your profile.

21.4 Call the Microsoft Graph API

The starter sample is configured to send a simple email. You can use Microsoft Graph to update the sample to send an email with a link to the signed-in user’s profile photo in OneDrive.

  1. Go to ‘Models\GraphService.cs’, which hosts the code to call Microsoft Graph.

  2. Find and Uncomment calls to the SDK in the following methods. This shows how to call Microsoft Graph to get a profile photo, upload a file to OneDrive, and get a sharing link.

        GetCurrentUserPhotoStream(GraphServiceClient graphClient)
        UploadFileToOneDrive(GraphServiceClient graphClient, byte[] file)
        GetSharingLink(GraphServiceClient graphClient, string Id)

**Tip:** Each comment starts with ‘//Uncomment:’

21.5 Run the sample

Build and run the sample. Next, choose the Sign-in link on the top right, and then choose Get email address followed by Send email.

This will send an email that includes a link to your profile photo.

**Notes:**

  • If you stop and rerun the sample from Visual Studio, you might need to explicitly sign out for the sample to work.
  • If you get an exception that indicates that the User is not authenticated, you might need to repeat the Add the Connected Service step.

21.6 Explore the code

You can now use Visual Studio 2017 to connect to and configure your services. The starter sample creates the scaffolding and references for you.

The starter sample includes the following files:

21.7 Need help?

If you need help, post your questions on StackOverflow. Tag your post with {microsoftgraph}.

22 Overview of Microsoft Graph

You can use the Microsoft Graph API to interact with the data of millions of users in the Microsoft cloud. Use Microsoft Graph to build apps for organizations and consumers that connect to a wealth of resources, relationships, and intelligence, all through a single endpoint: https://graph.microsoft.com.

22.1 What’s in the graph?

Microsoft Graph is made up of resources connected by relationships. For example, a user can be connected to a group through a memberOf relationship, and to another user through a manager relationship. Your app can traverse these relationships to access these connected resources and perform actions on them through the API.

You can also get valuable insights and intelligence about the data from Microsoft Graph. For example, you can get the popular files trending around a particular user, or get the most relevant people around a user.

Discover the possibilities in the relationships within Microsoft Graph.

An image showing the primary resources and relationships that are part of the graph

22.2 What can you do with Microsoft Graph?

You can use Microsoft Graph to build experiences around the user’s unique context to help them be more productive. Imagine an app that…

  • Looks at your next meeting and helps you prepare for it by providing profile information for attendees, including their job titles and who they work with, as well as information on the latest documents and projects they’re working on.
  • Scans your calendar, and suggests the best times for the next team meeting.
  • Fetches the latest sales projection chart from an Excel file in your OneDrive and lets you update the forecast in real time, all from your phone.
  • Subscribes to changes in your calendar, sends you an alert when you’re spending too much time in meetings, and provides recommendations for the ones you could miss or delegate based on how relevant the attendees are to you.
  • Helps you sort out personal and work information on your phone; for example, by categorizing pictures that should go to your personal OneDrive and business receipts that should go to your OneDrive for Business.

You can do all this and more with the Microsoft Graph API.

22.3 Next steps

22.4 Feedback?

Your feedback is important to us. Connect with us on Stack Overflow. Tag your questions with {MicrosoftGraph}.



23 Paging Microsoft Graph data in your app

When Microsoft Graph requests return too much information to show on one page, you can use paging to break the information into manageable chunks.

You can page forward and backward in Microsoft Graph responses. A response that contains paged results will include a skip token (odata.nextLink) that allows you to get the next page of results. This skip token can be combined with a previous-page=true query argument to page backward.

The follow request example shows paging forward:

https://graph.microsoft.com/v1.0/users?$top=5$skiptoken=X'4453707402.....0000'

The $skiptoken parameter from the previous response is included, and allows you to get the next page of results.

The following request example shows paging backward:

https://graph.microsoft.com/v1.0/users?$top=5$skiptoken=X'4453707.....00000'&previous-page=true

The $skiptoken parameter from the previous response is included. When this is combined with the &previous-page=true parameter, the previous page of results will be retrieved.

The following are the request/response steps to page forward and backward:

  1. A request is made to get a list of the first 10 users out of 15. The response contains a skip token to indicate the final page of 10 users.
  2. To get the final 5 users, another request is made that contains the skip token returned from the previous response.
  3. To page backward, a request is made using the skip token returned in step 1 and the parameter &previous-page=true is added to the request.
  4. The response contains the previous (first) page of 10 users. In a different scenario where more pages are left, a new skip token would be returned. This new skip token can be added to the request along with &previous-page=true to page backward again.

The following restrictions apply to paged requests:

  • The default page size is 100. The maximum page size is 999.
  • Queries against roles do not support paging. This includes reading role objects themselves as well as role members.
  • Paging is not supported for link searches, such as for querying group members.

24 Use the People API in Microsoft Graph to get information about the people most relevant to you

Microsoft Graph applications can use the People API to retrieve the people who are most relevant to a user. Relevance is determined by the user’s communication and collaboration patterns and business relationships. People can be local contacts, contacts from social networking or from an organization’s directory, and people from recent communications (such as email and Skype). Along with generating this insight, the People API also provides fuzzy matching search support and the ability to retrieve the list of users relevant to another user in the signed-in user’s organization.
The People API is particularly useful for people picking scenarios, such as composing an email or creating a meeting. For example, you can use the People API in email compose scenarios.

24.1 Authorization

To call the People API in Microsoft Graph, your app will need the appropriate permissions:

  • People.Read - Use to make general People API calls; for example, https://graph.microsoft.com/v1.0/me/people/. People.Read requires end user consent.
  • People.Read.All - Required to retrieve the people most relevant to a specified user in the signed-in user’s organization (https://graph.microsoft.com/v1.0/users(‘{id}’)/people) calls. People.Read.All requires admin consent.

    24.1 Browse people

    The requests in this section get the people most relevant to the signed-in user (/me). These requests require the People.Read permission. By default, each response returns 10 records, but you can change this by using the $top query parameter.

    24.1 Get a collection of relevant people

    The following request gets the people most relevant to the signed-in user (/me), based on communication and collaboration patterns and business relationships.

GET https://graph.microsoft.com/v1.0/me/people/

The following example shows the response. By default, each response returns 10 records. You can change this by using the $top query parameter. This example uses $top to limit the response to three records.

HTTP/1.1 200 OK
Content-type: application/json

{
    "value": [
        {
            "id": "8CE6E1DE-CB84-4BF5-971D-D3ECF452E2B5",
            "displayName": "Lorrie Frye",
            "givenName": "Lorrie",
            "surname": "Frye",
            "birthday": "",
            "personNotes": "",
            "isFavorite": false,
            "jobTitle": "Paralegal",
            "companyName": null,
            "yomiCompany": "",
            "department": "Legal",
            "officeLocation": "20/1109",
            "profession": "",
            "userPrincipalName": "Lorrief@contoso.onmicrosoft.com",
            "imAddress": "sip:Lorrief@contoso.onmicrosoft.com",
            "scoredEmailAddresses": [
                {
                    "address": "Lorrief@contoso.onmicrosoft.com",
                    "relevanceScore": 8
                }
            ],
            "phones": [
                {
                    "type": "Business",
                    "number": "+1 980 555 0101"
                }
            ],
            "postalAddresses": [],
            "websites": [],
            "personType": {
                "class": "Person",
                "subclass": "OrganizationUser"
            }
        },
        {
            "id": "5767393D-42BA-4E5C-BEE4-52BB25639CF4",
            "displayName": "Maynard Denman",
            "givenName": "Maynard",
            "surname": "Denman",
            "birthday": "",
            "personNotes": "",
            "isFavorite": false,
            "jobTitle": "Web Marketing Manager",
            "companyName": null,
            "yomiCompany": "",
            "department": "Sales & Marketing",
            "officeLocation": "20/1101",
            "profession": "",
            "userPrincipalName": "Maynardd@contoso.onmicrosoft.com",
            "imAddress": "sip:Maynardd@contoso.onmicrosoft.com",
            "scoredEmailAddresses": [
                {
                    "address": "Maynardd@contoso.onmicrosoft.com",
                    "relevanceScore": 8
                }
            ],
            "phones": [
                {
                    "type": "Business",
                    "number": "+1 918 555 0101"
                }
            ],
            "postalAddresses": [],
            "websites": [],
            "personType": {
                "class": "Person",
                "subclass": "OrganizationUser"
            }
        },
        {
            "id": "914B5191-11FA-4C0B-A354-0FA8C8EFD585",
            "displayName": "Darrel Halsey",
            "givenName": "Darrel",
            "surname": "Halsey",
            "birthday": "",
            "personNotes": "",
            "isFavorite": false,
            "jobTitle": "Attorney",
            "companyName": null,
            "yomiCompany": "",
            "department": "Legal",
            "officeLocation": "14/1102",
            "profession": "",
            "userPrincipalName": "Darrelh@contoso.onmicrosoft.com",
            "imAddress": "sip:Darrelh@contoso.onmicrosoft.com",
            "scoredEmailAddresses": [
                {
                    "address": "Darrelh@contoso.onmicrosoft.com",
                    "relevanceScore": 8
                }
            ],
            "phones": [
                {
                    "type": "Business",
                    "number": "+1 205 555 0103"
                }
            ],
            "postalAddresses": [],
            "websites": [],
            "personType": {
                "class": "Person",
                "subclass": "OrganizationUser"
            }
        }
    ]
}

24.1.1 Request a subsequent page of people

If the first response does not contain the complete list of relevant people, you can make a second request using $top and $skip to request additional pages of information. If the previous request has additional information, the following request gets the next page of people from the server.

GET https://graph.microsoft.com/v1.0/me/people/?$top=3&$skip=10

The following example shows the response. By default, each response returns 10 records. You can change this by using the $top query parameter. This example uses $top to limit the response to three records.

HTTP/1.1 200 OK
Content-type: application/json

{
    "value": [
        {
            "id": "1F28616D-BDFE-4080-8F06-03366A851688",
            "displayName": "Felix Coppola",
            "givenName": "Felix",
            "surname": "Coppola",
            "birthday": "",
            "personNotes": "",
            "isFavorite": false,
            "jobTitle": "CVP Legal",
            "companyName": null,
            "yomiCompany": "",
            "department": "Legal",
            "officeLocation": "19/2109",
            "profession": "",
            "userPrincipalName": "Felixc@contoso.onmicrosoft.com",
            "imAddress": "sip:Felixc@contoso.onmicrosoft.com",
            "scoredEmailAddresses": [
                {
                    "address": "Felixc@contoso.onmicrosoft.com",
                    "relevanceScore": 8
                }
            ],
            "phones": [
                {
                    "type": "Business",
                    "number": "+1 309 555 0104"
                }
            ],
            "postalAddresses": [],
            "websites": [],
            "personType": {
                "class": "Person",
                "subclass": "OrganizationUser"
            }
        },
        {
            "id": "8A3FC021-6DBB-44AC-8884-B7B500CC260A",
            "displayName": "Lenora Rowland",
            "givenName": "Lenora",
            "surname": "Rowland",
            "birthday": "",
            "personNotes": "",
            "isFavorite": false,
            "jobTitle": "Marketing Assistant",
            "companyName": null,
            "yomiCompany": "",
            "department": "Sales & Marketing",
            "officeLocation": "18/1106",
            "profession": "",
            "userPrincipalName": "Lenorar@contoso.onmicrosoft.com",
            "imAddress": "sip:Lenorar@contoso.onmicrosoft.com",
            "scoredEmailAddresses": [
                {
                    "address": "Lenorar@contoso.onmicrosoft.com",
                    "relevanceScore": 8
                }
            ],
            "phones": [
                {
                    "type": "Business",
                    "number": "+1 954 555 0118"
                }
            ],
            "postalAddresses": [],
            "websites": [],
            "personType": {
                "class": "Person",
                "subclass": "OrganizationUser"
            }
        },
        {
            "id": "032C9919-4DF9-4715-8C46-4D0FAE7B3EB2",
            "displayName": "Manuel Collette",
            "givenName": "Manuel",
            "surname": "Collette",
            "birthday": "",
            "personNotes": "",
            "isFavorite": false,
            "jobTitle": "Accountant II",
            "companyName": null,
            "yomiCompany": "",
            "department": "Finance",
            "officeLocation": "98/2202",
            "profession": "",
            "userPrincipalName": "Manuelc@contoso.onmicrosoft.com",
            "imAddress": "sip:Manuelc@contoso.onmicrosoft.com",
            "scoredEmailAddresses": [
                {
                    "address": "Manuelc@contoso.onmicrosoft.com",
                    "relevanceScore": 8
                }
            ],
            "phones": [
                {
                    "type": "Business",
                    "number": "+20 255501070"
                }
            ],
            "postalAddresses": [],
            "websites": [],
            "personType": {
                "class": "Person",
                "subclass": "OrganizationUser"
            }
        }
    ]
}

24.1.2 Sort the response

By default, the people in the response are sorted by their relevance to your query. You can change the order of the people in the response by using the $orderby parameter. This query selects the people most relevant to you, sorts them by their displayName, and then returns the first 10 people on the sorted list.

GET https://graph.microsoft.com/v1.0/me/people/?$orderby=displayName

The following example shows the response. By default, each response returns 10 records. You can change this by using the $top parameter. The following example uses $top to limit the response to three records.

HTTP/1.1 200 OK
Content-type: application/json

{
    "value": [
        {
            "id": "818E29A1-E6BB-4EDA-AB20-8230B4B1E290",
            "displayName": "Adriana Ramos",
            "givenName": "Adriana",
            "surname": "Ramos",
            "birthday": "",
            "personNotes": "",
            "isFavorite": false,
            "jobTitle": "Product Marketing Manager",
            "companyName": null,
            "yomiCompany": "",
            "department": "Sales & Marketing",
            "officeLocation": "18/2111",
            "profession": "",
            "userPrincipalName": "Adrianar@contoso.onmicrosoft.com",
            "imAddress": "sip:Adrianar@contoso.onmicrosoft.com",
            "scoredEmailAddresses": [
                {
                    "address": "Adrianar@contoso.onmicrosoft.com",
                    "relevanceScore": 8
                }
            ],
            "phones": [
                {
                    "type": "Business",
                    "number": "+1 425 555 0109"
                }
            ],
            "postalAddresses": [],
            "websites": [],
            "personType": {
                "class": "Person",
                "subclass": "OrganizationUser"
            }
        },
        {
            "id": "62633BAA-1CB9-4FA2-9B8F-55AB1840B69D",
            "displayName": "Alyce Cooley",
            "givenName": "Alyce",
            "surname": "Cooley",
            "birthday": "",
            "personNotes": "",
            "isFavorite": false,
            "jobTitle": "Marketing Assistant",
            "companyName": null,
            "yomiCompany": "",
            "department": "Sales & Marketing",
            "officeLocation": "131/1104",
            "profession": "",
            "userPrincipalName": "Alycec@contoso.onmicrosoft.com",
            "imAddress": "sip:Alycec@contoso.onmicrosoft.com",
            "scoredEmailAddresses": [
                {
                    "address": "Alycec@contoso.onmicrosoft.com",
                    "relevanceScore": 8
                }
            ],
            "phones": [
                {
                    "type": "Business",
                    "number": "+1 858 555 0110"
                }
            ],
            "postalAddresses": [],
            "websites": [],
            "personType": {
                "class": "Person",
                "subclass": "OrganizationUser"
            }
        },
        {
            "id": "6BB54D2C-EF20-48DA-ADD9-AE757DD30C4E",
            "displayName": "Alyssa Clarke",
            "givenName": "Alyssa",
            "surname": "Clarke",
            "birthday": "",
            "personNotes": "",
            "isFavorite": false,
            "jobTitle": "Corporate Security Officer",
            "companyName": null,
            "yomiCompany": "",
            "department": "Operations",
            "officeLocation": "24/1106",
            "profession": "",
            "userPrincipalName": "Alyssac@contoso.onmicrosoft.com",
            "imAddress": "sip:Alyssac@contoso.onmicrosoft.com",
            "scoredEmailAddresses": [
                {
                    "address": "Alyssac@contoso.onmicrosoft.com",
                    "relevanceScore": 8
                }
            ],
            "phones": [
                {
                    "type": "Business",
                    "number": "+1 262 555 0106"
                }
            ],
            "postalAddresses": [],
            "websites": [],
            "personType": {
                "class": "Person",
                "subclass": "OrganizationUser"
            }
        }
    ]
}

24.1.3 Change the number of people and fields returned

You can change the number of people returned in the response by setting the $top parameter.

The following example requests the 1,000 people most relevant to /me. The request also limits the amount of data sent back from the server by requesting only the displayName of the person.

GET https://graph.microsoft.com/v1.0/me/people/?$top=1000&$Select=displayName

The following example shows the response.

HTTP/1.1 200 OK
Content-type: application/json

{
    "value": [
        {
            "id": "8CE6E1DE-CB84-4BF5-971D-D3ECF452E2B5",
            "displayName": "Lorrie Frye"
        },
        {
            "id": "5767393D-42BA-4E5C-BEE4-52BB25639CF4",
            "displayName": "Maynard Denman"
        },
        {
            "id": "914B5191-11FA-4C0B-A354-0FA8C8EFD585",
            "displayName": "Darrel Halsey"
        },
        {
            "id": "E3C5B235-DE15-4566-B7B1-7A8E32426540",
            "displayName": "Roscoe Seidel"
        },
        {
            "id": "6BB54D2C-EF20-48DA-ADD9-AE757DD30C4E",
            "displayName": "Alyssa Clarke"
        },
        {
            "id": "818E29A1-E6BB-4EDA-AB20-8230B4B1E290",
            "displayName": "Adriana Ramos"
        },
        {
            "id": "62633BAA-1CB9-4FA2-9B8F-55AB1840B69D",
            "displayName": "Alyce Cooley"
        },
        {
            "id": "6BB9CC1F-418D-4DDF-AB0C-6A1C4ABCDBF4",
            "displayName": "Wayne Leeper"
        },
        {
            "id": "E7D40AC5-0078-4575-B1F3-F738124C4BC9",
            "displayName": "Jan Travis"
        },
        {
            "id": "6F99D1CC-4FCC-49E4-9160-E8AB01BF3E83",
            "displayName": "Charlotte Delacruz"
        },
        {
            "id": "1F28616D-BDFE-4080-8F06-03366A851688",
            "displayName": "Felix Coppola"
        },
        {
            "id": "8A3FC021-6DBB-44AC-8884-B7B500CC260A",
            "displayName": "Lenora Rowland"
        },
        {
            "id": "032C9919-4DF9-4715-8C46-4D0FAE7B3EB2",
            "displayName": "Manuel Collette"
        },
      ... etc
}

24.1.4 Select the fields to return

You can limit the amount of data returned from the server by using the $select parameter to choose one or more fields. The @odata.id field is always returned.

The following example limits the response to the displayName and scoredEmailAddresses of the 10 most relevant people.

GET https://graph.microsoft.com/v1.0/me/people/?$select=displayName,scoredEmailAddresses

The following example shows the response. By default, each response returns 10 records. You can change this using the $top parameter. This example uses $top to limit the response to three records.

HTTP/1.1 200 OK
Content-type: application/json

{
    "value": [
        {
            "id": "8CE6E1DE-CB84-4BF5-971D-D3ECF452E2B5",
            "displayName": "Lorrie Frye",
            "scoredEmailAddresses": [
                {
                    "address": "Lorrief@contoso.onmicrosoft.com",
                    "relevanceScore": 8
                }
            ]
        },
        {
            "id": "5767393D-42BA-4E5C-BEE4-52BB25639CF4",
            "displayName": "Maynard Denman",
            "scoredEmailAddresses": [
                {
                    "address": "Maynardd@contoso.onmicrosoft.com",
                    "relevanceScore": 8
                }
            ]
        },
        {
            "id": "914B5191-11FA-4C0B-A354-0FA8C8EFD585",
            "displayName": "Darrel Halsey",
            "scoredEmailAddresses": [
                {
                    "address": "Darrelh@contoso.onmicrosoft.com",
                    "relevanceScore": 8
                }
            ]
        }
    ]
}

24.1.5 Use a filter to limit the response

You can use the $filter parameter to limit the response to only those people whose record contains the specified criteria.

The following query limits the response to person instances with the personType property being assigned person as class and organizationUser as subclass.

GET https://graph.microsoft.com/v1.0/me/people/?$filter=personType/class eq 'Person' and personType/subclass eq 'OrganizationUser'

The following example shows the response. By default, each response returns 10 records. You can change this using the $top parameter. This example uses $top to limit the response to three records.

HTTP/1.1 200 OK
Content-type: application/json

{
    "value": [
        {
            "id": "8CE6E1DE-CB84-4BF5-971D-D3ECF452E2B5",
            "displayName": "Lorrie Frye",
            "givenName": "Lorrie",
            "surname": "Frye",
            "birthday": "",
            "personNotes": "",
            "isFavorite": false,
            "jobTitle": "Paralegal",
            "companyName": null,
            "yomiCompany": "",
            "department": "Legal",
            "officeLocation": "20/1109",
            "profession": "",
            "userPrincipalName": "Lorrief@contoso.onmicrosoft.com",
            "imAddress": "sip:Lorrief@contoso.onmicrosoft.com",
            "scoredEmailAddresses": [
                {
                    "address": "Lorrief@contoso.onmicrosoft.com",
                    "relevanceScore": 8
                }
            ],
            "phones": [
                {
                    "type": "Business",
                    "number": "+1 980 555 0101"
                }
            ],
            "postalAddresses": [],
            "websites": [],
            "personType": {
                "class": "Person",
                "subclass": "OrganizationUser"
            }
        },
        {
            "id": "5767393D-42BA-4E5C-BEE4-52BB25639CF4",
            "displayName": "Maynard Denman",
            "givenName": "Maynard",
            "surname": "Denman",
            "birthday": "",
            "personNotes": "",
            "isFavorite": false,
            "jobTitle": "Web Marketing Manager",
            "companyName": null,
            "yomiCompany": "",
            "department": "Sales & Marketing",
            "officeLocation": "20/1101",
            "profession": "",
            "userPrincipalName": "Maynardd@contoso.onmicrosoft.com",
            "imAddress": "sip:Maynardd@contoso.onmicrosoft.com",
            "scoredEmailAddresses": [
                {
                    "address": "Maynardd@contoso.onmicrosoft.com",
                    "relevanceScore": 8
                }
            ],
            "phones": [
                {
                    "type": "Business",
                    "number": "+1 918 555 0101"
                }
            ],
            "postalAddresses": [],
            "websites": [],
            "personType": {
                "class": "Person",
                "subclass": "OrganizationUser"
            }
        },
        {
            "id": "914B5191-11FA-4C0B-A354-0FA8C8EFD585",
            "displayName": "Darrel Halsey",
            "givenName": "Darrel",
            "surname": "Halsey",
            "birthday": "",
            "personNotes": "",
            "isFavorite": false,
            "jobTitle": "Attorney",
            "companyName": null,
            "yomiCompany": "",
            "department": "Legal",
            "officeLocation": "14/1102",
            "profession": "",
            "userPrincipalName": "Darrelh@contoso.onmicrosoft.com",
            "imAddress": "sip:Darrelh@contoso.onmicrosoft.com",
            "scoredEmailAddresses": [
                {
                    "address": "Darrelh@contoso.onmicrosoft.com",
                    "relevanceScore": 8
                }
            ],
            "phones": [
                {
                    "type": "Business",
                    "number": "+1 205 555 0103"
                }
            ],
            "postalAddresses": [],
            "websites": [],
            "personType": {
                "class": "Person",
                "subclass": "OrganizationUser"
            }
        }
    ]
}

24.1.6 Select the fields to return in a filtered response

You can combine the $select and $filter parameters to create a custom list of people relevant to the user and get only the fields that your application needs.

The following example gets the displayName and scoredEmailAddresses of people whose display name equals the specified name. In this example, only people whose display name equals “Lorrie Frye” are returned.

GET https://graph.microsoft.com/v1.0/me/people/?$select=displayName,scoredEmailAddresses&$filter=displayName eq 'Lorrie Frye'

The following example shows the response.

HTTP/1.1 200 OK
Content-type: application/json

{
    "value": [
        {
            "id": "8CE6E1DE-CB84-4BF5-971D-D3ECF452E2B5",
            "displayName": "Lorrie Frye",
            "scoredEmailAddresses": [
                {
                    "address": "Lorrief@contoso.onmicrosoft.com",
                    "relevanceScore": 8
                }
            ]
        }
    ]
}

24.2 Search people

The requests in this section allow you to search for people relevant to the signed-in user (/me) and other users in the signed-in user’s organization. These requests require the People.Read permission, with the exception of searching other users’ relevant people, which requires People.Read.All. By default, each response returns 10 records, but you can change this by using the $top parameter.

24.2.1 Use search to select people

Use the $search parameter to select people who meet a particular set of criteria.

The following search query returns people relevant to /me whose displayName has a word that begins with the letter “j”.

GET https://graph.microsoft.com/v1.0/me/people/?$search=j

The following example shows the response. By default, each response returns 10 records. You can change this using the $top parameter. This example uses $top to limit the response to three records.

HTTP/1.1 200 OK
Content-type: application/json

{
    "value": [
        {
            "id": "E3C5B235-DE15-4566-B7B1-7A8E32426540",
            "displayName": "Jan Travis",
            "givenName": "Jan",
            "surname": "Travis",
            "birthday": "",
            "personNotes": "",
            "isFavorite": false,
            "jobTitle": "VP Sales",
            "companyName": null,
            "yomiCompany": "",
            "department": "Sales & Marketing",
            "officeLocation": "19/3123",
            "profession": "",
            "userPrincipalName": "jant@contoso.onmicrosoft.com",
            "imAddress": "sip:jant@contoso.onmicrosoft.com",
            "scoredEmailAddresses": [
                {
                    "address": "jant@contoso.onmicrosoft.com",
                    "relevanceScore": -12.297347783416837
                }
            ],
            "phones": [
                {
                    "type": "Business",
                    "number": "+1 732 555 0102"
                }
            ],
            "postalAddresses": [],
            "websites": [],
            "personType": {
                "class": "Person",
                "subclass": "OrganizationUser"
            }
        },
        {
            "id": "C43BF05E-5B6B-4DCF-B2FC-0837B09E0FA9",
            "displayName": "Jacob Cazares (TAILSPIN)",
            "givenName": null,
            "surname": null,
            "birthday": "",
            "personNotes": "",
            "isFavorite": false,
            "jobTitle": null,
            "companyName": null,
            "yomiCompany": "",
            "department": null,
            "officeLocation": null,
            "profession": "",
            "userPrincipalName": "",
            "imAddress": null,
            "scoredEmailAddresses": [
                {
                    "address": "jacobc@tailspintoys.com",
                    "relevanceScore": -12.298154282019846
                }
            ],
            "phones": [],
            "postalAddresses": [],
            "websites": [],
            "personType": {
                "class": "Person",
                "subclass": "PersonalContact"
            }
        },
        {
            "id": "6BB9CC1F-418D-4DDF-AB0C-6A1C4ABCDBF4",
            "displayName": "Jewell Montgomery",
            "givenName": "Jewell",
            "surname": "Montgomery",
            "birthday": "",
            "personNotes": "",
            "isFavorite": false,
            "jobTitle": null,
            "companyName": null,
            "yomiCompany": "",
            "department": null,
            "officeLocation": null,
            "profession": "",
            "userPrincipalName": "jewellm@contoso.onmicrosoft.com",
            "imAddress": null,
            "scoredEmailAddresses": [
                {
                    "address": "jewellm@contoso.onmicrosoft.com",
                    "relevanceScore": -12.531408487977451
                }
            ],
            "phones": [],
            "postalAddresses": [],
            "websites": [],
            "personType": {
                "class": "Person",
                "subclass": "OrganizationUser"
            }
        }
    ]
}

The following request does a search for a person named “Irene McGowen”. Because a person named “Irene McGowan” is relevant to the signed-in user, the information for “Irene McGowan” is returned.

GET https://graph.microsoft.com/v1.0/me/people/?$search="Irene McGowen"

The following example shows the response.

HTTP/1.1 200 OK
Content-type: application/json

{
    "value": [
       {
           "id": "C0BD1BA1-A84E-4796-9C65-F8A0293741D1",
           "displayName": "Irene McGowan",
           "givenName": "Irene",
           "surname": "McGowan",
           "birthday": "",
           "personNotes": "",
           "isFavorite": false,
           "jobTitle": "Auditor",
           "companyName": null,
           "yomiCompany": "",
           "department": "Finance",
           "officeLocation": "12/1110",
           "profession": "",
           "userPrincipalName": "irenem@contoso.onmicrosoft.com",
           "imAddress": "sip:irenem@contoso.onmicrosoft.com",
           "scoredEmailAddresses": [
               {
                   "address": "irenem@contoso.onmicrosoft.com",
                   "relevanceScore": -16.446060612802224
               }
           ],
           "phones": [
               {
                   "type": "Business",
                   "number": "+1 412 555 0109"
               }
           ],
           "postalAddresses": [],
           "websites": [],
           "personType": {
               "class": "Person",
               "subclass": "OrganizationUser"
           }
       }
   ]
}

24.2.3 Search other user’s relevant people

The following request gets the people most relevant to another person in the signed-in user’s organization. This request requires the People.Read.All permission. In this example, Roscoe Seidel’s relevant people are displayed.

GET https://graph.microsoft.com/v1.0/users('roscoes@contoso.com')/people/

The following example shows the response. By default, each response returns 10 records. You can change this using the $top parameter. The example below uses $top to limit the response to three records.

HTTP/1.1 200 OK
Content-type: application/json

{
     "value": [
        {
            "id": "56155636-703F-47F2-B657-C83F01F49BBC",
            "displayName": "Clifton Clemente",
            "givenName": "Clifton",
            "surname": "Clemente",
            "birthday": "",
            "personNotes": "",
            "isFavorite": false,
            "jobTitle": "Director",
            "companyName": null,
            "yomiCompany": "",
            "department": "Legal",
            "officeLocation": "19/2106",
            "profession": "",
            "userPrincipalName": "Cliftonc@contoso.onmicrosoft.com",
            "imAddress": "sip:Cliftonc@contoso.onmicrosoft.com",
            "scoredEmailAddresses": [
                {
                    "address": "Cliftonc@contoso.onmicrosoft.com",
                    "relevanceScore": 20
                }
            ],
            "phones": [
                {
                    "type": "Business",
                    "number": "+1 309 555 0101"
                }
            ],
            "postalAddresses": [],
            "websites": [],
            "personType": {
                "class": "Person",
                "subclass": "OrganizationUser"
            }
        },
        {
            "id": "6BF27D5A-AB4F-4C43-BED0-7DAD9EB0C1C4",
            "displayName": "Sheree Mitchell",
            "givenName": "Sheree",
            "surname": "Mitchell",
            "birthday": "",
            "personNotes": "",
            "isFavorite": false,
            "jobTitle": "Product Manager",
            "companyName": null,
            "yomiCompany": "",
            "department": "Sales & Marketing",
            "officeLocation": "20/2107",
            "profession": "",
            "userPrincipalName": "Shereem@contoso.onmicrosoft.com",
            "imAddress": "sip:shereem@contoso.onmicrosoft.com",
            "scoredEmailAddresses": [
                {
                    "address": "Shereem@contoso.onmicrosoft.com",
                    "relevanceScore": 10
                }
            ],
            "phones": [
                {
                    "type": "Business",
                    "number": "+1 918 555 0107"
                }
            ],
            "postalAddresses": [],
            "websites": [],
            "personType": {
                "class": "Person",
                "subclass": "OrganizationUser"
            }
        },
        {
            "id": "B3E5302D-EAF0-4E8B-8C6C-A2AE64B4B163",
            "displayName": "Vincent Matney",
            "givenName": "Vincent",
            "surname": "Matney",
            "birthday": "",
            "personNotes": "",
            "isFavorite": false,
            "jobTitle": "CVP Engineering",
            "companyName": null,
            "yomiCompany": "",
            "department": "Engineering",
            "officeLocation": "23/2102",
            "profession": "",
            "userPrincipalName": "Vincentm@contoso.onmicrosoft.com",
            "imAddress": "sip:vincentm@contoso.onmicrosoft.com",
            "scoredEmailAddresses": [
                {
                    "address": "Vincentm@contoso.onmicrosoft.com",
                    "relevanceScore": 10
                }
            ],
            "phones": [
                {
                    "type": "Business",
                    "number": "+1 502 555 0102"
                }
            ],
            "postalAddresses": [],
            "websites": [],
            "personType": {
                "class": "Person",
                "subclass": "OrganizationUser"
            }
        }
    ]
}

25 Microsoft Graph permissions reference

Microsoft Graph exposes granular permissions that control the access that apps have to resources, like users, groups, and mail. As a developer, you decide which permissions for Microsoft Graph your app requests. When a user signs in to your app they, or, in some cases, an administrator, are given a chance to consent to these permissions. If the user consents, your app is given access to the resources and APIs that it has requested. For apps that don’t take a signed-in user, permissions can be pre-consented to by an administrator when the app is installed or during sign-up.

25.1 Delegated permissions, Application permissions, and effective permissions

Microsoft Graph has two types of permissions: delegated permissions and application permissions.

  • Delegated permissions are used by apps that have a signed-in user present. For these apps either the user or an administrator consents to the permissions that the app requests and the app is delegated permission to act as the signed-in user when making calls to Microsoft Graph. Some delegated permissions can be consented to by non-administrative users, but some higher-privileged permissions require administrator consent.

  • Application permissions are used by apps that run without a signed-in user present; for example, apps that run as background services or daemons. Application permissions can only be consented by an administrator.

Effective permissions are the permissions that your app will have when making requests to Microsoft Graph. It is important to understand the difference between the delegated and application permissions that your app is granted and its effective permissions when making calls to Microsoft Graph.

  • For delegated permissions, the effective permissions of your app will be the least privileged intersection of the delegated permissions the app has been granted (via consent) and the privileges of the currently signed-in user. Your app can never have more privileges than the signed-in user. Within organizations, the privileges of the signed-in user may be determined by policy or by membership in one or more administrator roles. For more information about administrator roles, see Assigning administrator roles in Azure Active Directory.<br/><br/>For example, assume your app has been granted the User.ReadWrite.All delegated permission. This permission nominally grants your app permission to read and update the profile of every user in an organization. If the signed-in user is a global administrator, your app will be able to update the profile of every user in the organization. However, if the signed-in user is not in an administrator role, your app will be able to update only the profile of the signed-in user. It will not be able to update the profiles of other users in the organization because the user that it has permission to act on behalf of does not have those privileges.

  • For application permissions, the effective permissions of your app will be the full level of privileges implied by the permission. For example, an app that has the User.ReadWrite.All application permission can update the profile of every user in the organization.

25.1.1 Microsoft Graph permission names

Microsoft Graph permission names follow a simple pattern: resource.operation.constraint. For example, User.Read grants permission to read the profile of the signed-in user, User.ReadWrite grants permission to read and modify the profile of the signed-in user, and Mail.Send grants permission to send mail on behalf of the signed-in user.

The constraint element of the name determines the potential extent of access your app will have within the directory. Currently Microsoft Graph supports the following constraints:

  • All grants permission for the app to perform the operations on all of the resources of the specified type in a directory. For example, User.Read.All potentially grants the app privileges to read the profiles of all of the users in a directory.
  • Shared grants permission for the app to perform the operations on resources that other users have shared with the signed-in user. This constraint is mainly used with Outlook resources like mail, calendars, and contacts. For example, Mail.Read.Shared, grants privileges to read mail in the mailbox of the signed-in user as well as mail in mailboxes that other users in the organization have shared with the signed-in user.
  • AppFolder grants permission for the app to read and write files in a dedicated folder in OneDrive. This constraint is only exposed on Files permissions and is only valid for Microsoft accounts.
  • If no constraint is specified the app is limited to performing the operations on the resources owned by the signed-in user. For example, User.Read grants privileges to read the profile of the signed-in user only, and Mail.Read grants permission to read only mail in the mailbox of the signed-in user.

Note: In delegated scenarios, the effective permissions granted to your app may be constrained by the privileges of the signed-in user in the organization.

25.1.2 Microsoft accounts and work or school accounts

Not all permissions are valid for both Microsoft accounts and work or school accounts. You can check Remarks for each permission group to determine whether a specific permission is valid for Microsoft accounts, work or school accounts, or both.

25.1.3 User and group search limitations for guest users in organizations

User and group search capabilities allow the app to search for any user or group in an organization’s directory by performing queries against the /users or /groups resource set (for example, https://graph.microsoft.com/v1.0/users). Both administrators and users have this capability; however, guest users do not. If the signed-in user is a guest user, depending on the permissions an app has been granted, it can read the profile of a specific user or group (for example, https://graph.microsoft.com/v1.0/users/241f22af-f634-44c0-9a15-c8cd2cea5531); however, it cannot perform queries against the /users or /groups resource set that potentially return more than a single resource. With the appropriate permissions, the app can read the profiles of users or groups that it obtains by following links in navigation properties; for example, /users/{id}/directReports or /groups/{id}/members.


25.2 Calendars permissions

25.2.0.1 Delegated permissions

Permission Display String Description Admin Consent Required
Calendars.Read Read user calendars  Allows the app to read events in user calendars. No
Calendars.Read.Shared Read user and shared calendars  Allows the app to read events in all calendars that the user can access, including delegate and shared calendars.  No
Calendars.ReadWrite Have full access to user calendars  Allows the app to create, read, update, and delete events in user calendars. No
Calendars.ReadWrite.Shared Read and write user and shared calendars  Allows the app to create, read, update and delete events in all calendars the user has permissions to access. This includes delegate and shared calendars. No

25.2.0.2 Application permissions

Permission Display String Description Admin Consent Required
Calendars.Read Read calendars in all mailboxes  Allows the app to read events of all calendars without a signed-in user. Yes
Calendars.ReadWrite Read and write calendars in all mailboxes  Allows the app to create, read, update, and delete events of all calendars without a signed-in user. Yes

25.2.1 Remarks

Calendars.Read.Shared and Calendars.ReadWrite.Shared are only valid for work or school accounts. All other permissions are valid for both Microsoft accounts and work or school accounts.

25.2.2 Example usage

25.2.2.1 Delegated

  • Calendars.Read : Get events on the user’s calendar between April 23, 2017 and April 29, 2017 (GET /me/calendarView?startDateTime=2017-04-23T00:00:00&endDateTime=2017-04-29T00:00:00).
  • Calendars.Read.Shared: Find meeting times where all attendees are available (POST /users/{id|userPrincipalName}/findMeetingTimes).
  • Calendars.ReadWrite : Add an event to the user’s calendar (POST /me/events).

25.2.2.2 Application

  • Calendars.Read : Find events in a conference room’s calendar organized by (GET /users/{id | userPrincipalName}/events?$filter=organizer/emailAddress/address eq 'bob@contoso.com').
  • Calendars.Read: List all events on a user’s calendar for the month of May (GET /users/{id | userPrincipalName}/calendarView?startDateTime=2017-05-01T00:00:00&endDateTime=2017-06-01T00:00:00)
  • Calendars.ReadWrite : Add an event to a user’s calendar for approved time off (POST /users/{id | userPrincipalName}/events).
  • Calendars.Send: Send a message (POST /users/{id | userPrincipalName}/sendCalendars).

For more complex scenarios involving multiple permissions, see Permission scenarios.


25.3 Contacts permissions

25.3.0.1 Delegated permissions

Permission Display String Description Admin Consent Required
Contacts.Read Read user contacts  Allows the app to read user contacts. No
Contacts.Read.Shared Read user and shared contacts Allows the app to read contacts that the user has permissions to access, including the user’s own and shared contacts.  No
Contacts.ReadWrite Have full access to user contacts  Allows the app to create, read, update, and delete user contacts. No
Contacts.ReadWrite.Shared Read and write user and shared contacts Allows the app to create, read, update and delete contacts that the user has permissions to, including the user’s own and shared contacts. No

25.3.0.2 Application permissions

Permission Display String Description Admin Consent Required
Contacts.Read Read contacts in all mailboxes  Allows the app to read all contacts in all mailboxes without a signed-in user.  Yes
Contacts.ReadWrite Read and write contacts in all mailboxes  Allows the app to create, read, update, and delete all contacts in all mailboxes without a signed-in user. Yes

25.3.1 Remarks

Only the Contacts.Read and Contacts.ReadWrite delegated permissions are valid for Microsoft accounts.

25.3.2 Example usage

25.3.2.1 Delegated

  • Contacts.Read : Read a contact from one of the top-level contact folders of the signed-in user (GET /me/contactfolders/{Id}/contacts/{id}).
  • Contacts.ReadWrite : Update the contact photo of one of the signed-in user’s contacts (PUT /me/contactfolders/{contactFolderId}/contacts/{id}/photo/$value).
  • Contacts.ReadWrite : Add contacts to the root folder of the signed-in user (POST /me/contacts).

25.3.2.2 Application

  • Contacts.Read : Read contacts from one of the top-level contact folders of any user in the organization (GET /users/{id | userPrincipalName}/contactfolders/{Id}/contacts/{id}).
  • Contacts.ReadWrite : Update the photo for any contact of any user in an organization (PUT /user/{id | userPrincipalName}/contactfolders/{contactFolderId}/contacts/{id}/photo/$value).
  • Contacts.ReadWrite : Add contacts to the root folder of any user in the organization (POST /users/{id | userPrincipalName}/contacts).

For more complex scenarios involving multiple permissions, see Permission scenarios.


25.4 Device permissions

25.4.0.1 Delegated permissions

Permission Display String Description Admin Consent Required
Device.Read Read user devices Allows the app to read a user’s list of devices on behalf of the signed-in user. No
Device.Command Communicate with user devices Allows the app to launch another app or communicate with another app on a user’s device on behalf of the signed-in user. No

25.4.0.2 Application permissions

Permission Display String Description Admin Consent Required
Device.ReadWrite.All Read and write devices Allows the app to read and write all device properties without a signed in user. Does not allow device creation, device deletion or update of device alternative security identifiers. Yes

25.4.1 Remarks

The Device.Read and Device.Command delegated permissions are valid only for personal Microsoft accounts.

25.4.2 Example usage

25.4.2.1 Application

  • Device.ReadWrite.All : Read all registered devices in the organization (GET /devices).

For more complex scenarios involving multiple permissions, see Permission scenarios.


25.5 Microsoft Intune Device Management permissions

25.5.0.1 Delegated permissions

None.

25.5.0.2 Application permissions

Permission Display String Description Admin Consent Required
DeviceManagementServiceConfig.Read.All Read Microsoft Intune configuration (preview) Allows the app to read Microsoft Intune service properties including device enrollment and third party service connection configuration. Yes
DeviceManagementServiceConfig.ReadWrite.All Read and write Microsoft Intune configuration (preview) Allows the app to read and write Microsoft Intune service properties including device enrollment and third party service connection configuration. Yes
DeviceManagementConfiguration.Read.All Read Microsoft Intune device configuration and policies (preview) Allows the app to read properties of Microsoft Intune-managed device configuration and device compliance policies and their assignment to groups. Yes
DeviceManagementConfiguration.ReadWrite.All Read and write Microsoft Intune device configuration and policies (preview) Allows the app to read and write properties of Microsoft Intune-managed device configuration and device compliance policies and their assignment to groups. Yes
DeviceManagementApps.Read.All Read Microsoft Intune apps (preview) Allows the app to read the properties, group assignments and status of apps, app configurations and app protection policies managed by Microsoft Intune. Yes
DeviceManagementApps.ReadWrite.All Read and write Microsoft Intune apps (preview) Allows the app to read and write the properties, group assignments and status of apps, app configurations and app protection policies managed by Microsoft Intune. Yes
DeviceManagementRBAC.Read.All Read Microsoft Intune RBAC settings (preview) Allows the app to read the properties relating to the Microsoft Intune Role-Based Access Control (RBAC) settings. Yes
DeviceManagementRBAC.ReadWrite.All Read and write Microsoft Intune RBAC settings (preview) Allows the app to read and write the properties relating to the Microsoft Intune Role-Based Access Control (RBAC) settings. Yes
DeviceManagementManagedDevices.Read.All Read Microsoft Intune devices (preview) Allows the app to read the properties of devices managed by Microsoft Intune. Yes
DeviceManagementManagedDevices.ReadWrite.All Read and write Microsoft Intune devices (preview) Allows the app to read and write the properties of devices managed by Microsoft Intune. Does not allow high impact operations such as remote wipe and password reset on the device’s owner. Yes
DeviceManagementManagedDevices.PrivilegedOperations.All Perform user-impacting remote actions on Microsoft Intune devices (preview) Allows the app to perform remote high impact actions such as wiping the device or resetting the passcode on devices managed by Microsoft Intune. Yes

25.5.1 Remarks

Note: Using the Microsoft Graph APIs to configure Intune controls and policies still requires that the Intune service is correctly licensed by the customer.

These permissions are only valid for work or school accounts.

25.5.2 Example usage

25.5.2.1 Application

  • DeviceManagementServiceConfiguration.Read.All : Check the current state of the Intune subscription (GET /deviceManagement/subscriptionState)
  • DeviceManagementServiceConfiguration.ReadWrite.All : Create new Terms and Conditions (POST /deviceManagement/termsAndConditions)
  • DeviceManagementConfiguration.Read.All : Find the status of a device configuration (GET /deviceManagement/deviceConfigurations/{id}/deviceStatuses)
  • DeviceManagementConfiguration.ReadWrite.All : Assign a device compliance policy to a group (POST deviceCompliancePolicies/{id}/assign)
  • DeviceManagementApps.Read.All : Find all the Windows Store apps published to Intune (GET /deviceAppManagement/mobileApps?$filter=isOf('microsoft.graph.windowsStoreApp'))
  • DeviceManagementApps.ReadWrite.All : Publish a new application (POST /deviceAppManagement/mobileApps)
  • DeviceManagementRBAC.Read.All : Find a role assignment by name (GET /deviceManagement/roleAssignments?$filter=displayName eq 'My Role Assignment')
  • DeviceManagementRBAC.ReadWrite.All : Create a new custom role (POST /deviceManagement/roleDefinitions)
  • DeviceManagementManagedDevices.Read.All : Find a managed device by name (GET /managedDevices/?$filter=deviceName eq 'My Device')
  • DeviceManagementManagedDevices.ReadWrite.All : Remove a managed device (DELETE /managedDevices/{id})
  • DeviceManagementManagedDevices.PrivilegedOperations.All : Reset the passcode on a user’s managed device (POST /managedDevices/{id}/resetPasscode).

For more complex scenarios involving multiple permissions, see Permission scenarios.


25.6 Directory permissions

25.6.0.1 Delegated permissions

Permission Display String Description Admin Consent Required
Directory.Read.All Read directory data Allows the app to read data in your organization’s directory, such as users, groups and apps. Yes
Directory.ReadWrite.All Read and write directory data Allows the app to read and write data in your organization’s directory, such as users, and groups. It does not allow the app to delete users or groups, or reset user passwords. Yes
Directory.AccessAsUser.All Access directory as the signed-in user Allows the app to have the same access to information in the directory as the signed-in user. Yes

25.6.0.2 Application permissions

Permission Display String Description Admin Consent Required
Directory.Read.All Read directory data Allows the app to read data in your organization’s directory, such as users, groups and apps, without a signed-in user. Yes
Directory.ReadWrite.All Read and write directory data Allows the app to read and write data in your organization’s directory, such as users, and groups, without a signed-in user. Does not allow user or group deletion. Yes

25.6.1 Remarks

Directory permissions are not supported on Microsoft accounts.

Directory permissions provide the highest level of privilege for accessing directory resources such as User, Group, and Device in an organization. They also exclusively control access to other directory resources like: organizational contacts, schema extension APIs, Privileged Identity Management (PIM) APIs, as well as many of the resources and APIs listed under the Azure Active Directory node in the v1.0 and beta API reference documentation. These include administrative units, directory roles, directory settings, policy, and many more.

The Directory.ReadWrite.All permission grants the following privileges:

  • Full read of all directory resources (both declared properties and navigation properties)
  • Create and update users
  • Disable and enable users (but not company administrator)
  • Set user alternative security id (but not administrators)
  • Create and update groups
  • Manage group memberships
  • Update group owner
  • Manage license assignments
  • Define schema extensions on applications
  • Note: No rights to reset user passwords
  • Note: No rights to delete resources (including users or groups)
  • Note: Specifically excludes create or update for resources not listed above. This includes: application, oAauth2Permissiongrant, appRoleAssignment, device, servicePrincipal, organization, domains, and so on.

25.6.2 Example usage

25.6.2.1 Delegated

  • Directory.Read.All : List all administrative units in an organization (GET /beta/administrativeUnits)
  • Directory.ReadWrite.All : Add members to a directory role (POST /directoryRoles/{id}/members/$ref)

25.6.2.2 Application

  • Directory.Read.All : List all memberships of a user, including directory roles and administrative units (GET /beta/users/{id}/memberOf)
  • Directory.Read.All : List all group members, including service principals (GET /beta/groups/{id}/members)
  • Directory.ReadWrite.All : Add an owner to a group (POST /groups/{id}/owners/$ref)

For more complex scenarios involving multiple permissions, see Permission scenarios.


25.7 Files permissions

25.7.0.1 Delegated permissions

Permission Display String Description Admin Consent Required
Files.Read Read user files Allows the app to read the signed-in user’s files. No
Files.Read.All Read all files that user can access Allows the app to read all files the signed-in user can access. No
Files.ReadWrite Have full access to user files Allows the app to read, create, update, and delete the signed-in user’s files. No
Files.ReadWrite.All Have full access to all files user can access Allows the app to read, create, update, and delete all files the signed-in user can access. No
Files.ReadWrite.AppFolder Have full access to the application’s folder (preview) (Preview) Allows the app to read, create, update, and delete files in the application’s folder. No
Files.Read.Selected Read files that the user selects (preview) Limited support in Microsoft Graph - see Remarks <br/> (Preview) Allows the app to read files that the user selects. The app has access for several hours after the user selects a file. No
Files.ReadWrite.Selected Read and write files that the user selects (preview) Limited support in Microsoft Graph – see Remarks <br/> (Preview) Allows the app to read and write files that the user selects. The app has access for several hours after the user selects a file. No

25.7.0.2 Application permissions

Permission Display String Description Admin Consent Required
Files.Read.All Read files in all site collections (preview) (Preview) Allows the app to read all files in all site collections without a signed in user. Yes
Files.ReadWrite.All Read and write files in all site collections (preview) Limited support in Microsoft Graph <br/> (Preview) Allows the app to read, create, update, and delete all files in all site collections without a signed in user. Yes

25.7.1 Remarks

The Files.Read, Files.ReadWrite, Files.Read.All, and Files.ReadWrite.All delegated permissions are valid on both personal Microsoft accounts and work or school accounts. Note that for personal accounts, Files.Read and Files.ReadWrite also grant access to files shared with the signed-in user.

The Files.Read.Selected and Files.ReadWrite.Selected delegated permissions are only valid on work or school accounts and are only exposed for working with Office 365 file handlers (v1.0). They should not be used for directly calling Microsoft Graph APIs.

The Files.ReadWrite.AppFolder delegated permission is only valid for personal accounts and is used for accessing the App Root special folder with the OneDrive Get special folder Microsoft Graph API.

The Files.ReadWrite.All application permission does not yet support the OneDrive Create resumable upload session Microsoft Graph API. Full support is coming soon.

25.7.2 Example usage

25.7.2.1 Delegated

  • Files.Read : Read files stored in the signed-in user’s OneDrive (GET /me/drive/root/children)
  • Files.Read.All : Read files shared with the signed-in user (GET /me/drive/root/sharedWithMe)
  • Files.ReadWrite : Write a file in the signed-in user’s OneDrive (PUT /me/drive/root/children/filename.txt/content)
  • Files.ReadWrite.All : Write a file shared with the user (PUT /users/rgregg@contoso.com/drive/root/children/file.txt/content)
  • Files.ReadWrite.AppFolder : Write files into the app’s folder in OneDrive (PUT /me/drive/special/approot/children/file.txt/content)

For more complex scenarios involving multiple permissions, see Permission scenarios.


25.8 Group permissions

25.8.0.1 Delegated permissions

Permission Display String Description Admin Consent Required
Group.Read.All Read all groups Allows the app to list groups, and to read their properties and all group memberships on behalf of the signed-in user. Also allows the app to read calendar, conversations, files, and other group content for all groups the signed-in user can access. Yes
Group.ReadWrite.All Read and write all groups Allows the app to create groups and read all group properties and memberships on behalf of the signed-in user. Additionally allows group owners to manage their groups and allows group members to update group content. Yes

25.8.0.2 Application permissions

Permission Display String Description Admin Consent Required
Group.Read.All Read all groups Allows the app to read memberships for all groups without a signed-in user. Note that not all group API supports access using app-only permissions. See known issues for examples. Yes
Group.ReadWrite.All Read and write all groups Allows the app to create groups, read and update group memberships, and delete groups. All of these operations can be performed by the app without a signed-in user. Note that not all group API supports access using app-only permissions. See known issues for examples. Yes

25.8.1 Remarks

Group functionality is not supported on Microsoft accounts.

For Office 365 groups, Group permissions grant the app access to the contents of the group; for example, conversations, files, notes, and so on. Group permissions are also used to control access to Microsoft Planner resources and APIs.

For application permissions, there are some limitations for the APIs that are supported. For more information, see known issues.

In some cases, an app may need Directory permissions to read some group properties like member and memberOf. For example, if a group has a one or more servicePrincipals as members, the app will need effective permissions to read service principals through being granted one of the Directory.* permissions, otherwise Microsoft Graph will return an error. (In the case of delegated permissions, the signed-in user will also need sufficient privileges in the organization to read service principals.) The same guidance applies for the memberOf property, which can return administrativeUnits.

25.8.2 Example usage

25.8.2.1 Delegated

  • Group.Read.All : Read all Office 365 groups that the signed-in user is a member of (GET /me/memberOf/$/microsoft.graph.group?$filter=groupTypes/any(a:a%20eq%20'unified')).
  • Group.Read.All : Read all Office 365 group content like conversations (GET /groups/{id}/conversations).
  • Group.ReadWrite.All : Update group properties, like photo (PUT /groups/{id}/photo/$value).
  • Group.ReadWrite.All : Update group members (POST /groups/{id}/members/$ref). NOTE: This also requires User.ReadBasic.All to read the user to add as a member.

25.8.2.2 Application

  • Group.Read.All : Find all groups with name that starts with ‘Sales’ (GET /groups?$filter=startswith(displayName,'Sales')).
  • Group.ReadWrite.All : Daemon service creates new events on an Office 365 group’s calendar (POST /groups/{id}/events).

For more complex scenarios involving multiple permissions, see Permission scenarios.


25.9 Identity Risk Event permissions

25.9.0.1 Delegated permissions

Permission Display String Description Admin Consent Required
IdentityRiskEvent.Read.All Read identity risk event information Allows the app to read identity risk event information for all users in your organization on behalf of the signed-in user. Yes

25.9.0.2 Application permissions

Permission Display String Description Admin Consent Required
IdentityRiskEvent.Read.All Read identity risk event information Allows the app to read identity risk event information for all users in your organization without a signed-in user. Yes

25.9.1 Remarks

IdentityRiskEvent.Read.All is valid only for work or school accounts. For an app with delegated permissions to read identity risk information, the signed-in user must be a member of one of the following administrator roles: Global Administrator, Security Administrator, or Security Reader. For more information about administrator roles, see Assigning administrator roles in Azure Active Directory.

25.9.2 Example usage

25.9.2.1 Delegated and Application

The following usages are valid for both delegated and application permissions:

  • Read all risk events generated for all users in the tenant (GET /beta/identityRiskEvents)
  • Read malware risk events generated by the Dorknet botnet (GET /beta/malwareRiskEvents?$filter=malwareName eq 'Dorkbot')
  • Read most recent 50 risk events (GET /beta/identityRiskEvents?$orderBy=riskEventDateTime desc&top=50)

For more complex scenarios involving multiple permissions, see Permission scenarios.


25.10 Mail permissions

25.10.0.1 Delegated permissions

Permission Display String Description Admin Consent Required
Mail.Read Read user mail  Allows the app to read email in user mailboxes.  No
Mail.ReadWrite Read and write access to user mail  Allows the app to create, read, update, and delete email in user mailboxes. Does not include permission to send mail. No
Mail.Read.Shared Read user and shared mail Allows the app to read mail that the user can access, including the user’s own and shared mail.  No
Mail.ReadWrite.Shared Read and write user and shared mail  Allows the app to create, read, update, and delete mail that the user has permission to access, including the user’s own and shared mail. Does not include permission to send mail. No
Mail.Send Send mail as a user  Allows the app to send mail as users in the organization.  No
Mail.Send.Shared Send mail on behalf of others  Allows the app to send mail as the signed-in user, including sending on-behalf of others.  No
MailboxSettings.Read Read user mailbox settings  Allows the app to the read user’s mailbox settings. Does not include permission to send mail. No
MailboxSettings.ReadWrite Read and write user mailbox settings  Allows the app to create, read, update, and delete user’s mailbox settings. Does not include permission to send mail. No

25.10.0.2 Application permissions

Permission Display String Description Admin Consent Required
Mail.Read Read mail in all mailboxes Allows the app to read mail in all mailboxes without a signed-in user. Yes
Mail.ReadWrite Read and write mail in all mailboxes Allows the app to create, read, update, and delete mail in all mailboxes without a signed-in user. Does not include permission to send mail. Yes
Mail.Send Send mail as any user Allows the app to send mail as any user without a signed-in user. Yes
MailboxSettings.Read Read all user mailbox settings  Allows the app to read user’s mailbox settings without a signed-in user. Does not include permission to send mail. No
MailboxSettings.ReadWrite Read and write all user mailbox settings Allows the app to create, read, update, and delete user’s mailbox settings without a signed-in user. Does not include permission to send mail. Yes

25.10.1 Remarks

Mail.Read.Shared, Mail.ReadWrite.Shared, and Mail.Send.Shared are only valid for work or school accounts. All other permissions are valid for both Microsoft accounts and work or school accounts.

With the Mail.Send or Mail.Send.Shared permission, an app can send mail and save a copy to the user’s Sent Items folder, even if the app does not use a corresponding Mail.ReadWrite or Mail.ReadWrite.Shared permission.

25.10.2 Example usage

25.10.2.1 Delegated

  • Mail.Read : List messages in the user’s inbox, sorted by receivedDateTime (GET /me/mailfolders/inbox/messages?$orderby=receivedDateTime DESC).
  • Mail.Read.Shared: Find all messages with attachments in a user’s inbox that has shared their inbox with the signed-in user (GET /users{id | userPrincipalName}/mailfolders/inbox/messages?$filter=hasAttachments eq true).
  • Mail.ReadWrite : Mark a message read (PATCH /me/messages/{id}).
  • Mail.Send : Send a message (POST /me/sendmail).
  • MailboxSettings.ReadWrite : Update the user’s automatic reply (PATCH /me/mailboxSettings).

25.10.2.2 Application

  • Mail.Read : Find messages from (GET /users/{id | userPrincipalName}/messages?$filter=from/emailAddress/address eq 'bob@contoso.com').
  • Mail.ReadWrite : Create a new folder in the Inbox named Expense Reports (POST /users/{id | userPrincipalName}/mailfolders).
  • Mail.Send: Send a message (POST /users/{id | userPrincipalName}/sendmail).
  • MailboxSettings.Read: Get the default timezone for the user’s mailbox (GET /users/{id | userPrincipalName}/mailboxSettings/timeZone)

For more complex scenarios involving multiple permissions, see Permission scenarios.


25.11 Member permissions

25.11.0.1 Delegated permissions

None.

25.11.0.2 Application permissions

Permission Display String Description Admin Consent Required
Member.Read.Hidden Read all hidden memberships Allows the app to read the memberships of hidden groups and administrative units without a signed-in user. Yes

25.11.1 Remarks

Membership in some Office 365 groups can be hidden. This means that only the members of the group can view its members. This feature can be used to help comply with regulations that require an organization to hide group membership from outsiders (for example, an Office 365 group that represents students enrolled in a class).

25.11.2 Example usage

25.11.2.1 Application

  • Member.Read.Hidden : Read the members of an administrative unit with hidden membership (GET /administrativeUnits/{id}/members).
  • Member.Read.Hidden : Read the members of a group with hidden membership (GET /groups/{id}/members).

For more complex scenarios involving multiple permissions, see Permission scenarios.


25.12 Notes permissions

25.12.0.1 Delegated permissions

Permission Display String Description Admin Consent Required
Notes.Read Read user OneNote notebooks Allows the app to read the titles of OneNote notebooks and sections and to create new pages, notebooks, and sections on behalf of the signed-in user. No
Notes.Create Create user OneNote notebooks Allows the app to read the titles of OneNote notebooks and sections and to create new pages, notebooks, and sections on behalf of the signed-in user. No
Notes.ReadWrite Read and write user OneNote notebooks Allows the app to read, share, and modify OneNote notebooks on behalf of the signed-in user. No
Notes.Read.All Read all OneNote notebooks that user can access Allows the app to read OneNote notebooks that the signed-in user has access to in the organization. No
Notes.ReadWrite.All Read and write all OneNote notebooks that user can access Allows the app to read, share, and modify OneNote notebooks that the signed-in user has access to in the organization. No
Notes.ReadWrite.CreatedByApp Limited notebook access (deprecated) Deprecated <br/>Do not use. No privileges are granted by this permission. No

25.12.0.2 Application permissions

Permission Display String Description Admin Consent Required
Notes.Read.All Read all OneNote notebooks Allows the app to read all the OneNote notebooks in your organization, without a signed-in user. Yes
Notes.ReadWrite.All Read and write all OneNote notebooks Allows the app to read, share, and modify all the OneNote notebooks in your organization, without a signed-in user. Yes

25.12.1 Remarks

Notes.Read.All and Notes.ReadWrite.All are only valid for work or school accounts. All other permissions are valid for both Microsoft accounts and work or school accounts.

With the Notes.Create permission, an app can view the OneNote notebook hierarchy of the signed-in user and create OneNote content (notebooks, section groups, sections, pages, etc.).

Notes.ReadWrite and Notes.ReadWrite.All also allow the app to modify the permissions on the OneNote content that can be accessed by the signed-in user.

For work or school accounts, Notes.Read.All and Notes.ReadWrite.All allow the app to access other users’ OneNote content that the signed-in user has permission to within the organization.

25.12.2 Example usage

25.12.2.1 Delegated

  • Notes.Create : Create a new notebooks for the signed-in user (POST /me/onenote/notebooks).
  • Notes.Read : Read the notebooks for the signed-in user (GET /me/onenote/notebooks).
  • Notes.Read.All : Get all notebooks that the signed-in user has access to within the organization (GET /me/onenote/notebooks?includesharednotebooks=true).
  • Notes.ReadWrite : Update the page of the signed-in user (PATCH /me/onenote/pages/{id}/$value).
  • Notes.ReadWrite.All : Create a page in another user’s notebook that the signed-in user has access to within the organization (POST /users/{id}/onenote/pages).

25.12.2.2 Application

  • Notes.Read.All : Read all users notebooks in a group (GET /groups/{id}/onenote/notebooks).
  • Notes.ReadWrite.All : Update the page in a notebook for any user in the organization (PATCH /users/{id}/onenote/pages/{id}/$value).

For more complex scenarios involving multiple permissions, see Permission scenarios.


25.13 OpenID permissions

25.13.0.1 Delegated permissions

Permission Display String Description Admin Consent Required
email View users’ email address Allows the app to read your users’ primary email address. No
offline_access Access user’s data anytime Allows the app to read and update user data, even when they are not currently using the app. No
openid Sign users in Allows users to sign in to the app with their work or school accounts and allows the app to see basic user profile information. No
profile View users’ basic profile Allows the app to see your users’ basic profile (name, picture, user name). No

25.13.0.2 Application permissions

None.

25.13.1 Remarks

You can use these permissions to specify artifacts that you want returned in Azure AD authorization and token requests. They are supported differently by the Azure AD v1.0 and v2.0 endpoints.

With the Azure AD (v1.0) endpoint, only the openid permission is used. You specify it in the scope parameter in an authorization request to return an ID token when you use the OpenID Connect protocol to sign in a user to your app. For more information, see Authorize access to web applications using OpenID Connect and Azure Active Directory. To successfully return an ID token, you must also make sure that the User.Read permission is configured when you register your app.

With the Azure AD v2.0 endpoint, you specify the offline_access permission in the scope parameter to explicitly request a refresh token when using the OAuth 2.0 or OpenID Connect protocols. With OpenID Connect, you specify the openid permission to request an ID token. You can also specify the email permission, profile permission, or both to return additional claims in the ID token. You do not need to specify User.Read to return an ID token with the v2.0 endpoint. For more information, see OpenID Connect scopes.

Important The Microsoft Authentication Library (MSAL) currently specifies offline_access, openid, profile, and email by default in authorization and token requests. This means that, for the default case, if you specify these permissions explicitly, Azure AD may return an error.


25.14 People permissions

25.14.0.1 Delegated permissions

Permission Display String Description Admin Consent Required
People.Read Read users’ relevant people lists Allows the app to read a scored list of people relevant to the signed-in user. The list can include local contacts, contacts from social networking or your organization’s directory, and people from recent communications (such as email and Skype). No
People.Read.All Read all users’ relevant people lists Allows the app to read a scored list of people relevant to the signed-in user or other users in the signed-in user’s organization. The list can include local contacts, contacts from social networking or your organization’s directory, and people from recent communications (such as email and Skype). Also allows the app to search the entire directory of the signed-in user’s organization.  Yes

25.14.0.2 Application permissions

Permission Display String Description Admin Consent Required
People.Read.All Read all users’ relevant people lists Allows the app to read a scored list of people relevant to the signed-in user or other users in the signed-in user’s organization. The list can include local contacts, contacts from social networking or your organization’s directory, and people from recent communications (such as email and Skype). Also allows the app to search the entire directory of the signed-in user’s organization.  Yes

25.14.1 Remarks

The People.Read.All permission is only valid for work and school accounts.

25.14.2 Example usage

25.14.2.1 Delegated

  • People.Read : Read a list of relevant people (GET /me/people)
  • People.Read.All : Read a list of relevant people to another user in the same organization (GET /users('{id})/people)

For more complex scenarios involving multiple permissions, see Permission scenarios.


25.15 Reports permissions

25.15.0.1 Delegated permissions

None.

25.15.0.2 Application permissions

Permission Display String Description Admin Consent Required
Reports.Read.All Read all usage reports Allows an app to read all service usage reports without a signed-in user. Services that provide usage reports include Office 365 and Azure Active Directory. Yes

25.15.1 Remarks

Reports permissions are only valid for work or school accounts.

25.15.2 Example usage

25.15.2.1 Application

  • Reports.Read.All : Read usage detail report of email apps with period of 7 days (GET /reports/EmailAppUsage(view='Detail',period='D7')/content)
  • Reports.Read.All : Read activity detail report of email with date of ‘2017-01-01’ (GET /reports/EmailActivity(view='Detail',data='2017-01-01')/content)
  • Reports.Read.All : Read Office 365 activations detail report (GET /reports/Office365Activations(view='Detail')/content)

For more complex scenarios involving multiple permissions, see Permission scenarios.


25.16 Sites permissions

25.16.0.1 Delegated permissions

Permission Display String Description Admin Consent Required
Sites.Read.All Read items in all site collections Allows the application to read documents and list items in all site collections on behalf of the signed-in user. No
Sites.ReadWrite.All Read and write items in all site collections Allows the application to edit or delete documents and list items in all site collections on behalf of the signed-in user. No

25.16.0.2 Application permissions

None.

25.16.1 Remarks

Sites permissions are valid only on work or school accounts.

25.16.2 Example usage

25.16.2.1 Delegated

  • Sites.Read.All : Read the lists on the SharePoint root site (GET /beta/sharePoint/site/lists)
  • Sites.ReadWrite.All : Create new list items in a SharePoint list (POST /beta/sharePoint/site/lists/123/items)

For more complex scenarios involving multiple permissions, see Permission scenarios.


25.17 Tasks permissions

25.17.0.1 Delegated permissions

Permission Display String Description Admin Consent Required
Tasks.Read Read user tasks Allows the app to read user tasks. No
Tasks.Read.Shared Read user and shared tasks Allows the app to read tasks a user has permissions to access, including their own and shared tasks. No
Tasks.ReadWrite Create, read, update and delete user tasks and containers Allows the app to create, read, update and delete tasks and containers (and tasks in them) that are assigned to or shared with the signed-in user. No
Tasks.ReadWrite.Shared Read and write user and shared tasks Allows the app to create, read, update, and delete tasks a user has permissions to, including their own and shared tasks. No

25.17.0.2 Application permissions

None.

25.17.1 Remarks

Tasks permissions are used to control access for Outlook tasks. Access for Microsoft Planner tasks is controlled by Group permissions.

Shared permissions are currently only supported for work or school accounts. Even with Shared permissions, reads and writes may fail if the user who owns the shared content has not granted the accessing user permissions to modify content within the folder.

25.17.2 Example usage

25.17.2.1 Delegated

  • Tasks.Read : Get all tasks in a user’s mailbox (GET /me/outlook/tasks).
  • Tasks.Read.Shared : Access tasks in a folder shared to you by another user in your organization (Get /users{id|userPrincipalName}/outlook/taskfolders/{id}/tasks).
  • Tasks.ReadWrite : Add an event to the user’s default task folder (POST /me/outook/tasks).
  • Tasks.Read : Get all uncompleted tasks in a user’s mailbox (GET /users/{id | userPrincipalName}/outlook/tasks?$filter=status ne 'completed').
  • Tasks.ReadWrite : Update a task in a user’s mailbox (PATCH /users/{id | userPrincipalName}/outlook/tasks/id).
  • Tasks.ReadWrite.Shared : Complete a task on behalf of another user (POST /users/{id | userPrincipalName}/outlook/tasks/id/complete).

For more complex scenarios involving multiple permissions, see Permission scenarios.


25.18 User permissions

25.18.0.1 Delegated permissions

Permission Display String Description Admin Consent Required
User.Read Sign-in and read user profile Allows users to sign-in to the app, and allows the app to read the profile of signed-in users. It also allows the app to read basic company information of signed-in users. No
User.ReadWrite Read and write access to user profile Allows the app to read your profile. It also allows the app to update your profile information on your behalf. No
User.ReadBasic.All Read all users’ basic profiles Allows the app to read a basic set of profile properties of other users in your organization on behalf of the signed-in user. This includes display name, first and last name, email address and photo. No
User.Read.All Read all users’ full profiles Allows the app to read the full set of profile properties, reports, and managers of other users in your organization, on behalf of the signed-in user. Yes
User.ReadWrite.All Read and write all users’ full profiles Allows the app to read and write the full set of profile properties, reports, and managers of other users in your organization, on behalf of the signed-in user. Also allows the app to create and delete users as well as reset user passwords on behalf of the signed-in user. Yes
User.Invite.All Invite guest users to the organization Allows the app to invite guest users to your organization, on behalf of the signed-in user. Yes

25.18.0.2 Application permissions

Permission Display String Description Admin Consent Required
User.Read.All Read all users’ full profiles Allows the app to read the full set of profile properties, group membership, reports and managers of other users in your organization, without a signed-in user. Yes
User.ReadWrite.All Read and write all users’ full profiles Allows the app to read and write the full set of profile properties, group membership, reports and managers of other users in your organization, without a signed-in user. Also allows the app to create and delete non-administrative users. Does not allow reset of user passwords. Yes
User.Invite.All Invite guest users to the organization Allows the app to invite guest users to your organization, without a signed-in user. Yes

25.18.1 Remarks

The only permissions valid for Microsoft accounts are User.Read and User.ReadWrite. For work or school accounts, all permissions are valid.

With the User.Read permission, an app can also read the basic company information of the signed-in user for a work or school account through the organization resource. The following properties are available: id, displayName, and verifiedDomains.

For work or school accounts, the full profile includes all of the declared properties of the User resource. On reads, only a limited number of properties are returned by default. To read properties that are not in the default set, use $select. The default properties are:

  • displayName
  • givenName
  • jobTitle
  • mail
  • mobilePhone
  • officeLocation
  • preferredLanguage
  • surname
  • userPrincipalName

User.ReadWrite and User.Readwrite.All delegated permissions allow the app to update the following profile properties for work or school accounts:

  • aboutMe
  • birthday
  • hireDate
  • interests
  • mobilePhone
  • mySite
  • pastProjects
  • photo
  • preferredName
  • responsibilities
  • schools
  • skills

With the User.ReadWrite.All application permission, the app can update all of the declared properties of work or school accounts except for password.

To read or write direct reports (directReports) or the manager (manager) of a work or school account, the app must have either User.Read.All (read only) or User.ReadWrite.All.

The User.ReadBasic.All permission constrains app access to a limited set of properties known as the basic profile. This is because the full profile might contain sensitive directory information. The basic profile includes only the following properties:

  • displayName
  • givenName
  • mail
  • photo
  • surname
  • userPrincipalName

To read the group memberships of a user (memberOf), the app must have either Group.Read.All or Group.ReadWrite.All. However, if the user also has membership in a directoryRole or an administrativeUnit, the app will need effective permissions to read those resources too, or Microsoft Graph will return an error. This means the app will also need Directory permissions, and, for delegated permissions, the signed-in user will also need sufficient privileges in the organization to access directory roles and administrative units.

25.18.2 Example usage

25.18.2.1 Delegated

  • User.Read : Read the full profile for the signed-in user (GET /me).
  • User.ReadWrite : Update the photo of the signed-in user (PUT /me/photo/$value).
  • User.ReadBasic.All : Find all users whose name starts with “David” (GET /users?$filter=startswith(displayName,'David')).
  • User.Read.All : Read a user’s manager (GET /user/{id | userPrincipalName}/manager).

25.18.2.2 Application

  • User.Read.All : Read all users and relationships through delta query (GET /beta/users/delta?$select=displayName,givenName,surname).
  • User.ReadWrite.All : Update the photo for any user in the organization (PUT /user/{id | userPrincipalName}/photo/$value).

For more complex scenarios involving multiple permissions, see Permission scenarios.


25.19 Permission scenarios

This section shows some common scenarios that target user and group resources in an organization. The tables show the permissions that an app needs to be able to perform specific operations required by the scenario. Note that in some cases the ability of the app to perform specific operations will depend on whether a permission is an application or delegated permission. In the case of delegated permissions, the app’s effective permissions will also depend on the privileges of the signed-in user within the organization. For more information, see Delegated permissions, Application permissions, and effective permissions.

25.19.1 Access scenarios on the User resource

| App tasks involving User | Required permissions | Permission strings |
|:——————————-|:———————|:—————|
| App wants to read other users’ basic information (only display name and picture), for example to show in a people picking experience | User.ReadBasic.All | Read all user’s basic profiles |
| App wants to read complete user profile for signed in user (see direct reports, and manager, etc.) | User.Read | Enable sign-in and read user profile|
| App wants to read complete user profile all users | User.Read.All | Read all user’s full profiles |
| App wants to read files, mail and calendar information for the signed in user | User.Read, Files.Read, Mail.Read, Calendars.Read | Enable sign-in and read user profile, Read users’ files, Read user mail, Read user calendars |
| App wants to read the signed-in user’s (my) files and files that other users have shared with the signed-in user (me). | User.Read, Files.Read, Sites.Read.All | Enable sign-in and read user profile, Read users’ files, Read items in all site collections |
| App wants to read and write complete user profile for signed in user | User.ReadWrite | Read and write access to user profile |
| App wants to read and write complete user profile all users | User.ReadWrite.All | Read and write all user’s full profiles |
| App wants to read and write files, mail and calendar information for the signed in user | User.ReadWrite, Files.ReadWrite, Mail.ReadWrite, Calendars.ReadWrite | Read and write access to user profile, Read and write access to user profile, Read and write access to user mail, Have full access to user calendars |

25.19.2 Access scenarios on the Group resource

App tasks involving Group Required permissions Permission strings
App wants to read basic group info (only display name and picture), for example to show in a group picking experience Group.Read.All Read all groups
App wants to read all content in all Office 365 groups, including files, conversations. It also needs to show group memberships, be able to update group memberships, (if owner). Group.Read.All Read items in all site collections, Read all groups
App wants to read and write all content in all Office 365 groups, including files, conversations. It also needs to show group memberships, be able to update group memberships, (if owner). Group.ReadWrite.All, Sites.ReadWrite.All Read and write all groups, Edit or delete items in all site collections
App wants to discover (find) an Office 365 group. It allows the user to search for a particular group and choose one from the enumerated list to allow the user to join the group. Group.ReadWrite.All Read and write all groups
App wants to create a group through AAD Graph Group.ReadWrite.All Read and write all groups

26 Get started with Microsoft Graph in a PHP app

This article describes the tasks required to get an access token from the Azure AD v2.0 endpoint and call Microsoft Graph. It walks you through building the Connect Sample for PHP (REST) and explains the main concepts that you implement to use Microsoft Graph. The article also describes how to access Microsoft Graph by using REST calls.

To use Microsoft Graph in your PHP app, you need to show the Microsoft sign in page to your users. The following screenshot shows a sign in page for Microsoft accounts.

Sign in page for Microsoft accounts

Don’t feel like building an app? Get up and running fast by downloading the Connect Sample for PHP (REST) that this article is based on. Or try out the Connect Sample for PHP (SDK) version that uses the Microsoft Graph Library for PHP (Preview).

26.1 Prerequisites

To get started, you’ll need:

26.2 Register the application

Register an app on the Microsoft App Registration Portal. This generates the app ID and password that you’ll use to configure the app.

  1. Sign into the Microsoft App Registration Portal using either your personal or work or school account.

  2. Choose Add an app.

  3. Enter a name for the app, and choose Create application.

    The registration page displays, listing the properties of your app.

  4. Choose Generate New Password.

  5. Copy the application ID and password.

  6. Choose Add Platform and Web.

  7. In the Redirect URI field, type http://localhost:8000/oauth.

  8. Choose Save.

26.3 Configure the project

Start a new project using composer. To create a new PHP project using the Laravel framework, use the following command:

composer create-project --prefer-dist laravel/laravel getstarted

This creates a getstarted folder that you can use for this project.

Note: You can also use the Starter project that takes care of the project configuration so you can focus on the coding sections of this walkthrough.

26.4 Authenticate the user and get an access token

Use an OAuth library to simplify the authentication process. The PHP League provides an OAuth client library that you can use in this project.

26.4.1 Add the dependency to composer

Open the composer.json file and include the following dependency in the require section:

"league/oauth2-client": "^1.4"

Update the dependencies by running the following command:

composer update

26.4.2 Start the authentication flow

  1. Open the resources > views > welcome.blade.php file. Replace the title div element with the following code.

    <div class="title" onClick="window.location='/oauth'">Sign in to Microsoft</div>
  2. Type-hint the Illuminate\Http\Request class on the app > Http > routes.php file. Add the following line before any route declaration.

    use Illuminate\Http\Request;
  3. Add an /oauth route to the app > Http > routes.php file. To add the route, copy the following code after the default route declaration. Insert the application ID and password of your app in the placeholder marked with \<YOUR_APPLICATION_ID> and \<YOUR_PASSWORD> respectively.

    Route::get('/oauth', function () {
        $provider = new \League\OAuth2\Client\Provider\GenericProvider([
            'clientId'                => '<YOUR_APPLICATION_ID>',
            'clientSecret'            => '<YOUR_PASSWORD>',
            'redirectUri'             => 'http://localhost:8000/oauth',
            'urlAuthorize'            => 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize',
            'urlAccessToken'          => 'https://login.microsoftonline.com/common/oauth2/v2.0/token',
            'urlResourceOwnerDetails' => '',
            'scopes'                  => 'openid mail.send'
        ]);
    
        if (!$request->has('code')) {
            return redirect($provider->getAuthorizationUrl());
        }
    });

At this point, you should have a PHP app that displays Sign in to Microsoft. If you click the text, the app presents the Microsoft sign-in page. The next step is to handle the code that the authorization server sends to the redirect URI and exchange it for an access token.

26.4.3 Exchange the authorization code for an access token

You need to handle the authorization server response, which contains a code that you can exchange for an access token.

Update the /oauth route so it can get an access token with the authorization code. To do this, open the app > Http > routes.php file and add the following else conditional clause to the existing if statement.

if (!$request->has('code')) {
    ...
    // add the following lines
} else {
    $accessToken = $provider->getAccessToken('authorization_code', [
        'code'     => $request->input('code')
    ]);
    exit($accessToken->getToken());
}

Note that you have an access token in this line: exit($accessToken->getToken());. Now you’re ready to add code to call Microsoft Graph.

26.5 Call Microsoft Graph using REST

You can call Microsoft Graph using REST. Replace the line exit($accessToken->getToken()); with the following code. Insert your email address in the placeholder marked with \<YOUR_EMAIL_ADDRESS>.

$client = new \GuzzleHttp\Client();

$email = "{
    Message: {
    Subject: 'Sent using the Microsoft Graph REST API',
    Body: {
        ContentType: 'text',
        Content: 'This is the email body'
    },
    ToRecipients: [
        {
            EmailAddress: {
            Address: '<YOUR_EMAIL_ADDRESS>'
            }
        }
    ]
    }}";

$response = $client->request('POST', 'https://graph.microsoft.com/v1.0/me/sendmail', [
    'headers' => [
        'Authorization' => 'Bearer ' . $accessToken->getToken(),
        'Content-Type' => 'application/json;odata.metadata=minimal;odata.streaming=true'
    ],
    'body' => $email
]);
if($response.getStatusCode() === 201) {
    exit('Email sent, check your inbox');
} else {
    exit('There was an error sending the email. Status code: ' . $response.getStatusCode());
}

26.6 Run the app

You’re ready to try your PHP app.

  1. In your shell, type the following command:

    php artisan serve
  2. Go to http://localhost:8000 in your web browser.
  3. Choose Sign in to Microsoft.
  4. Sign in with your personal or work or school account and grant the requested permissions.

Check the inbox of the email address that you configured in Call the Microsoft Graph using REST section. You should have an email from the account that you used to sign in to the app.

26.7 Next steps

26.8 See also

27 Use Microsoft Graph to access Excel in a Python app

You can use the Microsoft Graph API to read and update workbooks stored in supported online storage platforms including, OneDrive and SharePoint. The Workbook (or Excel file) resource contains all the other Excel resources and your app can access them via simple navigations.

You can access a set of Excel objects (such as Table, Range, or Chart) by using standard REST APIs to perform create, read, update, and delete (CRUD) operations on the workbook. For example,
https://graph.microsoft.com/{version}/me/drive/items/{id}/workbook/
returns a collection of worksheet objects that are part of the workbook.

This walkthrough describes how to make requests to the Excel REST API from a Python web app.

27.1 Prerequisites

27.2 Authorization and scopes

You can use the Azure AD v2.0 endpoint to authenticate Excel REST API calls. All APIs require the Authorization: Bearer {access-token} HTTP header.

One of the following permission scopes is required to use the Excel resource:

  • Files.Read
  • Files.ReadWrite

27.3 Sessions and persistence

Excel APIs can be called in one of two modes:

  1. Persistent session - All changes made to the workbook are persisted (saved). This is the usual mode of operation.
  2. Non-persistent session - Changes made by the API are not saved to the source location. Instead, the Excel backend server keeps a temporary copy of the file that reflects the changes made during that particular API session. When the Excel session expires, the changes are lost. This mode is useful for apps that need to do analysis or obtain the results of a calculation or a chart image, but not affect the document state.

To represent the session in the API, use the workbook-session-id: {session-id} header.

27.4 Register the application in Azure Active Directory

First, you need to register your application and set permissions to use Microsoft Graph. This lets users sign in to the application with work or school accounts.

27.4.1 Register the application

Register an app on the Microsoft App Registration Portal. This generates the app ID and password that you’ll use to configure the app for authentication.

  1. Sign in to the Microsoft App Registration Portal using either your personal or work or school account.

  2. Choose Add an app.

  3. Enter a name for the app, and choose Create application.

    The registration page displays, listing the properties of your app.

  4. Copy the application ID. This is the unique identifier for your app.

  5. Under Application Secrets, choose Generate New Password. Copy the app secret from the New password generated dialog box.

    You’ll use the application ID and app secret to configure the app.

  6. Under Platforms, choose Add platform > Web.

  7. Make sure the Allow Implicit Flow check box is selected, and enter your app’s Redirect URI.

    The Allow Implicit Flow option enables the OpenID Connect hybrid flow. During authentication, this enables the app to receive both sign-in information (the id_token) and artifacts (in this case, an authorization code) that the app uses to obtain an access token.

  8. Choose Save.

27.4.2 Create OAuth client

Your app needs to register an instance of the Flask-OAuth client that you’ll use to start the OAuth flow and get an access token. Note that the Files.ReadWrite scope is required to obtain an Excel session that supports persisted changes.

    # Put your consumer key and consumer secret into a config file
    # and don't check it into github!
    microsoft = oauth.remote_app(
        'microsoft',
        consumer_key = client_id,
        consumer_secret = client_secret,
        request_token_params = {'scope': 'User.Read Files.ReadWrite'},
        base_url = 'https://graph.microsoft.com/v1.0/',
        request_token_url = None,
        access_token_method = 'POST',
        access_token_url = 'https://login.microsoftonline.com/common/oauth2/v2.0/token',
        authorize_url = 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize'
    )

27.4.3 Receive an authorization code in your reply URL page

After the user signs in, the browser is redirected to your reply URL. Upon successful authorization, the access token (which will be used to authorize additional requests) will be returned in the response body.

    @app.route('/login/authorized')
    def authorized():
        response = microsoft.authorized_response()
        if response is None:
            return "Access Denied: Reason=%s\nError=%s" % (
                request.args['error'], 
                request.args['error_description']
            )
    
        # Check response for state
        if str(session['state']) != str(request.args['state']):
            raise Exception('State has been messed with, end authentication')
        # Remove state session variable to prevent reuse.
        session['state'] = ""
            
        # Okay to store this in a local variable, encrypt if it's going to client
        # machine or database. Treat as a password. 
        session['microsoft_token'] = (response['access_token'], '')
        # Store the token in another session variable for easy access
        session['access_token'] = response['access_token']

27.5 Make requests to the Excel API

27.5.1 Request headers

With an access token, your app can make authenticated requests to the Microsoft Graph API. Your app must append the access token to the Authorization header of each request.

    # Set request headers.
    headers = { 
        'User-Agent' : 'python_tutorial/1.0',
        'Authorization' : 'Bearer {0}'.format(access_token),
        'Accept' : 'application/json',
        'Content-Type' : 'application/json'
    }

Note The request must also send a Content-Type header with a value accepted by the Graph API, for example, application/json.

27.5.2 Getting an Excel Session

27.5.2.1 Request

Pass a JSON object by setting the persistChanges value to true or false. When the value of persistChanges is set to false, a non-persistent session id is returned. This example uses the Requests HTTP library

    # Replace the id with your Excel workbook's drive id
    url = 'https://graph.microsoft.com/v1.0/me/drive/items/01TBZDUE23F3CNYSIEGNBZV2LZGWHMC7TE/workbook/createSession'
    # Set request headers
    headers = { 
        'User-Agent' : 'python_tutorial/1.0',
        'Authorization' : 'Bearer {0}'.format(access_token),
        'Accept' : 'application/json',
        'Content-Type' : 'application/json'
    }
    # Specify type of session
    body = {
        'persistChanges': True
    }
    
    response = requests.post(url, headers = headers, json = body)

27.5.2.2 Response

<!– { “blockType”: “ignored” } –>

HTTP code: 201, Created
content-type: application/json;odata.metadata 

{
    "@odata.context": "https://graph.microsoft.com/{version}/$metadata#microsoft.graph.sessionInfo",
    "id": "{session-id}",
    "persistChanges": true
}

27.5.2.3 Usage

The session ID returned from the previous call is passed as a header on subsequent API requests in the
Workbook-Session-Id HTTP header. For instance, to list worksheets in that Excel workbook.

    # Replace the id with your Excel workbook's drive id
    url = 'https://graph.microsoft.com/v1.0/me/drive/items/01TBZDUE23F3CNYSIEGNBZV2LZGWHMC7TE/workbook/worksheets'
    # Set request headers - note the session header 
    headers = { 
        'User-Agent' : 'python_tutorial/1.0',
        'Authorization' : 'Bearer {0}'.format(access_token),
        'Accept' : 'application/json',
        'Workbook-Session-Id': 'cluster=PP1&session=12.a04039942e021.A272...'
    }
    
    response = requests.get(url, headers = headers)

27.5.2.4 Response

<!– { “blockType”: “ignored” } –>

HTTP code: 200, OK
content-type: application/json;odata.metadata 

{
    "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('8473b867-3e4e-4e44-8d09-8c6da362080f')/drive/items('01TBZDUE23F3CNYSIEGNBZV2LZGWHMC7TE')/workbook/worksheets",
    "value": [
    {
        "@odata.id": "/users('8473b867-3e4e-4e44-8d09-8c6da362080f')/drive/items('01TBZDUE23F3CNYSIEGNBZV2LZGWHMC7TE')/workbook/worksheets(%27%7B00000000-0001-0000-0000-000000000000%7D%27)",
        "id": "{00000000-0001-0000-0000-000000000000}",
        "name": "Session 1",
        "position": 0,
        "visibility": "Visible"
    },
    {
        "@odata.id": "/users('8473b867-3e4e-4e44-8d09-8c6da362080f')/drive/items('01TBZDUE23F3CNYSIEGNBZV2LZGWHMC7TE')/workbook/worksheets(%27%7B00000000-0001-0000-0100-000000000000%7D%27)",
        "id": "{00000000-0001-0000-0100-000000000000}",
        "name": "Session 2",
        "position": 1,
        "visibility": "Visible"
    }]
}

27.6 Next steps

With the Workbook-Session-Id HTTP header, you can begin issuing requests to fetch data, create charts, and much more.

The Excel REST API in Microsoft Graph provides a powerful way to access and interact with data in Excel workbooks. Explore what else is possible with Microsoft Graph.

28 Get started with Microsoft Graph in a Python app

This article describes the tasks required to get an access token from Azure AD and call Microsoft Graph. It walks you through the Microsoft Graph Connect Sample for Python and explains the main concepts that you implement to use the Microsoft Graph API. The article describes how to access Microsoft Graph by using direct REST calls.

Office 365 Python Connect sample screenshot

28.1 Prerequisites

28.2 Register the application in Azure Active Directory

First, you need to register your application and set permissions to use Microsoft Graph. This lets users sign into the application with work or school accounts.

28.3 Register the application

Register an app on the Microsoft App Registration Portal. This generates the app ID and password that you’ll use to configure the app for authentication.

  1. Sign into the Microsoft App Registration Portal using either your personal or work or school account.

  2. Choose Add an app.

  3. Enter a name for the app, and choose Create application.

    The registration page displays, listing the properties of your app.

  4. Copy the application ID. This is the unique identifier for your app.

  5. Under Application Secrets, choose Generate New Password. Copy the app secret from the New password generated dialog.

    You’ll use the application ID and app secret to configure the app.

  6. Under Platforms, choose Add platform > Web.

  7. Make sure the Allow Implicit Flow check box is selected, and enter *http://localhost:5000/login/authorized* as the Redirect URI.

    The Allow Implicit Flow option enables the OpenID Connect hybrid flow. During authentication, this enables the app to receive both sign-in info (the id_token) and artifacts (in this case, an authorization code) that the app uses to obtain an access token.

    The redirect URI *http://localhost:5000/login/authorized* is the value that the OmniAuth middleware is configured to use once it has processed the authentication request.

  8. Choose Save.

28.4 Configure and run the app

  1. Using your favorite text editor, open the **_PRIVATE.txt** file.
  2. Replace ENTER_YOUR_CLIENT_ID with the client ID of your registered application.
  3. Replace ENTER_YOUR_SECRET with the key you generated for your app.
  4. Start the development server by running python manage.py runserver.
  5. Navigate to http://localhost:5000/ in your web browser.

<!–<a name=“authCode”></a>–>

28.5 Receive an authorization code in your reply URL page

After the user signs in, the browser is redirected to your reply URL, the login/authorized route in connectsample.py, with an access token in the response. The sample stores the token as a session variable.

@app.route('/login/authorized')
def authorized():
    """Handler for login/authorized route."""
    response = msgraphapi.authorized_response()

    if response is None:
        return "Access Denied: Reason={0}\nError={1}".format( \
            request.args['error'], request.args['error_description'])

    # Check response for state
    if str(session['state']) != str(request.args['state']):
        raise Exception('State has been messed with, end authentication')
    session['state'] = '' # reset session state to prevent re-use

    # Okay to store this in a local variable, encrypt if it's going to client
    # machine or database. Treat as a password.
    session['microsoft_token'] = (response['access_token'], '')
    # Store the token in another session variable for easy access
    session['access_token'] = response['access_token']
    me_response = msgraphapi.get('me')
    me_data = json.loads(json.dumps(me_response.data))
    username = me_data['displayName']
    email_address = me_data['userPrincipalName']
    session['alias'] = username
    session['userEmailAddress'] = email_address
    return redirect('main')

<!–<a name=“request”></a>–>

28.6 Use the access token in a request to the Microsoft Graph API

With an access token, your app can make authenticated requests to the Microsoft Graph API. Your app must append the access token to the Authorization header of each request.

The Connect sample sends an email using the me/microsoft.graph.sendMail endpoint in the Microsoft Graph API. The code is in the call_sendmail_endpoint function in the connectsample.py file. This is the code that shows how to append the access code to the Authorization header.

    # Set request headers.
    headers = { 
      'User-Agent' : 'python_tutorial/1.0',
      'Authorization' : 'Bearer {0}'.format(access_token),
      'Accept' : 'application/json',
      'Content-Type' : 'application/json'
    }

Note The request must also send a Content-Type header with a value accepted by the Graph API, for example, application/json.

The Microsoft Graph API is a very powerful, unifiying API that can be used to interact with all kinds of Microsoft data. Check out the API reference to explore what else you can accomplish with Microsoft Graph.

29 Use query parameters to customize responses

Microsoft Graph provides optional query parameters that you can use to specify and control the amount of data returned in a response. The following following query parameters are supported.

|Name|Description|Example (click examples to try in Graph Explorer)
|:—————|:——–|:——-|
|$filter|Filters results (rows).|/users?$filter=startswith(givenName,'J')
|$select|Filters properties (columns).|/users?$select=givenName,surname
|$expand|Retrieves related resources.|/groups/{id}?$expand=members
|$orderby|Orders results.|/users?$orderby=displayName,userPrincipalName desc
|$top|Limits results. Typically used with $skipToken.|/users?$top=2
|$skipToken|Used with $top to retrieve a page of results.|See nextLink from the $top query for an example.
|$count|Retrieves the total count of matching resources.|/me/messages?$top=2&$count=true
<!– TODO: figure out whether $search is actually used
|$search|A property and value pair separated by a colon.|
–>

These parameters are compatible with the OData V4 query language.

Note: On the beta endpoint, the $ prefix is optional. For example, instead of $filter, you can use filter. For more details and examples, see Supporting query parameters without $ prefixes in Microsoft Graph.

Encoding query parameters:

The values of query parameters should be percent-encoded. Many HTTP clients, browsers and tools (e.g., the Graph Explorer) will help you with this. If a query is failing, one possible reason is failure to encode the values of query parameters appropriately.

An unencoded URL looks like this:

GET https://graph.microsoft.com/v1.0/users?$filter=startswith(givenName, 'J')

A properly encoded URL looks like this:

GET https://graph.microsoft.com/v1.0/users?$filter=startswith(givenName%2C+'J')

29.1 filter

$filter can be used to retrieve just a subset of a collection. For example, to find users whose display name starts with J, use startswith.

Try in Graph Explorer

Request:

GET https://graph.microsoft.com/v1.0/users?$filter=startswith(displayName,'J')

Response:

{
    "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users",
    "value": [
        {
            "id": "e013b9f3-a1ab-48d1-907b-e716c39d6363",
            "businessPhones": [
                "4255550100"
            ],
            "displayName": "Jan Madden",
            "givenName": "Jan",
            "jobTitle": null,
            "mail": "demo32@a830edad9050849NDA1.onmicrosoft.com",
            "mobilePhone": null,
            "officeLocation": null,
            "preferredLanguage": null,
            "surname": "Madden",
            "userPrincipalName": "demo32@a830edad9050849NDA1.onmicrosoft.com"
        },
        {
            "id": "89efe8ed-d141-4151-a3e4-570a70022dff",
            "businessPhones": [
                "+1 425 555 0109"
            ],
            "displayName": "Janet Schorr",
            "givenName": "Janet",
            "jobTitle": "Product Marketing Manager",
            "mail": "janets@a830edad9050849NDA1.onmicrosoft.com",
            "mobilePhone": null,
            "officeLocation": "18/2111",
            "preferredLanguage": null,
            "surname": "Schorr",
            "userPrincipalName": "janets@a830edad9050849NDA1.onmicrosoft.com"
        },
        ...
    ]
}

$filter has a very rich and expressive syntax with many built-in operators. Logical operators include equals (eq), not equals (ne), greater than (gt), greater than or equals (gte), and (and), or (or), not (not) etc. Arithmetic operators include add (add), subtract (sub), etc. String operators include contains (contains), starts with (startswith), etc. Lambda operators include any (any) and all (all). For additional details on $filter syntax, see the OData protocol.

29.2 select

In a collection or an individual entity, to specify a different set of properties to return instead of the default set, use the $select query parameter. The $select parameter allows for choosing a subset or superset of the default set returned.
For example, when retrieving your messages, you might want to select that only the from and subject properties of messages are returned.

GET https://graph.microsoft.com/v1.0/me/messages?$select=from,subject

<!–For example, when retrieving the children of an item on a drive, you want to select that only the name and size properties of items are returned.

GET https://graph.microsoft.com/v1.0/me/drive/root/children?$select=name,size

By submitting the request with the $select=name,size query string, the objects
in the response will only have those property values included.

json { "value": [ { "id": "13140a9sd9aba", "name": "Documents", "size": 1024 }, { "id": "123901909124a", "name": "Pictures", "size": 1012010210 } ] }–>

29.3 expand

In Microsoft Graph API requests, navigations to an object or collection of the referenced item are not automatically expanded.
This is by design because it reduces network traffic and the time it takes to generate a response from the service.
However, in some cases you might want to include those results in a response.

You can use the $expand query string parameter to instruct the API to expand a child object or collection and include those results.

For example, to retrieve the root drive information and the top level child items in a drive, you use the $expand parameter.
This example also uses a $select statement to only return the id and name properties of the children items.

GET https://graph.microsoft.com/v1.0/me/drive/root?$expand=children($select=id,name)

Note: The maximum number of expanded objects for a request is 20. Also, if you query on the user resource, you can use $expand to get the properties of only one child object or collection at a time.
The following example gets user objects, each with up to 20 directReport objects in the directReports collection expanded:

GET https://graph.microsoft.com/v1.0/users?$expand=directReports

Some other resources may have a limit as well, so always check for possible errors.

29.4 orderby

To specify the sort order of the items returned from the Microsof Graph API, use the $orderby query parameter.

For example, to return the users in the organization ordered by their display name, the syntax is as follows:

GET https://graph.microsoft.com/v1.0/users?$orderby=displayName

You can also sort by complex type entities. The following example gets messages and sorts them by the address field of the from property, which is of the complex type emailAddress:

GET https://graph.microsoft.com/v1.0/me/messages?$orderby=from/emailAddress/address

To sort the results in ascending or descending order, append either asc or desc to the field name, separated by a space, for example, ?$orderby=name%20desc.

Note: If you query on the user resource, $orderby can’t be combined with filter expressions.

29.5 top

To specify the maximum number of items to return in a result set, use the $top query parameter.
The $top query parameter identifies a subset in the collection. This subset is formed by selecting only the first N items of the set, where N is a positive integer specified by this query parameter.
For example, to return the first five messages in the user’s mailbox, the syntax is as follows:

GET https://graph.microsoft.com/v1.0/me/messages?$top=5

29.6 skip

(To set the number of items to skip before retrieving items in a collection, use the $skip query parameter.
For example, to return events sorted by date created, and starting with the 21st event, the syntax is as follows.

GET  https://graph.microsoft.com/v1.0/me/events?$orderby=createdDateTime&$skip=20

29.7 skipToken

To request second and subsequent pages of Graph data use the $skipToken query parameter.
]The $skipToken query parameter is provided in Urls returned from the Graph when the Graph has returned a partial subset of results, usually due to server-side paging.
It identifies the point in a collection where the server finished sending results, and is passed back to the Graph to indicate where it should resume sending results from.
For example, the value of a $skipToken query parameter could identify the tenth item in a collection or the 20th item in a collection containing 50 items, or any other position within the collection.

In some responses, you’ll see an @odata.nextLink value.
Some of them include a $skipToken value.
The $skipToken value is like a marker that tells the service where to resume for the next set of results.
The following is an example of a @odata.nextLink value from a response where users have been requested ordered by displayName:

"@odata.nextLink": "https://graph.microsoft.com/v1.0/users?$orderby=displayName&$skiptoken=X%2783630372100000000000000000000%27"

To return the next page of users in your organization, the syntax is as follows.

GET  https://graph.microsoft.com/v1.0/users?$orderby=displayName&$skiptoken=X%2783630372100000000000000000000%27

29.8 count

Use $count as a query parameter to include a count of the total number of items in a collection alongside the page of data values returned from the Graph, as in the following example:

GET  https://graph.microsoft.com/v1.0/me/contacts?$count=true

This would return both the contacts collection, and the number of items in the contacts collection in the @odata.count property.

Note: This is not supported for directoryObject collections.

To restrict the results of a request that match a search criterion, use the $search query parameter.

Note: You can currently only search message and person collections. A $search request returns up to 250 results. You cannot use $filter or $orderby in a search request.

Search criteria are expressed using Advanced Query Syntax (AQS). The results are sorted by the date and time that the message was sent.

You can specify the following properties on a message in a $search criterion:
attachments, bccRecipients, body, category, ccRecipients, content, from, hasAttachments, participants, receivedDateTime, sender, subject, toRecipients

If you do a search on messages and specify only a value, the search is carried out on the default search properties of from, subject and body.

The following example returns all messages in the signed-in user’s Inbox that contains “pizza” in any of the three default search properties:

GET https://graph.microsoft.com/v1.0/me/messages?$search="pizza"

The next example searches all messages in the user’s Inbox that were sent from a specific email address:

GET https://graph.microsoft.com/v1.0/me/messages?$search="from:help@contoso.com"

30 Get started with Microsoft Graph and REST

This article describes the tasks required to get an access token from the Azure AD v2.0 endpoint and call Microsoft Graph using REST calls. It describes the sequence of requests and responses that an app uses to authenticate and retrieve email messages.

First, you need register your app with Azure Active Directory (Azure AD).

30.1 Register the application

There are currently two options to register your app with Azure AD.

  • Register an app to use the Azure AD v2.0 endpoint that works for both personal (Microsoft) identities and work and school (Azure AD) accounts.
  • Register an app to use the Azure AD endpoint that supports work and school accounts only.

This article assumes a v2.0 registration, so you’ll register your app on the Application Registration Portal. Follow the instructions in Register your Microsoft Graph application with the Azure AD v2.0 endpoint to register your app. For information about using the Azure AD endpoint, see Authenticate using Azure AD.

Some limitations apply when using the v2.0 endpoint. To decide if it’s right for you, see Should I use the v2.0 endpoint?

30.2 Authenticate the user and get an access token

The app described in this article implements the Authorization Code Grant flow to get access tokens from the Azure AD v2.0 endpoint, following standard OAuth 2.0 protocols. For a complete guide to the flows supported in the Azure AD v2.0 endpoint see Types of the v2.0 endpoint.

With the Authorization Code Grant flow, first you get an authorization code and then you exchange the code for an access token.

30.2.1 Getting an authorization code

The first step in the Authorization Code Grant flow is to get an authorization code. The code is returned to the app by the authorization server when the user signs in and consents to the permissions requested by the app.

You request an authorization code by sending a GET request to the Azure AD v2.0 endpoint. This URL must be opened in a browser so that the user can sign in and provide consent.

30.2.1.1 Construct the request

1- Start with the base URL:

https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize

The tenant segment in the path controls who can sign into the application. Allowed values are common, organizations, consumers, and tenant identifiers. For more information, see Protocol endpoints.

2- Append query parameters to the base URL. These are used to identify the app, the requested permissions, and other auth request information. The following table describes some common parameters.

Parameter Descriptions
client_id The app ID generated by registering the app. This lets Azure AD know which app is requesting the logon.
redirect_uri The location that Azure will redirect to after the user has granted consent to the app. This value must correspond to the value of Redirect URI used when registering the app.
response_type The type of response the app is expecting. This value is code for the Authorization Code Grant flow.
scope A space-separated list of Microsoft Graph permission scopes that the app is requesting. You can also specify OpenId Connect scopes for single sign-on.
state A value included in the request that will also be returned in the token response, used for validation.

For example, the request URL for an application that requires read access to mail might look like the following.

GET https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=<app ID>&redirect_uri=http%3A%2F%2Flocalhost/myapp%2F&response_type=code&state=1234&scope=mail.read

3- Redirect the user to the logon URL. The user is presented with a sign in screen that displays the name of the app. After signing in, the user is presented with the list of the permissions the app requires and prompted to allow or deny. If the user consents, the browser redirects to the redirect URI with the authorization code and state in the query string, as shown in the following example.

http://localhost/myapp/?code=AwABAAAA...cZZ6IgAA&state=1234

The next step is to exchange the authorization code returned for an access token.

30.2.2 Getting an access token

To get an access token, the app posts form-encoded parameters to the token request URL (for example, https://login.microsoftonline.com/common/oauth2/v2.0/token) with the following parameters.

Parameter Descriptions
client_id The app ID generated by registering the app.
client_secret The app secret generated when registering the app.
code The authorization code obtained in the prior step.
redirect_uri This value must be the same as the value used in the authorization code request.
grant_type The type of grant the app is using. This value is code for the Authorization Code Grant flow.
scope A space-separated list of Microsoft Graph permission scopes that the app is requesting.

The request URL for our application, using the code from the previous step, looks like the following.

POST https://login.microsoftonline.com/common/oauth2/v2.0/token
Content-Type: application/x-www-form-urlencoded

{
  grant_type=authorization_code
  &code=AwABAAAA...cZZ6IgAA
  &redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F
  &resource=https%3A%2F%2Fgraph.microsoft.com%2F
  &scope=mail.read
  &client\_id=<app ID>
  &client\_secret=<app SECRET>
}

The server responds with a JSON payload which includes the access token.

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{
  "token_type":"Bearer",
  "expires_in":"3600",
  "access_token":"eyJ0eXAi...b66LoPVA",
  "scope":"https://graph.microsoft.com/mail.read",
  ...
}

The access token is found in the access_token field of the JSON payload. The app uses this value to set the Authorization header when making REST calls to the API.

30.3 Call Microsoft Graph

After the app has an access token, it’s ready to call Microsoft Graph. Because this sample app is retrieving messages, it will use an HTTP GET request to the https://graph.microsoft.com/v1.0/me/messages endpoint.

30.3.1 Refine the request

Apps can control the behavior of GET requests by using OData query parameters. We recommend that apps use these parameters to limit the number of results that are returned and to limit the fields that are returned for each item.

This sample app will display messages in a table that shows the subject, sender, and the date and time the message was received. The table displays a maximum of 25 rows and is sorted so that the most recently received message is at the top. The app uses the following query parameters to get these results.

  • $select - Specifies only the subject, sender, and dateTimeReceived fields.
  • $top - Specifies a maximum of 25 items.
  • $orderby - Sorts the results by the dateTimeReceived field.

This results in the following request.

GET https://graph.microsoft.com/v1.0/me/messages?$select=subject,from,receivedDateTime&$top=25&$orderby=receivedDateTime%20DESC
Accept: application/json
Authorization: Bearer eyJ0eXAi...b66LoPVA

Now that you’ve seen how to make calls to Microsoft Graph, you can use the API reference to construct any other kinds of calls your app needs to make. However, bear in mind that your app needs to have the appropriate permissions configured on the app registration for the calls it makes.

30.4 Next steps

30.5 See also

# Get started with Microsoft Graph in a Ruby on Rails app

This article describes the tasks required to get an access token from the Azure AD v2.0 endpoint and call Microsoft Graph. It walks you through building the Microsoft Graph Ruby on Rails Connect Sample and explains the main concepts that you implement to use the Microsoft Graph. The article also describes how to access Microsoft Graph by using direct REST calls.

To download a version of the Connect sample that uses the Azure AD endpoint, see Microsoft Graph Ruby on Rails Connect Sample.

The following image shows the app you’ll create.

Microsoft Ruby on Rails Connect sample screenshot

Don’t feel like building an app? Use the Microsoft Graph quick start to get up and running fast, or download the Ruby REST Connect sample that this article is based on.

30.6 Prerequisites

To get started, you’ll need:

30.7 Register the application

Register an app on the Microsoft App Registration Portal. This generates the app ID and secret that you’ll use to configure the app for authentication.

  1. Sign into the Microsoft App Registration Portal using either your personal or work or school account.

  2. Choose Add an app.

  3. Enter a name for the app, and choose Create application.

    The registration page displays, listing the properties of your app.

  4. Copy the application ID. This is the unique identifier for your app.

  5. Under Application Secrets, choose Generate New Password. Copy the app secret from the New password generated dialog.

    You’ll use the application ID and app secret to configure the app.

  6. Under Platforms, choose Add platform > Web.

  7. Make sure the Allow Implicit Flow check box is selected, and enter *http://localhost:3000/auth/microsoft_v2_auth/callback* as the Redirect URI.

    The Allow Implicit Flow option enables the OpenID Connect hybrid flow. During authentication, this enables the app to receive both sign-in info (the id_token) and artifacts (in this case, an authorization code) that the app uses to obtain an access token.

    The redirect URI *http://localhost:3000/auth/microsoft_v2_auth/callback* is the value that the OmniAuth middleware is configured to use once it has processed the authentication request.

  8. Choose Save.

30.8 Configure the project

  1. Download or clone the Microsoft Graph Ruby on Rails Connect Sample. Open the starter folder in the editor of your choice.
  2. If you don’t already have bundler and rack, you can install them with the following command.

    gem install bundler rack
  3. In the config/environment.rb file, do the following:
    • Replace ENTER_YOUR_CLIENT_ID with the client ID of your registered application.
    • Replace ENTER_YOUR_SECRET with the key of your registered application.
  4. Install the Rails application and dependencies with the following command.

    bundle install

30.9 Authenticate the user and get an access token

This app uses the authorization code grant flow with a delegated user identity. For a web application, the flow requires the application ID, secret, and redirect URI from the registered app.

The auth flow can be broken down into these basic steps:

  1. Redirect the user for authentication and consent
  2. Get an authorization code
  3. Redeem the authorization code for an access token

For more information about this auth flow, see Web application to web API and Integrate Microsoft identity and the Microsoft Graph into a web application using OpenID Connect in the Azure AD documentation.

We’ll be using a stack of three pieces of Rack middleware to enable the app to authenticate against the Microsoft Graph:

  • OmniAuth, a generalized Rack framework for multiple-provider authentication.
  • Omniauth-oauth2, an abstract OAuth2 strategy for OmniAuth.
  • omniauth-microsoft_v2_auth, an OmniAuth strategy that customizes Omniauth-oauth2 to specifically provide authentication against the Azure AD v2.0 endpoint. This project is included in the code sample.

30.9.1 Specify gem dependencies for authentication

In Gemfile, uncomment the following gems to add them as dependencies.

```
gem 'omniauth'
gem 'omniauth-oauth2'
gem 'omniauth-microsoft_v2_auth', path: './omniauth-microsoft_v2_auth'
```

Note that omniauth-microsoft_v2_auth is included in the app project, and will be installed from the path specified.

30.9.2 Configure the authentication middleware

In config/initializers/omniauth-microsoft_v2_auth.rb, uncomment the following lines.

```
Rails.application.config.middleware.use OmniAuth::Builder do
  provider :microsoft_v2_auth,
  ENV['CLIENT_ID'],
  ENV['CLIENT_SECRET'],
  :scope => ENV['SCOPE']
end
```

This configures the OmniAuth middleware, including specifying the app ID and app secret to use, as well as the scopes to request for the user. These are the values you specified earlier in config/environment.rb.

30.9.3 Specify routes for authentication

Now we need to specify two routes necessary for the authentication flow. The first route forwards the authentication request to the OmniAuth middleware, and the second specifies the location in the app to which OmniAuth should redirect once authentication has occurred.

In config/routes.rb, uncomment the following route directive.

get '/login', to: 'pages#login'

This directs login requests to the pages controller’s login method, which in turn redirects the request to the omniauth-microsoft_v2_auth middleware.

def login
    redirect_to '/auth/microsoft_v2_auth'
end

Next, we need to specify where in the app OmniAuth should redirect once authentication has occurred. Uncomment the following route.

match '/auth/:provider/callback', to: 'pages#callback', via: [:get, :post]

When OmniAuth has finished authenticating the user, it calls the redirect URL specified in the app registration; in this case, *http://localhost:3000/auth/microsoft_v2_auth/callback*. The route pattern above matches that URL and so routes the request to the page controller’s callback method.

30.9.4 Get an access token

Next, we’ll add the code that actually starts the authentication process, and retrieves the access token once the user has successfully signed in.

Take a look at app/views/pages/index.html.erb, the view for the site root. The view includes a single button, which enables users to sign in.