Build an intelligent application by
connecting it to the Microsoft Graph
#SPC18
Sébastien Levert
Hi! I’m Seb!
@sebastienlevert | http://sebastienlevert.com | Product Evangelist & Partner Manager at
Agenda
Agenda
Introduction
Microsoft Graph is all about you
If you or your customers are part of the millions of users that are using Microsoft
cloud services, then Microsoft Graph is the fabric of all your data
It all starts with /me
Gateway to your data in the Microsoft
cloud
Your app
Gateway
Your or your
customer’s
data
Office 365 Windows 10 Enterprise Mobility + Security
1Microsoft Graph
Microsoft Graph
ALL
Microsoft 365
Office 365
Windows 10
EMS
ALL ONE
https://graph.microsoft.com
Microsoft 365 Platform
web, device,
and service apps
Extend Microsoft 365 experiences
1
iOS/Android/Windows/Web
Build your experience
Microsoft Graph
Agenda
Getting Started
Exploring the Graph
• Using the Graph Explorer
• Using plain HTTP Calls
• Using .NET
• Using PnP PowerShell
• Using JavaScript (Browser or Node)
• Using the SDKs
Acting on the graph
• Getting Graph data
• Creating Graph data
• Updating Graph data
• Deleting Graph data
• Executing actions on the Graph
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# Connecting to your tenant
Connect-PnPOnline -Graph -LaunchBrowser
# Build the Headers with the Access Token value
$headers = @{
"Authorization" = [String]::Format("Bearer {0}", (Get-PnPAccessToken))
"Content-Type" = "application/json"
}
# Calling the Microsoft Graph
Invoke-RestMethod -Header $headers -Uri "https://graph.microsoft.com/v1.0/me"
Get-Contacts.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
GET https://graph.microsoft.com/v1.0/me/contacts
Accept: application/json
Content-Type: application/json
{
"value": [{
"id":"AAMkAGZkNzVjNzkyLWE0OT…",
"createdDateTime": "2018-05-22T18:19:02Z",
"lastModifiedDateTime": "2018-05-22T18:19:02Z",
//…
}]
}
Listing All Contacts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
GET https://graph.microsoft.com/v1.0/me/contacts/AAMkAGZkNzVjNzkyLWE0OT…
Accept: application/json
Content-Type: application/json
{
"id":"AAMkAGZkNzVjNzkyLWE0OT…",
"createdDateTime": "2018-05-22T18:19:02Z",
"lastModifiedDateTime": "2018-05-22T18:19:02Z",
//…
}
Getting a specific Contacts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
POST https://graph.microsoft.com/v1.0/me/contacts
Accept: application/json
Content-Type: application/json
{
"givenName": "Sébastien",
"surname": "Levert",
"emailAddresses": [{
"address": "seb@valointranet.com",
"name": "Sébastien Levert"
}],
"businessPhones": [
"+1 555 555 5341"
]
}
Creating a Contact
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
PATCH https://graph.microsoft.com/v1.0/me/contacts/AAMkAGZkNzVjNzkyLWE0OT…
Accept: application/json
Content-Type: application/json
{
"givenName":"Seb"
}
Updating a specific Contact
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
DELETE https://graph.microsoft.com/v1.0/me/contacts/AAMkAGZkNzVjNzkyLWE0OT…
Accept: application/json
Content-Type: application/json
{
}
Getting a specific Contacts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# Building an Email JSON representation
$EmailBody = @{
"Message" = @{
"Subject" = "This is a test email from PowerShell!"
"Body" = @{
"ContentType" = "HTML"
"Content" = "This email was sent from PowerShell using the Microsoft Graph."
}
"ToRecipients" = @(
@{
"EmailAddress" = @{
"Address" = "admin@slevert.onmicrosoft.com"
}
}
)
}
}
Invoke-RestMethod -Header $headers –Uri "https://graph.microsoft.com/v1.0/me/sendMail" -
Method Post -Body ($EmailBody | ConvertTo-Json -Depth 4)
Send-Email.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Requiring the Microsoft Graph SDK
const MicrosoftGraph = require("../../lib/src/index.js").Client;
// Getting the Access Token from a secret file
const secrets = require("./secrets");
// Initializing the Microsoft Graph SDK
const client = MicrosoftGraph.init({
defaultVersion: 'v1.0’,
debugLogging: true,
authProvider: (done) => {
done(null, secrets.accessToken);
}
});
send-email.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Building the Email Message
const mail = {
subject: "This is a test email from NodeJS!",
toRecipients: [{
emailAddress: {
address: "admin@slevert.onmicrosoft.com"
}
}],
body: {
content: "This email was sent from NodeJS using the Microsoft Graph.",
contentType: "html"
}
}
// Email from the Microsoft Graph
client.api("/users/me/sendMail").post({message: mail}, (err, res) => {
if (err) console.log(err);
else console.log("Sent an email");
});
send-email.js
Agenda
Advanced Scenarios
Batching
•Batch requests are always sent using
POST to the /$batch endpoint.
•Dependent Queries are supported
•Can help with URL limitations
•Up to 20 individual requests
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Creating our Subscription
POST https://graph.microsoft.com/v1.0/$batch
Accept: application/json
Content-Type: application/json
{
"requests": [{
"id": "1",
"method": "GET",
"url": "/me/contacts"
},
{
"id": "2",
"url": "/me",
"method": "PATCH",
"body": { "city" : "Montreal"},
"headers": { "Content-Type": "application/json"}
}]
}
Batch multiple Queries
Be notified by the Graph
• Using Webhooks to get the notification
• Using Delta Query to query the changes
• Supported by the following resources :
• Contacts
• Conversations
• Events
• Messages
• Groups
• Users
• Drives
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Creating our Subscription
POST https://graph.microsoft.com/v1.0/subscriptions
Accept: application/json
Content-Type: application/json
{
"changeType": "Created",
"notificationUrl": "https://<url>/api/webhookCallback",
"resource": "me/contacts"
}
Create a Subscription
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Getting notified by the WebHook
POST https://<url>/api/webhookCallback
Accept: application/json
Content-Type: application/json
{
"value":[{
"subscriptionId":"7f105c7d-2dc5-4530-97cd-4e7af6534c07",
"subscriptionExpirationDateTime":"2015-11-20T18:23:45.9356913Z",
"changeType":"Created",
"resource":"Users/<user-id>/contacts/<contact-id>",
"resourceData":{
"@odata.type":"#Microsoft.Graph.Message",
"@odata.id":" Users/<user-id>/contacts/<contact-id>",
"@odata.etag":"W/"CQAAABYAAACoeN6SYXGLRrvRm+CYrrfQAACvvGdb"",
"Id":"<contact-id>"
}
}]
}
Being notified by the Graph
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Getting notified by the WebHook
GET https://graph.microsoft.com/v1.0/me/contacts/delta
Accept: application/json
Content-Type: application/json
{
"@odata.nextLink":"{…}/v1.0/me/contacts/delta?$skiptoken={skipToken}",
"value": [{
//…
}]
}
Using Delta Query
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Getting the Delta Link once all pages were covered
GET https://graph.microsoft.com/v1.0/me/contacts/delta?$skiptoken={skipToken}
{
"@odata.deltaLink":"{…}/v1.0/me/contacts/delta?$deltatoken={deltatoken}",
"value": []
}
Using the Delta Query Strategy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Getting the Delta Link once all pages were covered
GET https://graph.microsoft.com/v1.0/me/contacts/delta?$deltatoken={deltatoken}
Accept: application/json
Content-Type: application/json
{
"@odata.deltaLink":"{…}/v1.0/me/contacts/delta?$deltatoken={deltatoken}",
"value": [{
//…
}]
}
Getting the Delta Content
Extending the Graph
• Open type extensions for simple
key/value properties
• Schema extensions for typed properties
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
POST https://graph.microsoft.com/v1.0/me/contacts/<id>/extensions
{
"@odata.type": "Microsoft.Graph.OpenTypeExtension",
"extensionName": "Contacts.Extensions.LinkedIn",
"linkedInUrl": "https://www.linkedin.com/in/seb/"
}
Adding an Open Extension
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
GET https://graph.microsoft.com/v1.0/me/contacts/<id>?$
expand=Extensions($filter=Id eq 'Contacts.Extensions.LinkedIn')
{
//…
"extensions": [{
"@odata.type": "#microsoft.graph.openTypeExtension",
"extensionName": "Contacts.Extensions.LinkedIn",
"linkedInUrl": "https://www.linkedin.com/in/seb/"
}]
}
Getting an Open Extension Value
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
POST https://graph.microsoft.com/v1.0/schemaExtensions
{
"id": "domain_linkedinInformation",
"description": "All information about LinkedIn account",
"targetTypes": ["Contacts"],
"available": "Online",
"properties" : [{
"name": "linkedInUrl",
"type": "String"
}]
}
Defining a Schema Extension
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
POST https://graph.microsoft.com/v1.0/me/contacts/<id>/extensions
{
"domain_linkedinInformation": {
"linkedInUrl": "https://www.linkedin.com/in/seb/"
}
}
Setting a Schema Extension
Best Practices
• When no response required (PUT, PATCH,
POST), opt out of the response by using
HTTP Prefer return=minimal
• Using projection & filters will limit the
number of data transferred and speed up
your applications
• Watch for server-side pagination and look
for @odata.nextLink property in
response
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
GET
https://graph.microsoft.com/v1.0/me/contacts?$select=displayName,businessPhones
Accept: application/json
Content-Type: application/json
{
"value": [{
"id":"AAMkAGZkNzVjNzkyLWE0OT…",
"displayName": "Sébastien Levert",
"businessPhones": [
"+1 555 555 5555",
]
//…
}]
}
Projections
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
GET https://graph.microsoft.com/v1.0/me/contacts?$filter=startswith(displayName,
'Seb')
Accept: application/json
Content-Type: application/json
{
"value": [{
"id":"AAMkAGZkNzVjNzkyLWE0OT…",
"displayName": "Seb Levert",
"businessPhones": [
"+1 555 555 5555",
]
//…
}]
}
Filters
And…What about
SharePoint?
• The Microsoft Graph exposes items, lists,
webs and site collections
• SharePoint Framework has a built-in
mechanism available to interact with the
Microsoft Graph
Agenda
Next Steps
Resources
• https://dev.office.com
• https://aka.ms/ge
• https://graph.microsoft.com
• https://github.com/microsoftgraph/msgraph-community-samples
Share your experience
• Use hashtags to share your experience
• #Office365Dev
• #MicrosoftGraph
• Hack with the Microsoft Graph!
• https://aka.ms/office365hackathon
• Log issues & questions to the GitHub Repositories
Thank you!
@sebastienlevert | http://sebastienlevert.com | Product Evangelist & Partner Manager at

SharePoint Conference 2018 - Build an intelligent application by connecting it to the Microsoft Graph