Month: November 2024

  • How to Create SharePoint List Items with MS Graph API: A Step-by-Step Guide

    In this article I’ll elaborate how to create SharePoint List Items with MS Graph API. You might have use cases, which require the automatic list item creations – example: Your customer is providing feedback and you want to process it in SharePoint to integrate it to other tools like PowerAutomate.

    In my current engagement, I am populating demo data to our rollout automation tool. Using a programmatic approach ensures that the demo data is provided equally for every new demo.

    Following endpoint is used to create SharePoint List Items:

    POST /sites/{site-id}/lists/{list-id}/items
    

    In this article, I’ll walk you through the approach, which enables you to use the endpoint. To call the provided endpoint, following four steps need to be followed:

    • Obtain bearer token: The bearer token is required to authenticate with Microsoft Graph API.
    • Obtain Site ID: Based on the site name, the site id is getting obtained, which is required for the list item creation with MS Graph
    • Obtain List ID: the List ID is required to specify the list in which the SharePoint list item shall be created. The ID will be fetched by the specification of the list title.

    Prerequisites to Create SharePoint List Items with MS Graph

    In order to create SharePoint List items with MS Graph, following prerequisites are required:


    Your App Registration should look like this in terms of granted permissions:

    Obtain Bearer Token to create SharePoint List Items with MS Graph API

    In order to obtain the bearer token, you need to conduct a POST call for the endpoint /oauth2/v2.0/token.

    You can use the script below, to obtain a bearer token. Make sure to provide your SharePoint tenant name (https://tenantname.sharepoint.com) and the app ID of your app registration in the parameters.

    param (
        [string]$Tenant = "m365x16735261",
        [string]$AppID = "39180af4-ad90-442f-a4ca-028b9221b133"
    )
    
    $AppCredential = Get-Credential ($AppID)
    
    # Define the required scope for accessing the Microsoft Graph API
    $Scope = "https://graph.microsoft.com/.default"
    
    # Prepare the body for the token request with client ID, client secret, and scope
    $Body = @{
        client_id     = $AppCredential.UserName                     # Client ID from app registration
        client_secret = $AppCredential.GetNetworkCredential().password   # Securely retrieve the client secret
        scope         = $Scope                                         # API scope required for MS Graph API access
        grant_type    = 'client_credentials'                      # Grant type for app-only authentication
    }
    
    # Azure AD endpoint to request an OAuth token
    $GraphUrl = "https://login.microsoftonline.com/$($Tenant).onmicrosoft.com/oauth2/v2.0/token"
    
    try
    {
        # Request the access token from Azure AD
        $AuthorizationRequest = Invoke-RestMethod -Uri $GraphUrl -Method "Post" -Body $Body
        # Retrieve the access token from the response
        $Access_token = $AuthorizationRequest.Access_token
        Write-Output $Access_token
    }
    catch
    {
        # Handle authentication errors, if any
        Write-Error "Error during token retrieval: $_"
        return $null
    }

    When running the code, you’ll get prompted for the app secret. Once you have executed the code, you’ll receive following output with the bearer access token:

    Obtain Site ID to create SharePoint List Items with MS Graph API

    With the bearer token, you can obtain the Site ID. You can obtain the Site ID by running the code below – make sure to update the parameters Hostname and ServerRelativePath.

    Param (
        # The API version of MS Graph
        $ApiVersion = "v1.0",
    
        # hostname of the tenant
        $HostName = "m365x16735261.sharepoint.com",
        
        # The relative path of the site, beginning with /sites/, /teams/, or another valid site type path.
        $ServerRelativePath = "sites/GraphSite1"
    
    )
    
    # Set the Authorization header with the bearer token for API requests
    $Header = @{
        Authorization  = "Bearer $Access_token"              # Bearer token for API authorization
        "Content-Type" = "application/json"                 # JSON content type for the request body
    }
    
    #Obtain the SiteID of the Site
    
    $Url = "https://graph.microsoft.com/$ApiVersion/sites/${HostName}:/$ServerRelativePath"
    $Site = Invoke-RestMethod -Uri $Url -Headers $Header
    Write-Output $Site

    Once you execute the script, you should see a similar output:

    Obtain List ID to create SharePoint List Items with MS Graph API

    As we were able to obtain the Site ID, we can now obtain the List ID in which we want to create SharePoint List Items. In the script below, I am obtaining the SharePoint List “Tools2”. Make sure to update Parameters, so that you get the list, in which you want to create the SharePoint List Items.

    Param (
        # The API version of MS Graph
        $ApiVersion = "v1.0",
    
        # The displayname of the List
        $ListTitle = "Tools2"
    )
    
    # Set the Authorization header with the bearer token for API requests
    $Header = @{
        Authorization  = "Bearer $Access_token"              # Bearer token for API authorization
        "Content-Type" = "application/json"                 # JSON content type for the request body
    }
    
    #Obtain the listID of the list
    
    $Url = "https://graph.microsoft.com/$ApiVersion/sites/$($Site.id)/lists/$ListTitle"
    $List = Invoke-RestMethod -Uri $Url -Headers $Header
    Write-Output $List

    Create SharePoint List Items with MS Graph API

    In order to create SharePoint List Items with Graph API, you need to specify how your items shall look like. You can do this by defining a Body as a JSON as per your list. In my List I have two columns in place: Title [string], NumberOfOffices [Integer], Blank Character Attribute [string].

    For that reason the body of my SharePoint List Item looks like this:

    $Body = @{
        fields = @{
            Title = "ListItemTest1"
            NumberOfOffices = 1
            BlankCharacterAttribute = "TEST"
        }
    }

    Note: Make sure that you take the internal name of your columns. You can do it by browsing to the column settings of your SharePoint List column.

    Now as we have all three components: Bearer Token, Site ID and ListID, we can create SharePoint List Items with MS Graph API:

    # The API version of MS Graph
    $ApiVersion = "v1.0"
    
    # The displayname of the List
    $ListTitle = "Tools2"
    
    
    # Set the Authorization header with the bearer token for API requests
    $Header = @{
        Authorization  = "Bearer $Access_token"              # Bearer token for API authorization
        "Content-Type" = "application/json"                 # JSON content type for the request body
    }
    
    
    # Define the list item properties for the new list creation request
    $Body = @{
        fields = @{
            Title = "ListItemTest1"
            NumberOfOffices = 1
            BlankCharacterAttribute = "TEST"
        }
    }
    
    # Set the endpoint URL for creating a list item in Microsoft Graph API
    $Url = "https://graph.microsoft.com/$ApiVersion/sites/$($Site.id)/lists/$($List.id)/items"
    
    # Convert the list item properties to JSON format required for the API request
    $BodyJSON = $Body | ConvertTo-Json -Compress -Depth 3
     
    # Send the HTTP POST request to create the list items with the defined properties
    $Response = Invoke-RestMethod -Uri $Url -Headers $Header -Method Post -Body $BodyJSON
    # Output the ID of the newly created list for confirmation
    Write-Output "List Item $BodyJSON created successfully"
    Write-Output $Response

    Once you run the script, you’ll get a similar output like this:

    Ready-to-Use PowerShell Script: Create SharePoint List Items with MS Graph

    Enclosed you’ll find a ready-to-use PowerShell script to create SharePoint List Items with MS Graph. Make sure to update the parameters of the script as explained before and also to adjust the $ItemBody hashtable, so that the list items are created as per your preference.

    # Define parameters for the tenant, application ID, site name, and mail nickname
    Param (
        # The API version of MS Graph
        $ApiVersion = "v1.0",
    
        # The Azure AD tenant ID for authentication
        $Tenant = "m365x16735261", 
    
        # The Application (client) ID of the registered Entra ID application registration, which is supposed to create SharePoint List (TenantAdminApp)
        $TenantAdminAppID = "3342565c-dca1-4b55-b107-7aa0e2f7bfd6",   
    
        # hostname of the tenant
        $HostName = "m365x16735261.sharepoint.com",
    
        # The relative path of the site, beginning with /sites/, /teams/, or another valid site type path.
        $ServerRelativePath = "sites/GraphSite1",
        
        # The displayname of the List
        $ListTitle = "Tools2"
    )
    
    function Get-GraphToken {
        param (
            [string]$Tenant,
            [PSCredential]$AppCredential
        )
        
        # Define the required scope for accessing the Microsoft Graph API
        $Scope = "https://graph.microsoft.com/.default"
    
        # Prepare the body for the token request with client ID, client secret, and scope
        $Body = @{
            client_id = $AppCredential.UserName                     # Client ID from app registration
            client_secret = $AppCredential.GetNetworkCredential().password   # Securely retrieve the client secret
            scope = $Scope                                         # API scope required for MS Graph API access
            grant_type = 'client_credentials'                      # Grant type for app-only authentication
        }
    
        # Azure AD endpoint to request an OAuth token
        $GraphUrl = "https://login.microsoftonline.com/$($Tenant).onmicrosoft.com/oauth2/v2.0/token"
    
        try {
            # Request the access token from Azure AD
            $AuthorizationRequest = Invoke-RestMethod -Uri $GraphUrl -Method "Post" -Body $Body
            # Retrieve the access token from the response
            return $AuthorizationRequest.Access_token
        } catch {
            # Handle authentication errors, if any
            Write-Error "Error during token retrieval: $_"
            return $null
        }
    }
    
    #region authentication - obtain bearer token
    while ($null -eq $TenantAdminAppCredential)
    {
        $TenantAdminAppCredential = Get-Credential -UserName $TenantAdminAppID -Message "Enter the client secret for the app TenantAdminAppID $TenantAdminAppID"
    }
    
    # Call the Get-GraphToken function and store the result
    $Access_token = Get-GraphToken -Tenant $Tenant -AppCredential $TenantAdminAppCredential
    
    # Check if access token is successfully obtained
    if (-not $Access_token) 
    {
        Write-Error "Failed to retrieve access token. Exiting script."
        return
    }
    
    # Set the Authorization header with the bearer token for API requests
    $Header = @{
        Authorization  = "Bearer $Access_token"              # Bearer token for API authorization
        "Content-Type" = "application/json"                 # JSON content type for the request body
    }
    Write-Output "Access token retrieved successfully."
    #endregion
    
    #Obtain the SiteID of the Site
    
    $Url = "https://graph.microsoft.com/$ApiVersion/sites/${HostName}:/$ServerRelativePath"
    $Site = Invoke-RestMethod -Uri $Url -Headers $Header
    
    #Obtain the listID of the list
    
    $Url = "https://graph.microsoft.com/$ApiVersion/sites/$($Site.id)/lists/$ListTitle"
    $List = Invoke-RestMethod -Uri $Url -Headers $Header
    
    #region create list item
    
    # Define which values your SharePoint List items shall contain
    $ItemBody = @{
        fields = @{
            Title = "ListItemTest"
            NumberOfOffices = 1
            BlankCharacterAttribute = "TEST"
        }
    }
    
    # Set the endpoint URL for creating a list item in Microsoft Graph API
    $Url = "https://graph.microsoft.com/$ApiVersion/sites/$($Site.id)/lists/$($List.id)/items"
    
    # Convert the list item properties to JSON format required for the API request
    $BodyJSON = $ItemBody | ConvertTo-Json -Compress -Depth 3
     
    try
    {
        # Send the HTTP POST request to create the list item with the defined properties
        $response = Invoke-RestMethod -Uri $Url -Headers $Header -Method Post -Body $BodyJSON
        # Output the ID of the newly created list item for confirmation
        Write-Output "List item $BodyJSON created successfully"
        Write-Output $response
    }
    catch
    {
        # Handle errors that may occur during the list creation request
        Write-Error "Failed to create list item: $_"
    }
    #endregion

    I hope this article helped you to create SharePoint List Items with MS Graph. For which use cases are you looking forward to create SharePoint List Items? Let us connect on LinkedIn:
    Serkar Aydin | LinkedIn

    References

    Here you can find the official reference from Microsoft, which elaborates on the POST endpoint to create SharePoint List Items:
    Create a new entry in a SharePoint list – Microsoft Graph v1.0 | Microsoft Learn

  • How to create SharePoint Lists with MS Graph

    In this post I want to showcase how to create a SharePoint Library and SharePoint List using MS Graph. You might need to create a SharePoint List with MS Graph if you have scenarios, where you need to ensure that your SharePoint Site is following a strict guideline in terms of predefined lists and libraries.

    I am currently crafting an asset and whenever we deploy this asset to new customers, we need to make sure that certain lists and libraries are also created as part of the asset. I can imagine you were facing dozens of similar requirements.

    The approach is quite simple:

    1. Create an App registration with Sites.FullControll.All Permissions to manage permissions of sites – I’ll call this app registration the TenantAdminApp – unfortunately the sites.selected permission is as of 16. November 2024 not sufficient. You’ll get an access denied response with sites.selcted.
    2. Obtain a Token with the TenantAdminApp App
    3. Create the SharePoint Lists using MS Graph with the TenantAdminApp App

    I’ll delve into each of the steps, so that you can create the same on your end and have it up and running.

    The benefit using MS Graph is ultimately, that you don’t need PowerShell at all to do so. So if you want to do it with Logic Apps or PowerAutomate, Postman you name it, you could do it.

    How to create the App registrations to create SharePoint Lists using MS Graph (TenantAdminApp)

    Make sure that you create the App registration as per this article, but just use the Site.Fullcontroll.All Application Permission:

    The TenantAdminApp should look like this:


    How to create the SharePoint List using MS Graph with PowerShell

    Now as our TenantAdminApp has the necessary permissions, we can create SharePoint Lists with MS Graph using PowerShell:

    Make sure to change the parameters to cover your use case.

    # Define parameters for the tenant, application ID, site name, and mail nickname
    Param (
        # The API version of MS Graph
        $ApiVersion = "v1.0",
    
        # The Azure AD tenant ID for authentication
        $Tenant = "m365x16735261", 
        # The Application (client) ID of the registered Entra ID application registration, which is supposed to create SharePoint List (TenantAdminApp)
        $TenantAdminAppID = "39180af4-ad90-442f-a4ca-028b9221b133",   
    
        # hostname of the tenant
        $HostName = "m365x16735261.sharepoint.com",
        # The relative path of the site, beginning with /sites/, /teams/, or another valid site type path.
        $ServerRelativePath = "sites/GraphSite1",
        
        # The displayname of the List
        $ListDisplayName = "Tools2"
    )
    function Get-GraphToken {
        param (
            [string]$Tenant,
            [PSCredential]$AppCredential
        )
        
        # Define the required scope for accessing the Microsoft Graph API
        $Scope = "https://graph.microsoft.com/.default"
    
        # Prepare the body for the token request with client ID, client secret, and scope
        $Body = @{
            client_id = $AppCredential.UserName                     # Client ID from app registration
            client_secret = $AppCredential.GetNetworkCredential().password   # Securely retrieve the client secret
            scope = $Scope                                         # API scope required for MS Graph API access
            grant_type = 'client_credentials'                      # Grant type for app-only authentication
        }
    
        # Azure AD endpoint to request an OAuth token
        $GraphUrl = "https://login.microsoftonline.com/$($Tenant).onmicrosoft.com/oauth2/v2.0/token"
    
        try {
            # Request the access token from Azure AD
            $AuthorizationRequest = Invoke-RestMethod -Uri $GraphUrl -Method "Post" -Body $Body
            # Retrieve the access token from the response
            return $AuthorizationRequest.Access_token
        } catch {
            # Handle authentication errors, if any
            Write-Error "Error during token retrieval: $_"
            return $null
        }
    }
    
    #region authentication - obtain bearer token
    while ($null -eq $TenantAdminAppCredential)
    {
        $TenantAdminAppCredential = Get-Credential -UserName $TenantAdminAppID -Message "Enter the client secret for the app TenantAdminAppID $TenantAdminAppID"
    }
    
    # Call the Get-GraphToken function and store the result
    $Access_token = Get-GraphToken -Tenant $Tenant -AppCredential $TenantAdminAppCredential
    
    # Check if access token is successfully obtained
    if (-not $Access_token) 
    {
        Write-Error "Failed to retrieve access token. Exiting script."
        return
    }
    
    # Set the Authorization header with the bearer token for API requests
    $Header = @{
        Authorization  = "Bearer $Access_token"              # Bearer token for API authorization
        "Content-Type" = "application/json"                 # JSON content type for the request body
    }
    Write-Output "Access token retrieved successfully."
    #endregion
    
    #Obtain the SiteID of the Site
    
    $Url = "https://graph.microsoft.com/$ApiVersion/sites/${HostName}:/$ServerRelativePath"
    $Site = Invoke-RestMethod -Uri $Url -Headers $Header
    
    #region create site
    # Define the list properties for the new list creation request
    $Body = @{
        displayName = $ListDisplayName
        list        = @{
            template = "genericList"
        }
    }
    
    # Set the endpoint URL for creating a list in Microsoft Graph API
    $Url = "https://graph.microsoft.com/$ApiVersion/sites/$(($site.id -split ",")[1])/lists"
    
    # Convert the list properties to JSON format required for the API request
    $BodyJSON = $Body | ConvertTo-Json -Compress
     
    try
    {
        # Send the HTTP POST request to create the list with the defined properties
        $response = Invoke-RestMethod -Uri $Url -Headers $Header -Method Post -Body $BodyJSON
        # Output the ID of the newly created list for confirmation
        Write-Output "List $ListDisplayName created successfully"
        Write-Output $response
    }
    catch
    {
        # Handle errors that may occur during the list creation request
        Write-Error "Failed to create list: $_"
    }
    #endregion

    After running the script, following response is provided:

    Access token retrieved successfully.
    List Tools2 created successfully
    
    @odata.context       : https://graph.microsoft.com/v1.0/$metadata#sites('e5320bcc-9e60-49b4-8ba4-2b63412c4e5c')/lists/$entity
    @odata.etag          : 62e80bab-b52a-44c0-a669-6a20de47f86c,0
    createdDateTime      : 16.11.2024 13:47:42
    description          : 
    eTag                 : 62e80bab-b52a-44c0-a669-6a20de47f86c,0
    id                   : 62e80bab-b52a-44c0-a669-6a20de47f86c
    lastModifiedDateTime : 16.11.2024 13:47:42
    name                 : Tools2
    webUrl               : https://m365x16735261.sharepoint.com/sites/GraphSite1/Lists/Tools2
    displayName          : Tools2
    parentReference      : @{siteId=m365x16735261.sharepoint.com,e5320bcc-9e60-49b4-8ba4-2b63412c4e5c,313e2cc9-70da-4859-8660-9ca104c56d1a}
    list                 : @{contentTypesEnabled=False; hidden=False; template=genericList}
    


    As we can see, we could create SharePoint List “Tools2” with MS Graph.

    How to create the SharePoint Libraries with MS Graph using PowerShell

    To create SharePoint Libraries with MSGraph using PowerShell, we just need to apply a different template, namely DocumentLibary:

    # Define parameters for the tenant, application ID, site name, and mail nickname
    Param (
        # The API version of MS Graph
        $ApiVersion = "v1.0",
    
        # The Azure AD tenant ID for authentication
        $Tenant = "m365x16735261", 
        # The Application (client) ID of the registered Entra ID application registration, which is supposed to create SharePoint List (TenantAdminApp)
        $TenantAdminAppID = "39180af4-ad90-442f-a4ca-028b9221b133",   
    
        # hostname of the tenant
        $HostName = "m365x16735261.sharepoint.com",
        # The relative path of the site, beginning with /sites/, /teams/, or another valid site type path.
        $ServerRelativePath = "sites/GraphSite1",
        
        # The displayname of the List
        $ListDisplayName = "Solutions",
        # The template, based on which the list/library must be created - for list it is genericList, for a library it is DocumentLibrary. Find here all templates: https://learn.microsoft.com/en-us/previous-versions/office/sharepoint-server/ms413878(v=office.15)?redirectedfrom=MSDN#members
        $ListTemplate = "DocumentLibrary"
    )
    function Get-GraphToken {
        param (
            [string]$Tenant,
            [PSCredential]$AppCredential
        )
        
        # Define the required scope for accessing the Microsoft Graph API
        $Scope = "https://graph.microsoft.com/.default"
    
        # Prepare the body for the token request with client ID, client secret, and scope
        $Body = @{
            client_id = $AppCredential.UserName                     # Client ID from app registration
            client_secret = $AppCredential.GetNetworkCredential().password   # Securely retrieve the client secret
            scope = $Scope                                         # API scope required for MS Graph API access
            grant_type = 'client_credentials'                      # Grant type for app-only authentication
        }
    
        # Azure AD endpoint to request an OAuth token
        $GraphUrl = "https://login.microsoftonline.com/$($Tenant).onmicrosoft.com/oauth2/v2.0/token"
    
        try {
            # Request the access token from Azure AD
            $AuthorizationRequest = Invoke-RestMethod -Uri $GraphUrl -Method "Post" -Body $Body
            # Retrieve the access token from the response
            return $AuthorizationRequest.Access_token
        } catch {
            # Handle authentication errors, if any
            Write-Error "Error during token retrieval: $_"
            return $null
        }
    }
    
    #region authentication - obtain bearer token
    while ($null -eq $TenantAdminAppCredential)
    {
        $TenantAdminAppCredential = Get-Credential -UserName $TenantAdminAppID -Message "Enter the client secret for the app TenantAdminAppID $TenantAdminAppID"
    }
    
    # Call the Get-GraphToken function and store the result
    $Access_token = Get-GraphToken -Tenant $Tenant -AppCredential $TenantAdminAppCredential
    
    # Check if access token is successfully obtained
    if (-not $Access_token) 
    {
        Write-Error "Failed to retrieve access token. Exiting script."
        return
    }
    
    # Set the Authorization header with the bearer token for API requests
    $Header = @{
        Authorization  = "Bearer $Access_token"              # Bearer token for API authorization
        "Content-Type" = "application/json"                 # JSON content type for the request body
    }
    Write-Output "Access token retrieved successfully."
    #endregion
    
    #Obtain the SiteID of the Site
    
    $Url = "https://graph.microsoft.com/$ApiVersion/sites/${HostName}:/$ServerRelativePath"
    $Site = Invoke-RestMethod -Uri $Url -Headers $Header
    
    #region create list
    
    # Define the list properties for the new list creation request
    $Body = @{
        displayName = $ListDisplayName
        list        = @{
            template = $ListTemplate
        }
    }
    
    # Set the endpoint URL for creating a list in Microsoft Graph API
    $Url = "https://graph.microsoft.com/$ApiVersion/sites/$(($site.id -split ",")[1])/lists"
    
    # Convert the list properties to JSON format required for the API request
    $BodyJSON = $Body | ConvertTo-Json -Compress -Depth 3
     
    try
    {
        # Send the HTTP POST request to create the list with the defined properties
        $response = Invoke-RestMethod -Uri $Url -Headers $Header -Method Post -Body $BodyJSON
        # Output the ID of the newly created list for confirmation
        Write-Output "List $ListDisplayName created successfully"
        Write-Output $response
    }
    catch
    {
        # Handle errors that may occur during the list creation request
        Write-Error "Failed to create list: $_"
    }
    #endregion

    As you can see, the SharePoint Library Solutions was created with MSGraph:

    How to add columns, when creating SharePoint Lists/ Libraries?

    The approach, which was showcased before will create simple lists and libraries with default columns. The approach can be extended further by adding columns to the SharePoint Lists/ Libraries. This can be done by extending the JSON body of the POST /Lists call.

    Add a Single Line of Text column to the SharePoint List

    Here you can find an example to add a single line of text column to the SharePoint list. You need to create a hash table, which elaborates about your columns. I added the Comment column to the SharePoint list.

    $Body = @{
        displayName = $ListDisplayName
        columns = @(
    		@{
    			name = "Comment"
                text = @{
                    allowMultipleLines = $false
                    appendChangesToExistingText = $false
                    linesForEditing = 0
                    maxLength = 255
                }
    		}
    	)
        list        = @{
            template = $ListTemplate
        }
    }

    Add a Integer Column to the SharePoint List

    Below you can find an example, which shows how to add a integer column to a SharePoint List/Library:

    $Body = @{
        displayName = $ListDisplayName
        columns = @(
    		@{
    			name = "Number of Entities"
    			number = @{
                    decimalPlaces= "none"
                    displayAs = "number"
                  }
    		}
    	)
        list        = @{
            template = $ListTemplate
        }
    }
    

    References

    Here you can find the definition of the column resource type, which describes which properties need to be considered, when adding a column:
    columnDefinition resource type – Microsoft Graph v1.0 | Microsoft Learn

    You could might also want to create SharePoint Sites using MS Graph:
    How to create SharePoint Sites using Graph | SPO Scripts


  • How to create SharePoint Sites using Graph

    In the previous article I was showcasing how to create a SharePoint Site with PNP.PowerShell. In this article I want to elaborate how to create a SharePoint Site with MS Graph.

    Creating SharePoint Sites with MS Graph can be interesting for integration scenarios as part of a overarching process. Let’s assume, that you want to create a SharePoint Site for each Sales opportunity or whenever a new Project is initiated, for this purpose it makes sense to create SharePoint Sites using Graph.

    The benefit for this approach in comparison to the PNP.PowerShell is, that you don’t need PowerShell for it, so you could theoretically also leverage every other programming language. In this article, I will create SharePoint sites using Graph in PowerShell, but you can easily replicate the approach to every different programing language as long as you stick to the foundation.

    You could create the SharePoint Sites using either a user account or an Azure Application Permission. In this article I will explain the SharePoint site creation based on an Azure Application Registration.

    In this article, I’ll leverage the MS Graph call POST /groups. With the creation of the M365 Group, a SharePoint teams site will be created.

    Why would you prioritize direct Graph Access vs Pnp.Powershell?

    There are integration scenarios, where you cannot install PowerShell modules. Either because it is not permitted by your organization or because your automation execution host is not using PowerShell as the programing language. This might be the case when you use ServiceNow Orchestration. Having an standard REST API adds flexibility in comparison to a PowerShell module, which can be only used on PowerShell execution hosts.

    Prerequisites to Create SharePoint Sites using Graph

    In order to create SharePoint Sites using Graph, you need to setup an App Registration in Azure Portal. The App Registration needs to have following permission.

    Permission typeLeast privileged permissionsHigher privileged permissions
    Delegated (work or school account)Group.ReadWrite.AllDirectory.ReadWrite.All
    Delegated (personal Microsoft account)Not supported.Not supported.
    ApplicationGroup.CreateDirectory.ReadWrite.All, Group.ReadWrite.All
    Permission Reference for creating SharePoint sites using Graph

    Looking forward, I’ll utilize the Application permission Group.Create following least privilege principles.

    Azure App Registration to Create SharePoint Sites using graph

    In order to create SharePoint sites using Graph, we need the Azure App registration considering the aforementioned application permission Group.Create.

    To create the Azure App Registration, browse to the Azure App Registration page in the Microsoft Azure Portal:

    Click on New registration:

    Provide a meaningful name and register the App by clicking on Register.

    Click on API Permissions

    By default the App is able to read user information from Entra ID. Click on Add a permission to add permissions.

    Now select Microsoft Graph

    Now click on Application Permissions, search for Group and provide the Group.Create permission.

    Now you have requested the permission. Make sure that the permission is also granted. You can grant it by a Global Administrator, Application Administrator, or Cloud Application Administrator.

    Once the permission is granted, the page should look like this:

    Now we made sure that the App registration is created and the necessary permissions are granted. We just need to make sure to configure the authentication of the Application. There are two approaches, which can be used to authenticate with Entra ID:

    1. Certificate based authentication
    2. Secret based authentication

    For this article, I’ll use the secret based authentication. However in production use, consider using a certificate, which is considered to be more secure.

    Browse to the Certificates and secrets blade, click on Client secrets and on New client secret.

    Provide a meaningful name to the client secret. I’ll use GroupMgmt_GroupCreate_180days and configure the lifetime. I’ll use the default lifetime of 180 days. Before expiration you need to make sure to create an additional client secret, and change it in your code. Else your app and the use case won’t work.

    After addition, you’ll be shown only once the value of the client secret. Make sure to store it in a secure place like a key vault.

    Create SharePoint Site Using Graph: PowerShell code

    With the code below you can create SharePoint Sites using Graph with PowerShell. Before you run the code, make sure that you change the parameters.

    If you trigger the code below, you’ll get prompted the app secret, which you have created previously.

    How can I avoid getting prompted on Windows?

    To avoid getting prompted each time for the app secret value, make sure to export it like this:

    Make sure that you export the credential with the user account, with which you want to run the code, and also the machine, on which the code shall run. If you copy the credential xml to another machine or try to decode the credential file with a different user account, you’ll notice that you won’t be able to do so.

    If you use the PowerShell code in Azure (like in Azure Automation, Azure Functions), make sure that you store the credentials in a secure place e.g. Azure Key Vault.

    # Export the Credential path to specified path   
    Get-Credential | Export-CliXml -Path c:\creds\credential.xml
    
    # Import the credential object from specified path
    $Credential = Import-CliXml -Path c:\creds\credential.xml

    The code below is first attempting to obtain a bearer token from Entra Id. Once the token is obtained, it is intended to create an Entra ID group, based on which the SharePoint Site is getting created.

    # Define parameters for the tenant, application ID, site name, and mail nickname
    Param (
        # The Azure AD tenant ID for authentication
        $Tenant = "m365x16735261", 
        # The Application (client) ID of the registered Azure AD application
        $AppID = "730efedf-b000-4deb-92c6-25da0e27e24d",   
        # The display name of the group to be created
        $SiteName = "GraphSite7",   
        # The mail nickname for the group (used for email addressing)
        $Mailnickname = "GraphSite7"   
    )
    
    # Securely prompts for application credentials (Client ID and Secret)
    #$AppCredential = Get-Credential -UserName $AppID -Message "Enter the client secret"
    
    # Function to obtain the Microsoft Graph API token
    function Get-GraphToken {
        param (
            [string]$Tenant,
            [PSCredential]$AppCredential
        )
        
        # Define the required scope for accessing the Microsoft Graph API
        $Scope = "https://graph.microsoft.com/.default"
    
        # Prepare the body for the token request with client ID, client secret, and scope
        $Body = @{
            client_id = $AppCredential.UserName                     # Client ID from app registration
            client_secret = $AppCredential.GetNetworkCredential().password   # Securely retrieve the client secret
            scope = $Scope                                         # API scope required for MS Graph API access
            grant_type = 'client_credentials'                      # Grant type for app-only authentication
        }
    
        # Azure AD endpoint to request an OAuth token
        $GraphUrl = "https://login.microsoftonline.com/$($Tenant).onmicrosoft.com/oauth2/v2.0/token"
    
        try {
            # Request the access token from Azure AD
            $AuthorizationRequest = Invoke-RestMethod -Uri $GraphUrl -Method "Post" -Body $Body
            # Retrieve the access token from the response
            return $AuthorizationRequest.Access_token
        } catch {
            # Handle authentication errors, if any
            Write-Error "Error during token retrieval: $_"
            return $null
        }
    }
    
    # Call the Get-GraphToken function and store the result
    $Access_token = Get-GraphToken -Tenant $Tenant -AppCredential $AppCredential
    
    # Check if access token is successfully obtained
    if (-not $Access_token) {
        Write-Error "Failed to retrieve access token. Exiting script."
        return
    }
    
    # Set the Authorization header with the bearer token for API requests
    $Header = @{
        Authorization = "Bearer $Access_token"              # Bearer token for API authorization
        "Content-Type" = "application/json"                 # JSON content type for the request body
    }
    Write-Output "Access token retrieved successfully."
    
    #region create site
    # Define the group properties for the new group creation request
    $Body = @{
        displayName = $SiteName                   # Name displayed for the new group in Azure AD
        groupTypes = @("Unified")                 # "Unified" indicates an Office 365 group
        mailEnabled = $false                       # Enable mail functionality for the group
        mailNickname = $Mailnickname              # The mail alias for the group, unique for Microsoft 365 groups in the organization
        securityEnabled = $false                  # Indicates that this is not a security group
    }
    
    # Set the endpoint URL for creating a group in Microsoft Graph API
    $Url = "https://graph.microsoft.com/v1.0/groups"
    # Convert the group properties to JSON format required for the API request
    $BodyJSON = $Body | ConvertTo-Json -Compress
    
    try {
        # Send the HTTP POST request to create the group with the defined properties
        $response = Invoke-RestMethod -Uri $Url -Headers $Header -Method Post -Body $BodyJSON
        # Output the ID of the newly created group for confirmation
        Write-Output "Group created successfully: $($response.id)"
        Write-Output "Site created succesfully: $SiteName"
    } catch {
        # Handle errors that may occur during the group creation request
        Write-Error "Failed to create group: $_"
    }
    #endregion

    Upon submission of the code, you’ll get following similar output:

    With the execution of the code, the SharePoint site https://m365x16735261.sharepoint.com/sites/GraphSite8 was just created:

    Create SharePoint Sites using Graph: Postman

    I want to showcase the strength of the usage of MS Graph by showing how to create SharePoint sites with Postman. The approach consists of a two staged process: Obtain Bearer Token and creation of Entra ID group.

    Create SharePoint Sites using Graph: Postman – Prerequisites

    Make sure that you install Postman or utilize the web version of postman. You can download it from the official website: Postman API Platform

    Create SharePoint Sites using Graph: Postman – Obtain bearer token

    To create the bearer token, you need to trigger a POST call for the endpoint https://login.microsoftonline.com/<tenanturl>/oauth2/v2.0/token

    In my example it is: https://login.microsoftonline.com/m365x16735261.onmicrosoft.com/oauth2/v2.0/token

    Make sure you maintain following body as x-www-form-urlencoded:

    KeyValue
    grant_typeclient_credentials
    client_id<app id of the Azure App registration>
    In my example:
    730efedf-b000-4deb-92c6-25da0e27e24d
    client_secret<secret of the Azure App registration>
    scope.default

    Your call shall look like this:

    After calling it you should receive a bearer token as part of a response:

    {
        "token_type": "Bearer",
        "expires_in": 3599,
        "ext_expires_in": 3599,
        "access_token": "eyJ0eXAiOiJKV1QiLCJub2...<SANITIZED>"
    }

    Copy the bearer token value, you’ll need it in the next step.

    Create SharePoint Sites using Graph: Postman – Create Group

    Now as you have obtained the bearer token, create another tab and make sure to Enter following header information:

    KeyValue
    Content-Typeapplication/json
    AuthorizationBearer eyJ0eXAiOiJKV1QiLCJub25jZSI6ImkyQUxLTktKMVpoRXdTU2xoWDJrYXZ1a09IRVFocUdQMnRESzhGWS1naGciLCJhbGciOiJSUzI1NiIsIng1dCI6IjNQYUs0RWZ5Qk5RdTNDdGpZc2EzWW1oUTVFMCIsImtpZCI6<SANITIZED>

    Proceed with the body configuration:

    Provide the body as JSON. Make sure to adjust it based on your scenario:

    {
      "mailEnabled": false,
      "displayName": "GraphSite10",
      "mailNickname": "GraphSite10",
      "securityEnabled": false,
      "groupTypes": [
        "Unified"
      ]
    }

    After submitting the POST request, you’ll get the Entra ID group and the Site created. This is a sample response, upon submission of the request.

    {
        "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#groups/$entity",
        "id": "d32e29f1-68e2-4a55-a9cd-bda027125522",
        "deletedDateTime": null,
        "classification": null,
        "createdDateTime": "2024-11-01T23:32:57Z",
        "creationOptions": [],
        "description": null,
        "displayName": "GraphSite10",
        "expirationDateTime": null,
        "groupTypes": [
            "Unified"
        ],
        "isAssignableToRole": null,
        "mail": "GraphSite10@M365x16735261.onmicrosoft.com",
        "mailEnabled": true,
        "mailNickname": "GraphSite10",
        "membershipRule": null,
        "membershipRuleProcessingState": null,
        "onPremisesDomainName": null,
        "onPremisesLastSyncDateTime": null,
        "onPremisesNetBiosName": null,
        "onPremisesSamAccountName": null,
        "onPremisesSecurityIdentifier": null,
        "onPremisesSyncEnabled": null,
        "preferredDataLocation": null,
        "preferredLanguage": null,
        "proxyAddresses": [
            "SMTP:GraphSite10@M365x16735261.onmicrosoft.com"
        ],
        "renewedDateTime": "2024-11-01T23:32:57Z",
        "resourceBehaviorOptions": [],
        "resourceProvisioningOptions": [],
        "securityEnabled": false,
        "securityIdentifier": "S-1-12-1-3543017969-1247111394-2696793513-576000551",
        "theme": null,
        "uniqueName": null,
        "visibility": "Public",
        "onPremisesProvisioningErrors": [],
        "serviceProvisioningErrors": []
    }

    As one can see below, the SharePoint site was created.

    With the Postman approach, you can see the benefit: You really don’t rely anymore on PowerShell. With Graph you can create SharePoint Sites, with every REST API execution host.

    Conclusion

    With the approach, we have a straight forward approach to create SharePoint sites, without being dependent on PowerShell. Now I am curious about your setup: Do you create SharePoint Sites as part of a workflow? Which business use case are you supporting with it and what else are you creating apart from the SharePoint Site?

    References