Graph API
377 TopicsMicrosoft Graph API: Outlook Contact NOT Permanently Deleted with PermanentDelete.PostAsync()
I'm encountering an issue when attempting to permanently delete an Outlook contact using the Microsoft Graph API. The contact was previously inserted without any problems via the API, and I also assigned a profile picture to it, uploaded via the API. Contact? contactAdded = await _graphClient.Users["{user-id}"] .ContactFolders["{folder-id}"] .Contacts.PostAsync(contactToBeAdd, cancellationToken: cancelToken); I'm using the PermanentDelete endpoint as described in the Microsoft Graph documentation: API LINK My C# code looks like this: await graphClient.Users["{user-id}"].ContactFolders["{folder-id}"].Contacts["{contact-id}"].PermanentDelete.PostAsync(); The code executes successfully without throwing any exceptions. However, when I check the Outlook application (desktop or web), the contact still exists. It appears that almost all of the contact's information has been deleted, but the contact itself remains visible and still appears in searches. Has anyone else experienced this issue and can suggest a solution or an alternative approach to permanently delete Outlook contacts using the Graph API? Thanks in advance for any help.35Views0likes0CommentsApplicationAccessPolicy vs Azure Automation Account
Hi all. I have an Azure Automation Account (AAA) with enabled system managed identity. I added Graph API permission Mail.Send (application) to this identity and in script I'm able to send behalf of any email mailboxes. It works correctly. I want to restrict this AAA to specific mailboxes. So, I followed the Limiting application permissions to specific Exchange Online mailboxes - Microsoft Graph | Microsoft Learn. I created Service Principal for AAA by "New-ServicePrincipal" command and created new Application Access Policy. When I test it via Test-ApplicationAccessPolicy command I see correct result. But AAA is still able to send an email behalf of an email mailbox. Do you have the same experience?Solved56Views0likes2CommentsGetting Teams meeting transcripts using Powershell with Graph API
I have set up an Enterprise App in Entra with the following API permissions: Microsoft.Graph OnlineMeetings.Read (Delegated) OnlineMeetings.Read.All (Application) User.Read.All (Application) Admin consent has been granted for the Application types. Below is the code snippet for getting the meetings: $tenantId = "xxxxxx" $clientId = "xxxxxx" $clientSecret = "xxxxxx" $secureSecret = ConvertTo-SecureString $clientSecret -AsPlainText -Force $psCredential = New-Object System.Management.Automation.PSCredential ($clientId, $secureSecret) Connect-MgGraph -TenantId $tenantId -ClientSecretCredential $psCredential -NoWelcome $meetings = Get-MgUserOnlineMeeting -UserId "email address removed for privacy reasons" -All Connect-MgGraph is invoked without errors. I had verified this with Get-MgContext command. At line 10 I get this error: Status: 404 (NotFound) ErrorCode: UnknownError I don't know if this is means there was an error in the API call, or there were no records found (I do have Teams calls with transcripts though). I have tried changing the last line to (without -All): $meetings = Get-MgUserOnlineMeeting -UserId "my guid user id here" And I get this error: Status: 403 (Forbidden) ErrorCode: Forbidden Adding -All parameter results in this error: Filter expression expected - /onlineMeetings?$filter={ParameterName} eq '{id}'. I've done some searching but I haven't found any more information nor solution for this. I hope someone can point me in the right direction. Thanks in advance!75Views0likes0CommentsPodcast Microsoft Ignite E05: Agent Builder
Excited to have Pascal Brunner join me in my Ignite series, where we dive into one of the hottest announcements AgentBuilder In this episode, we break down: -What AgentBuilder is all about. -How it empowers organizations with AI-driven automation. -Key takeaways YOUTUBE https://youtube.com/@shadykhorshed?si=c8CLxoCjMfUMfA1938Views0likes0CommentsNew Blog Post: Android: Browser Access to be Enabled by Default for All Android Users
🔐#Android in #msintune: Upcoming Security Update for Microsoft Entra ID on Android! Starting July 2025, Microsoft Entra ID device registration will be hardware-bound, enhancing security and automatically enabling browser access. 🚀 Key Changes: ✅ Device identities will be tied to hardware for stronger security. ✅ Enable Browser Access (EBA) will be retired. ✅ Browser access will be enabled by default during registration. 📌 No action needed—this change will be applied automatically! Stay informed and prepare for a more secure device registration process. #MicrosoftIntune #MicrosoftEntraID #Android #mvpbuzz https://www.linkedin.com/pulse/microsoft-entra-browser-access-enabled-default-all-android-khorshed-5d8ee?utm_source=share&utm_medium=member_ios&utm_campaign=share_via151Views0likes0CommentsDuplicating Device Configuration Profiles
Duplicating Device Configuration Profiles 7/24/2019 - 13 Minutes to read One of the highest voted feature requests in Intune UserVoice is the ability to duplicate Device Configuration profiles and for good reason. I work in the Education sector, so I'm deploying carts of laptops to multiple classrooms in multiple schools. Generally, the whole school would have the same profiles assigned to all devices but teachers can be pretty fickle about what restrictions should and shouldn't be on their classroom's devices. So if a couple classrooms want to have one or two things changed for their carts, I'd be stuck in the portal, clicking away and comparing until I have four or five profiles that are exactly the same, aside from those tiny changes. It's a huge time suck having to do that and some setting always gets missed. Lucky us, (almost*) the entire Intune UI front end is built using Graph so anything we can do in the UI, we can also do in Graph. Let's say that the entire school has a profile applied to all devices but one classroom wants to block the camera. To do this through the UI, we'd have to start from scratch and dual monitor or split screen two windows to have the default profile open while we configure the one-off profile. But let's see how we can do this through Graph to speed up the process and help eliminate missed settings between the two profiles. I use two methods to view the profile through Graph. Between the two, the one that I use just depends on if I have Graph open already. If I don't have Graph open, I'll start in the portal. We'll start with that method first. Method 1 – Using Developer Tools from your Browser The first method, you'll be using your browser's built-in Developer Tools. For me, that's usually Chrome but I've been using the new Edge more and more lately. The good thing is since they are both built on Chromium, it's pretty much the same between the two. For this guide, I'll be using Chrome. Navigate to Intune > Device configuration – Profiles Since everything in the UI is just a frontend for Graph API, every time you do something in the UI, you'll be able to see all of the REST requests made by observing Network requests from the Network tab of your DevTools. This can look a little intimidating at first but if you start recording Network requests right before you view or change something in the UI, then stop recording when you're done viewing or changing things, you'll limit the number of recorded requests to only what happened while you making the changes or viewing the profiles. Open your browser's Developer Tools. In Chrome (called DevTools), this is done by pushing F12. Open the Network tab and make sure it's recording. You'll see the Red record button lit up. Click on the profile you want to copy. Once the page loads, stop the Network recording. You should now see a handful of requests listed there. These are what was happening behind the scenes as you opened the profile that you wanted to copy. We can break this down a little bit but we won't get too deep as that could be a completely separate guide by itself and I'm not an expert in RESTful APIs. You can see a little bit of what you need just by the name of the requests, but when you click on the requests, you'll get a lot more information. Click on the first one listed and open the Headers tab. In that tab, you'll see Request URL under General. Let's take a look at that URL and break it down. In this case, it can be broken down like this: https://graph.microsoft.com/{version}/{collection}/{collection}/{entity}?[query_parameters] So that means, "deviceManagment" is a collection that contains other collections, like "managedDeviceOverview", "detectedApps", and what we want, "deviceConfigurations". "deviceConfigurations" is the collection of, you guessed it, all your device configuration profiles. And the final part of the request URL is the ID of the device configuration profile entity that we are copying. Now technically, that is the full URL. The question mark is the query initiator and everything after is part of the query. In our URL, the query is requesting that the returned data also includes the assignments of the profile. We don't really need that and it's usually faster to just do the assignments through the UI unless you already have the entity ID of the groups you will be assigning them to. So now that we know all that, we can move on to the next Network request in the list which should be the actual "GET" request. What we are interested in with this one, is in the Response tab. These are all the settings that are in that device configuration profile and all their properties. Now, in this view it's pretty hard to read, but we can use Graph Explorer to get the same data in a prettier format since we have the request URL. Copy everything in the Request URL from the beginning up to the "?". Remember that the question mark and everything behind it is part of a query and is not something that we need right now. Open https://developer.microsoft.com/en-us/graph/graph-explorer# in a browser, sign in, and read and allow access if needed (if this is your first time using Graph and no one has accepted on behalf of the organization then you'll be prompted for this). In the Graph URL request input field, paste the Request URL that you just copied. Make sure that the HTTP verb select button is on GET and click on Run Query. Upon success you'll get a little notification with the Status Code of 200 and a Response Preview of all the settings and their properties in JSON format. We now have all the data we need to make another profile with the exact same settings. Method 2 – Using Graph to find the device configuration profile The second method is actually the one I use most since I typically have a Graph Explorer window open as one of my five opening tabs and since I'm becoming more comfortable using Graph. Open https://developer.microsoft.com/en-us/graph/graph-explorer# in a browser and enter https://graph.microsoft.com/v1.0/deviceManagement/deviceConfigurations into the Graph URL request input field, make sure that the HTTP verb select button is on GET and click on Run Query. How do I know this if I didn't use DevTools? The "Working with Intune in Microsoft Graph" (https://docs.microsoft.com/en-us/graph/api/resources/intune-graph-overview?view=graph-rest-1.0) doc is a pretty great reference on how to navigate your way through Graph. I have come across a few discrepancies here and there but for the most part, it's pretty solid. Using that doc, you can find out how to "list" all your device configurations. Again, you should see "Success – Status Code 200" after the query is returned. This time, in the Response Preview body, you'll see a list of all your device configuration profiles. For me, it's a very short list; just one profile, but in a production environment, there can be a lot more. Easiest thing to do is ctrl-F to find the name of the profile you want to copy but you can save yourself a little time and get a little practice in by adding some query parameters to the end of your request URL. We initiate the query parameter with "?" Followed by the name of the parameter. These query options are in OData V4 query language. We'll be using the "$filter" to filter out everything we don't need and only return what we do need. As you can see in the screen shot, the "displayName" of my policy is "Default Restrictions". Since we already know the name of the policy we are going to be copying, we can use that to filter everything else out by adding ?$filter=displayName eq 'Default Restrictions' to the end of our request URL and run the query. Now, only profiles matching that filter will be returned. Then copy the "id", and add it to the end of the request URL and run your query again. We now have the data we need to create a new profile with the same settings. Creating the new profile We should now be looking at a JSON formatted policy that we can copy and edit to create a new policy with. To do this, we'll need to prune out a few lines. While you can do this directly in Graph Explorer, I recommend using a smart text editor like Notepad ++ or Sublime Text. Copy everything from the opening bracket ( { ) just above the "@odata.context" line to the closing bracket ( } ) just after your last setting. Careful here. You have to make sure you're copying everything you need. In my profile, the last setting uses brackets within the setting. It's easy to misread it and copy the bracket that closes that setting and miss the bracket the closes the entire config. Just be mindful of that. Paste the copied text into a text editor and find the lines that you'll need to delete. You'll want to remove anything that is generated automatically like "@odata.context", "id", "lastModifiedDateTime", "supportsScopeTags", "createdDateTime", and "version". Once those are removed, you'll want to edit the "displayName" and "description" at least, but you can also make your configuration changes here if you know what you are doing. In my case, I'll change the "displayName", "description", and "cameraBlocked" settings, The first two setting properties are strings, while the "cameraBlocked" setting property is boolean. I'll replace displayName: "Default Restrictions" with "Custom Restrictions – City High School Room 104", description: "Standard policy for Company Windows 10 Devices" with "Modified from Default Restrictions – Block Camera", and cameraBlocked: false to true. Pay special attention to where the quotes are. There are none needed for boolean properties. Now I have my new profile in JSON format and we are ready to create the new profile using Graph. Open https://developer.microsoft.com/en-us/graph/graph-explorer and enter https://graph.microsoft.com/beta/deviceManagement/deviceConfigurations in the URL request field. Copy and paste our newly created JSON text into the Request Body field, change the HTTP verb select button to POST, run our query and be done. Obviously, you always want to be very careful when you are running POST requests, and generally any other request that isn't a read action. You should now get a notification with "Success – Status Code 201" along with a Response Preview of the complete JSON data of the new profile, including the automatically created settings that were removed previously. If you refresh your Intune > Device configuration – Profiles blade, you'll see your new profile. It's always best to compare the number of Settings Configured just to be sure nothing was missed. Here you can see that the new profile has the correct name, description, and has one more setting then the Default Restrictions profile. That additional setting is the Block Camera setting. So you can see how we can leverage Graph to programmatically make changes to Intune. It doesn't stop with duplicating profiles either. I've used it to create hundreds of Dynamic Device Groups, assign Apps to mass groups, and much more. Graph is adding to its capabilities to manage Intune as fast as Intune is adding features. And best of all, you get to deal with Intune UI a lot less. Follow Graph's What's new page at https://docs.microsoft.com/en-us/graph/whats-new-overview. Follow me on Twitter: @portaldotjay * -Thanks jenstf for pointing out that Intune also uses the API, "main.iam.ad.ext.azure.com". Be warned - using that API is unsupported so don't dink around in there if you don't know what you're doing.54KViews3likes10CommentsEdit app informations through Graph from existing mobile app with Powershell
Hi, in our environment we have published around 100 mobile apps. Mostly win32 apps. We would like to edit these mobile apps and add values for "owner" & "notes". Is it possible to edit these values through Graph?29Views0likes0CommentsStatus code keep changing after every query (404 & 200)
I am using the graph api to get the folders under my OneDrive root directory but the result is different in every run (most of the time failing). I have given it the Files.Read and Files.ReadWrite permission. This happened after I changed my microsoft password, but changing it again doesn't fix the issue. The query: https://graph.microsoft.com/v1.0/me/drive/root/children?%24select=name%2C%20id The screen recording: https://youtu.be/NIaz0Q37osg Timestamp: 0:00 - 0:13: 404 Not found error 0:16 - 0:26: 200 Files are found correctly 0:27 - 0:32: 404 Not found error again, without changing the query31Views0likes0CommentsNEW Podcast Microsoft Ignite E04: AI & Copilot – The Biggest Talk at MSIgnite!
Podcast Microsoft Ignite E04: AI & Copilot – The Biggest Talk at MSIgnite! AI is transforming the way we work, and Copilot is leading the charge! To break it all down and get expert insights, I’m joined by Jannik Reinhard and Fabio Bonolo to discuss: Key AI takeaways from Microsoft Ignite How companies & admins can benefit The future of AI-powered productivity Youtube: https://youtu.be/uD5V5a2Ldqg?si=u3R8fSndeW6wCruI49Views0likes0Comments