{"id":2425,"date":"2019-01-17T12:01:41","date_gmt":"2019-01-17T12:01:41","guid":{"rendered":"https:\/\/developer.microsoft.com\/en-us\/office\/blogs\/?p=2425"},"modified":"2019-01-17T12:01:41","modified_gmt":"2019-01-17T12:01:41","slug":"mvp-article-sharepoint-framework-web-part-with-microsoft-graph-and-pnpjs-step-by-step-guide","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/mvp-article-sharepoint-framework-web-part-with-microsoft-graph-and-pnpjs-step-by-step-guide\/","title":{"rendered":"MVP Article &#8211; SharePoint Framework web part with Microsoft Graph and PnPjs: step by step guide"},"content":{"rendered":"<p class=\"code-line\">So you want to build a SharePoint Framework web part which uses\u00a0<a title=\"https:\/\/developer.microsoft.com\/en-us\/graph\" href=\"https:\/\/developer.microsoft.com\/en-us\/graph\">Microsoft Graph API<\/a>\u00a0through\u00a0<a title=\"https:\/\/pnp.github.io\/pnpjs\/\" href=\"https:\/\/pnp.github.io\/pnpjs\/\">PnPjs<\/a>. Here is step by step guide on how to do that.<\/p>\n<p class=\"code-line\">A few months ago I wrote a\u00a0<a title=\"http:\/\/spblog.net\/post\/2018\/09\/09\/Using-PnPjs-to-send-requests-to-MS-Graph-with-SharePoint-Framework-16\" href=\"http:\/\/spblog.net\/post\/2018\/09\/09\/Using-PnPjs-to-send-requests-to-MS-Graph-with-SharePoint-Framework-16\">similar<\/a>\u00a0post, however, things were changed, some things were simplified a lot, that\u2019s why this is a revisited guide. Also, I\u2019ve addressed some additional steps here. The source code is available on the official\u00a0<a title=\"https:\/\/github.com\/SharePoint\/sp-dev-fx-webparts\/tree\/master\/samples\/react-graph-pnpjs\" href=\"https:\/\/github.com\/SharePoint\/sp-dev-fx-webparts\/tree\/master\/samples\/react-graph-pnpjs\">SharePoint\/sp-dev-fx-webparts<\/a>\u00a0GitHub repository.<\/p>\n<h3 id=\"prerequisites\" class=\"code-line\">Prerequisites<\/h3>\n<ul>\n<li class=\"code-line\">SPFx &gt;= 1.6<\/li>\n<li class=\"code-line\">PnPjs &gt;= 1.2.4<\/li>\n<\/ul>\n<h2 id=\"1-scaffold-spfx-webpart-solution-with-react\" class=\"code-line\">1. Scaffold SPFx web part solution with React<\/h2>\n<p class=\"code-line\">This step is pretty self-explanatory, simply run\u00a0<em>yo @microsoft\/sharepoint<\/em>, select React, give your web part a name, do not change other defaults asked by yeoman.<\/p>\n<p class=\"code-line\"><img decoding=\"async\" class=\"alignnone wp-image-2427 size-full\" src=\"https:\/\/officedevblogs.wpengine.com\/wp-content\/uploads\/2019\/01\/scaffold.png\" alt=\"\" width=\"1024\" height=\"435\" srcset=\"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2019\/01\/scaffold.png 1024w, https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2019\/01\/scaffold-300x127.png 300w, https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2019\/01\/scaffold-768x326.png 768w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/p>\n<h2 id=\"2-install-pnpjs-dependencies\" class=\"code-line\">2. Install PnPjs dependencies<\/h2>\n<p class=\"code-line\">Run<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f8f8f8;overflow: auto;width: auto;border: solid gray;border-width: .1em .1em .1em .8em;padding: .2em .6em\">\n<pre style=\"margin: 0;line-height: 125%\"><span style=\"color: #888888\">npm install @pnp\/common @pnp\/odata @pnp\/logging @pnp\/graph @microsoft\/microsoft-graph-types --save<\/span>\n<\/pre>\n<\/div>\n<p class=\"code-line\">to install all required PnPjs dependencies and\u00a0<em>@microsoft\/microsoft-graph-types<\/em>\u00a0which contains useful type definitions for MS Graph types. You can also use\u00a0<em>\u2013save-exact<\/em>\u00a0flag to persist specific versions and prevent automatic update to the most recent ones.<\/p>\n<h2 id=\"3-configure-pnpjs-instance\" class=\"code-line\">3. Configure PnPjs instance<\/h2>\n<p class=\"code-line\">This step is required for all PnPjs related solutions. You should configure PnPjs to make it aware of your environment and \\ or application. In the case of an SPFx solution, the configuration part is very simple and straightforward.\u00a0Open your web part code file and import setup method:<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f8f8f8;overflow: auto;width: auto;border: solid gray;border-width: .1em .1em .1em .8em;padding: .2em .6em\">\n<pre style=\"margin: 0;line-height: 125%\"><span style=\"color: #008000;font-weight: bold\">import<\/span> { setup <span style=\"color: #008000;font-weight: bold\">as<\/span> pnpSetup } from <span style=\"color: #ba2121\">'@pnp\/common'<\/span>;\n<\/pre>\n<\/div>\n<p class=\"code-line\">Add\u00a0<em>onInit<\/em>\u00a0and configure\u00a0<em>spfxContext<\/em>\u00a0with an instance of web part&#8217;s context:<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f8f8f8;overflow: auto;width: auto;border: solid gray;border-width: .1em .1em .1em .8em;padding: .2em .6em\">\n<pre style=\"margin: 0;line-height: 125%\"><span style=\"color: #008000;font-weight: bold\">public<\/span> onInit()<span style=\"color: #666666\">:<\/span> Promise<span style=\"color: #666666\">&lt;<\/span><span style=\"color: #008000;font-weight: bold\">void<\/span><span style=\"color: #666666\">&gt;<\/span> { \n  pnpSetup({\n    spfxContext: <span style=\"color: #b00040\">this.context<\/span> \n  }); \n  <span style=\"color: #008000;font-weight: bold\">return<\/span> Promise.resolve(); \n}\n<\/pre>\n<\/div>\n<p>The code looks simple, however, a lot of things will happen at runtime later on.<\/p>\n<p>If we open PnPjs source code,\u00a0<em>graphlibconfig.ts<\/em>, we will see that under\u00a0<em>fetchClientFactory<\/em>\u00a0getter there is a check for\u00a0<em>spfxContext<\/em>\u00a0property:<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f8f8f8;overflow: auto;width: auto;border: solid gray;border-width: .1em .1em .1em .8em;padding: .2em .6em\">\n<pre style=\"margin: 0;line-height: 125%\"><span style=\"color: #008000;font-weight: bold\">public<\/span> get fetchClientFactory()<span style=\"color: #666666\">:<\/span> () <span style=\"color: #666666\">=&gt;<\/span> HttpClientImpl {\n  <span style=\"color: #008000;font-weight: bold\">const<\/span> graphPart <span style=\"color: #666666\">=<\/span> RuntimeConfig.get(<span style=\"color: #ba2121\">\"graph\"<\/span>);\n  <span style=\"color: #408080;font-style: italic\">\/\/ use a configured factory firt<\/span>\n  <span style=\"color: #008000;font-weight: bold\">if<\/span> (graphPart <span style=\"color: #666666\">!==<\/span> <span style=\"color: #008000;font-weight: bold\">undefined<\/span> <span style=\"color: #666666\">&amp;&amp;<\/span> graphPart <span style=\"color: #666666\">!==<\/span> <span style=\"color: #008000;font-weight: bold\">null<\/span> <span style=\"color: #666666\">&amp;&amp;<\/span> graphPart.fetchClientFactory <span style=\"color: #666666\">!==<\/span> <span style=\"color: #008000;font-weight: bold\">undefined<\/span>) {\n    <span style=\"color: #008000;font-weight: bold\">return<\/span> graphPart.fetchClientFactory;\n  }\n\n  <span style=\"color: #408080;font-style: italic\">\/\/ then try and use spfx context if available<\/span>\n  <span style=\"color: #008000;font-weight: bold\">if<\/span> (RuntimeConfig.spfxContext <span style=\"color: #666666\">!==<\/span> <span style=\"color: #008000;font-weight: bold\">undefined<\/span>) {\n    <span style=\"color: #008000;font-weight: bold\">return<\/span> () <span style=\"color: #666666\">=&gt;<\/span> AdalClient.fromSPFxContext(RuntimeConfig.spfxContext);\n  }\n\n  <span style=\"color: #008000;font-weight: bold\">throw<\/span> <span style=\"color: #008000\">Error<\/span>(<span style=\"color: #ba2121\">\"There is no Graph Client available, either set one using configuration or provide a valid SPFx Context using setup.\"<\/span>);\n}\n<\/pre>\n<\/div>\n<p class=\"code-line\">If the property is initialized, then\u00a0<em>fetchClientFactory<\/em>\u00a0will be initialized with a method, which returns an instance of\u00a0<em>SPFxAdalClient<\/em>\u00a0class.<\/p>\n<p class=\"code-line\"><em>fetchClientFactory<\/em>\u00a0returns an instance of a class, which implements\u00a0<em>fetch<\/em>\u00a0method.\u00a0<em>Fetch<\/em>\u00a0method simply sends http request, however it also can adjust ongoing http request or modify http headers or add authorization. In turn,\u00a0<em>SPFxAdalClient\u2019s<\/em>\u00a0fetch method adds OAuth bearer access token to ongoing http request to make it authenticated against MS Graph endpoint.<\/p>\n<p class=\"code-line\">If we inspect\u00a0<em>getToken<\/em>\u00a0method (inside\u00a0<em>SPFxAdalClient<\/em>\u00a0class):<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f8f8f8;overflow: auto;width: auto;border: solid gray;border-width: .1em .1em .1em .8em;padding: .2em .6em\">\n<pre style=\"margin: 0;line-height: 125%\"><span style=\"color: #008000;font-weight: bold\">public<\/span> getToken(resource: <span style=\"color: #b00040\">string<\/span>)<span style=\"color: #666666\">:<\/span> Promise<span style=\"color: #666666\">&lt;<\/span><span style=\"color: #b00040\">string<\/span><span style=\"color: #666666\">&gt;<\/span> {\n  <span style=\"color: #008000;font-weight: bold\">return<\/span> <span style=\"color: #008000;font-weight: bold\">this<\/span>.context.aadTokenProviderFactory.getTokenProvider().then(provider <span style=\"color: #666666\">=&gt;<\/span> {\n    <span style=\"color: #008000;font-weight: bold\">return<\/span> provider.getToken(resource);\n  });\n}\n<\/pre>\n<\/div>\n<p>we will see that it uses SPFx feature called\u00a0<a title=\"https:\/\/docs.microsoft.com\/en-us\/sharepoint\/dev\/spfx\/web-parts\/guidance\/connect-to-api-secured-with-aad\" href=\"https:\/\/docs.microsoft.com\/en-us\/sharepoint\/dev\/spfx\/web-parts\/guidance\/connect-to-api-secured-with-aad\">AadTokenProvider<\/a>\u00a0(first introduced in SPFx 1.6). It turned out that PnPjs uses some SPFx features for access token generation. What does it mean for us? It means that we should configure web API permissions for our web part accordingly because that&#8217;s the part of SPFx Web API permissions infrastructure which is used by PnPjs.<\/p>\n<h2 id=\"4-add-permission-requests-to-the-webpart\" class=\"code-line\">4. Add permission requests to the web part<\/h2>\n<p>Open\u00a0<em>.\/config\/package-solution.json<\/em>\u00a0and add permission requests:<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f8f8f8;overflow: auto;width: auto;border: solid gray;border-width: .1em .1em .1em .8em;padding: .2em .6em\">\n<pre style=\"margin: 0;line-height: 125%\"><span style=\"color: #ba2121\">\"webApiPermissionRequests\"<\/span>: [ \n  { \n    <span style=\"color: #008000;font-weight: bold\">\"resource\"<\/span>: <span style=\"color: #ba2121\">\"Microsoft Graph\"<\/span>, \n    <span style=\"color: #008000;font-weight: bold\">\"scope\"<\/span>: <span style=\"color: #ba2121\">\"Group.Read.All\"<\/span> \n  } \n]\n<\/pre>\n<\/div>\n<p>In my sample, I\u2019m going to use\u00a0<a title=\"https:\/\/docs.microsoft.com\/en-us\/graph\/api\/group-list?view=graph-rest-1.0\" href=\"https:\/\/docs.microsoft.com\/en-us\/graph\/api\/group-list?view=graph-rest-1.0\">Groups API<\/a>. In your web part, you should add as many permission requests as your app needs.<\/p>\n<h2 id=\"5-package-your-app\">5. Package your app<\/h2>\n<p>Run<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f8f8f8;overflow: auto;width: auto;border: solid gray;border-width: .1em .1em .1em .8em;padding: .2em .6em\">\n<pre style=\"margin: 0;line-height: 125%\"><span style=\"color: #888888\">gulp bundle --ship<\/span>\n<span style=\"color: #888888\">gulp package-solution --ship<\/span>\n<\/pre>\n<\/div>\n<p>to package your app.<\/p>\n<h2 id=\"6-upload-the-app-to-your-app-catalog\" class=\"code-line\">6. Upload the app to your app catalog<\/h2>\n<p class=\"code-line\">Locate your package at\u00a0<em>.\/sharepoint\/solution\/your-app.sppkg<\/em>. Upload that package to the app catalog. Upon uploading you will see below screen:<\/p>\n<p><img decoding=\"async\" class=\"alignnone wp-image-2428 size-full\" src=\"https:\/\/officedevblogs.wpengine.com\/wp-content\/uploads\/2019\/01\/trust-solution.png\" alt=\"\" width=\"625\" height=\"387\" srcset=\"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2019\/01\/trust-solution.png 625w, https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2019\/01\/trust-solution-300x186.png 300w\" sizes=\"(max-width: 625px) 100vw, 625px\" \/><\/p>\n<p class=\"code-line\">The message seems complicated, but what it means is that you should approve all permission requests which we added earlier.<\/p>\n<h2 id=\"7-approve-app-permission-requests\" class=\"code-line\">7. Approve app permission requests<\/h2>\n<p class=\"code-line\">There are different ways\u00a0<a title=\"https:\/\/docs.microsoft.com\/en-us\/sharepoint\/dev\/spfx\/use-aadhttpclient#manage-permission-requests\" href=\"https:\/\/docs.microsoft.com\/en-us\/sharepoint\/dev\/spfx\/use-aadhttpclient#manage-permission-requests\">to approve your permission requests<\/a>\u00a0(SharePoint Admin UI, PowerShell, o365 cli). The most simple one is through the new UI of SharePoint central administration. You can navigate to your old SharePoint admin center and click \u201cTry new\u201d UI from there. Or you can simply open a page\u00a0<code>https:\/\/&lt;org&gt;-admin.sharepoint.com\/_layouts\/15\/online\/AdminHome.aspx#\/webApiPermissionManagement<\/code>\u00a0(replace\u00a0<code>&lt;org&gt;<\/code>\u00a0with your real organization name)<\/p>\n<p class=\"code-line\"><img decoding=\"async\" class=\"alignnone wp-image-2429 size-full\" src=\"https:\/\/officedevblogs.wpengine.com\/wp-content\/uploads\/2019\/01\/api-management.png\" alt=\"\" width=\"856\" height=\"651\" srcset=\"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2019\/01\/api-management.png 856w, https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2019\/01\/api-management-300x228.png 300w, https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2019\/01\/api-management-768x584.png 768w\" sizes=\"(max-width: 856px) 100vw, 856px\" \/><\/p>\n<p class=\"code-line\">Go ahead and select your APIs and click Approve. Please note, that if you use this feature at your tenant for the first time, you might experience some issues. Sometimes it simply happens. I did a\u00a0<a title=\"http:\/\/spblog.net\/post\/2018\/09\/19\/You-might-experience-errors-when-first-trying-new-SPFx-16-features\" href=\"http:\/\/spblog.net\/post\/2018\/09\/19\/You-might-experience-errors-when-first-trying-new-SPFx-16-features\">post<\/a>\u00a0on issues I had. There is a\u00a0<a title=\"https:\/\/blog.mastykarz.nl\/common-issues-sharepoint-framework-api-permissions\/\" href=\"https:\/\/blog.mastykarz.nl\/common-issues-sharepoint-framework-api-permissions\/\">post<\/a>\u00a0by <a href=\"https:\/\/twitter.com\/waldekm\">Waldek Mastykarz<\/a> as well on a different set of issues you might see. If you see errors try to look for a solution in mentioned posts.<\/p>\n<p class=\"code-line\">Now we\u2019re ready with configuration part and can finally program our web part code.<\/p>\n<h2 id=\"8-write-code\" class=\"code-line\">8. Write code!<\/h2>\n<p class=\"code-line\">In my sample, I use\u00a0<a title=\"https:\/\/docs.microsoft.com\/en-us\/graph\/api\/group-list?view=graph-rest-1.0\" href=\"https:\/\/docs.microsoft.com\/en-us\/graph\/api\/group-list?view=graph-rest-1.0\">Groups API<\/a>\u00a0to get all Azure AD groups and display in a list. The code which gets the data is fairly simple:<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f8f8f8;overflow: auto;width: auto;border: solid gray;border-width: .1em .1em .1em .8em;padding: .2em .6em\">\n<pre style=\"margin: 0;line-height: 125%\">graph.groups.get<span style=\"color: #666666\">&lt;<\/span>Group[]<span style=\"color: #666666\">&gt;<\/span>().then(groups <span style=\"color: #666666\">=&gt;<\/span> {\n  <span style=\"color: #008000;font-weight: bold\">this<\/span>.setState({\n    groups\n  });\n});\n<\/pre>\n<\/div>\n<p>When ready, simply run\u00a0<em>gulp serve<\/em>\u00a0and open hosted workbench (it only works in hosted one) to see it in action.<\/p>\n<p>Once again, you can find the source code for this sample from the official\u00a0<a title=\"https:\/\/github.com\/SharePoint\/sp-dev-fx-webparts\/tree\/master\/samples\/react-graph-pnpjs\" href=\"https:\/\/github.com\/SharePoint\/sp-dev-fx-webparts\/tree\/master\/samples\/react-graph-pnpjs\">SharePoint\/sp-dev-fx-webparts<\/a> GitHub repository.<\/p>\n<h3>About the Author<\/h3>\n<p><img decoding=\"async\" class=\"wp-image-2426 size-full alignnone\" style=\"float: left;margin: 10px\" src=\"https:\/\/officedevblogs.wpengine.com\/wp-content\/uploads\/2019\/01\/sergei.jpg\" alt=\"\" width=\"200\" height=\"200\" srcset=\"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2019\/01\/sergei.jpg 200w, https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2019\/01\/sergei-150x150.jpg 150w, https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2019\/01\/sergei-24x24.jpg 24w, https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2019\/01\/sergei-48x48.jpg 48w, https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2019\/01\/sergei-96x96.jpg 96w\" sizes=\"(max-width: 200px) 100vw, 200px\" \/><\/p>\n<p>Sergei Sergeev is a Microsoft Office Development MVP, currently working as an independent developer and consultant with a focus on SharePoint Online, Office 365 and Azure. He loves modern trends in development for SharePoint with JavaScript, TypeScript, and NodeJS. He enjoys learning something new (fortunately SharePoint is a great place to learn something new every day), sharing knowledge, creating useful and interesting tools and making it available to the community via open source contributions on <a href=\"https:\/\/github.com\/s-KaiNet\/\">GitHub<\/a>.<\/p>\n<p>Sergei speaks on SharePoint events and user groups, regularly posts to his blog <a href=\"https:\/\/spblog.net\/\">https:\/\/spblog.net<\/a> and tweets from <a href=\"https:\/\/twitter.com\/sergeev_srg\">@sergeev_srg<\/a>.<\/p>\n<h3>What is the MVP article series?<\/h3>\n<p>We have <a href=\"https:\/\/developer.microsoft.com\/en-us\/office\/blogs\/opening-sharepoint-dev-blog-for-community-posts\/\">opened up our SharePoint developer blog<\/a> also for the Microsoft MVPs who would like to share their articles around SharePoint development topics also through this channel. All articles written by MVPs are clearly indicated by using the &#8220;MVP article&#8221; prefix in the title of the blog post. If you are an MVP and would like to get some additional exposure, please send your suggestions around the article to <a href=\"mailto:spdevblogcommunity@microsoft.com\"><em class=\"\">spdevblogcommunity@microsoft.com<\/em><\/a>\u00a0email address and we can start a discussion on the suggestion and possible publishing schedule.<\/p>\n<p>You can absolutely also do cross-posting of the article through your own blog, but we would prefer the material which is submitted as a suggestion, to be fresh and new, rather than something which\u00a0has been released months ago. We will use both <a href=\"https:\/\/twitter.com\/sharepoint\"><em>SharePoint<\/em><\/a> and <em><a href=\"https:\/\/twitter.com\/officedev\">OfficeDev<\/a><\/em> social media channels to promote these articles, so it&#8217;s a nice way to get you additional exposure for the community around the work you do.<\/p>\n<hr \/>\n<p><i>SharePoint Team, Microsoft &#8211; 17th of January 2019<\/i><\/p>\n","protected":false},"excerpt":{"rendered":"<p>MVP Article &#8211; SharePoint Framework web part with Microsoft Graph and PnPjs: step by step guide. Great community article with code samples on how to use the PnPjs and Microsoft Graph in SPFx solutions.<\/p>\n","protected":false},"author":69078,"featured_media":2430,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-2425","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-microsoft-365-developer"],"acf":[],"blog_post_summary":"<p>MVP Article &#8211; SharePoint Framework web part with Microsoft Graph and PnPjs: step by step guide. Great community article with code samples on how to use the PnPjs and Microsoft Graph in SPFx solutions.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/posts\/2425","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/users\/69078"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/comments?post=2425"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/posts\/2425\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/media\/2430"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/media?parent=2425"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/categories?post=2425"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/tags?post=2425"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}