Upload files to SharePoint using Graph API (PowerShell)

How to upload files to SharePoint using Graph API (PowerShell)

Uploading files to SharePoint is a common use case, when we are integrating 3rd party systems with SharePoint. In my previous articles, I have been explaining how you can upload files to SharePoint using PNP module. In this article, I want to show you how you can achieve upload files to SharePoint using Graph API.

Note: This method works for files, where the size is maximum 4 MB.

In the beginning, we will create an Azure Enterprise Application in Azure Active Directory. Then we will grant the created Enterprise Application the permission to interact with selected sites. At the end, I will share a PowerShell script to upload files to the SharePoint using Graph API.

What do I need to upload files to SharePoint using Graph API?

To upload a file to SharePoint using Graph API, you need the following prerequisites fulfilled:

  • You need your global administrator in your organization to grant the sites.selected permission for an Azure Enterprise Application
  • You need to install PNP PowerShell module, to grant the Enterprise Application the permission to upload files to the specific SharePoint Site

How to create the Enterprise Application to upload Files to SharePoint?

In the beginning it is import to understand, which permission the Enterprise Application needs so that we can upload files to SharePoint using Graph API.

  1. Browse to Azure Active Directory Portal
  2. Create an App Registration with Sites.Selected permissions
  3. Create and note down credentials for the App Registration


I will explain how to do it step-by-step.

Browse to Azure Active Directory Portal

Open https://portal.azure.com/#view/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade in your browser.

If you have the global admin rights, I recommend authenticating with that account, so that you can directly grant your enterprise application the permission. Otherwise, you need to reauthenticate or ask your administrator to grant your enterprise application the permissions.

Create an App Registration with Sites.Selected permissions

Browse to the App Registration blade

Screenshot of the App registrations shortcut

Click on new registration

Screenshot of new enterprise app registration

Define for the App a meaningful name, which follows your organization standards (Different admins should recognize what the purpose for this app is) and register it.

Screenshot on how to create the App registration in MS Azure

Browse to API permissions to grant your app registration the permission to upload files to SharePoint using Graph API.

Screenshot of configuration blade for App API permissions

Click on Add a permission

Screenshot of how to add the API permission to the App registration

Now choose Microsoft Graph

Chose of Microsoft Graph Permission

If you want your application to work in the background (Without any user authentication), you need to choose Application permission. As my intention is to show you how to automate the process, I am sharing with you the application permission way.

Screenshot of Application permission path of API permission

Now search for Sites.Selected and click on add permissions.

image 7

If you are signed in with a user account with global administrator privileges, you can grant administrator admin consent for your tenant. In other case, you either need to sign in with the global administrator account or you have to ask your administrator to grant your app registration the permission.

Screenshot of grant admin consent for tenant of the app registration

Create Secret for the App Registration

To authenticate with your enterprise application, you need to either upload a certificate or create a secret for your enterprise application. In this case I am creating a secret.

Browse to Certificates & secrets

Screenshot of Certificates & secrets blade

Screenshot on how to create a client secret

For the description, I think it makes sense to define which application is going to use your client secret. For the duration, I would go with the recommendation of Microsoft, as you might have lost this application out of sight in 24 months, which is the maximum duration for a client secret.

Screenshot of creation of app secret

Now note down, what you see under value, you can only see it now.

Screenshot of app secret

With that last step, your Enterprise application has the right permissions on Azure Active Directory. In the next step you need to grant your enterprise Application the permission to write into the specific SharePoint site.

How to grant the App Registration Write Permissions for a Selected SharePoint Site?

In order to grant the app registration the permission, you need to ensure that PNP Module is installed on your client and that you are allowed to use it.

If you have not yet installed it, check the following documentation:

Connect to SharePoint with PowerShell | SharePoint Online (sposcripts.com)

If both conditions are applying, you can use this code to grant your App registration right permission to write in the site.

You can get your App ID by browsing to the overview page of your app registration.

Screenshot of Application (client) ID

Import-Module PnP.PowerShell

$AppID = "e0b8aefa-cb52-4bda-93a0-7d87120bcdbb"
$AppRegistrationName = "SP_Sites.Selected_SalesandMarketing"

$DisplayNameofSitePermission = "Enterprise Application $AppRegistrationName"
$SiteURL = "https://m365x323732.sharepoint.com/sites/SalesAndMarketing"


Connect-PnPOnline -Url $SiteURL -Interactive
Grant-PnPAzureADAppSitePermission -AppId $AppID -DisplayName $DisplayNameofSitePermission -Site $SiteURL -Permissions Write

You will be asked to authenticate.

Screenshot of authentication prompt

At the end, your app registration has write permissions.

Screenshot of App registration to write permissions to SharePoint Site

How to Upload Files to SharePoint using Graph API?

As we have created an app registration and gave it the permission to write to a selected site, we can use to upload files to SharePoint using Graph API. In my example, I want to upload a picture to the SharePoint Library Shared Documents. Make sure, that you have adjusted the parameters and have the client secret handy, which we have created in the previous steps.

When you run the code, you will be asked to provide the client secret for your app registration.

Screenshot of credential prompt
Param (
    $Tenant = "m365x323732",
    $AppID = "e0b8aefa-cb52-4bda-93a0-7d87120bcdbb",
    $SiteID = "e35cee33-6d10-4e2c-a83b-496a26062ad3",
    $LibraryURL = "https://m365x323732.sharepoint.com/sites/SalesAndMarketing/Shared%20Documents",
    $Path = "C:\Users\Serkar\Desktop\security.png"
)

$AppCredential = Get-Credential($AppID)

#region authorize
$Scope = "https://graph.microsoft.com/.default"

$Body = @{
    client_id = $AppCredential.UserName
    client_secret = $AppCredential.GetNetworkCredential().password
    scope = $Scope
    grant_type = 'client_credentials'
}

$GraphUrl = "https://login.microsoftonline.com/$($Tenant).onmicrosoft.com/oauth2/v2.0/token"
$AuthorizationRequest = Invoke-RestMethod -Uri $GraphUrl -Method "Post" -Body $Body
$Access_token = $AuthorizationRequest.Access_token

$Header = @{
    Authorization = $AuthorizationRequest.access_token
    "Content-Type"= "application/json"
}
#endregion

#region get drives


$GraphUrl = "https://graph.microsoft.com/v1.0/sites/$SiteID/drives"

$BodyJSON = $Body | ConvertTo-Json -Compress
$Result = Invoke-RestMethod -Uri $GraphUrl -Method 'GET' -Headers $Header -ContentType "application/json" 
$DriveID = $Result.value| Where-Object {$_.webURL -eq $LibraryURL } | Select-Object id -ExpandProperty id

If ($DriveID -eq $null){

    Throw "SharePoint Library under $LibraryURL could not be found."
}

#endregion

#region upload file

$FileName = $Path.Split("\")[-1]
$Url  = "https://graph.microsoft.com/v1.0/drives/$DriveID/items/root:/$($FileName):/content"

Invoke-RestMethod -Uri $Url -Headers $Header -Method Put -InFile $Path -ContentType 'multipart/form-data' -Verbose
#endregion 

At the end you will receive the following response as example

VERBOSE: PUT with -1-byte payload
VERBOSE: received -1-byte response of content type application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8


@odata.context               : https://graph.microsoft.com/v1.0/$metadata#drives('b%21M-5c4xBtLE6oO0lqJgYq04f6JqJ_iTlEhBdXmkuqxRI4cWqlVo8-QKlAJO6KoBgT')/items/$entity
@microsoft.graph.downloadUrl : https://m365x323732.sharepoint.com/sites/SalesAndMarketing/_layouts/15/download.aspx?UniqueId=9f900d6c-d023-41cc-8839-61f079916c03&Translate=fals
                               e&tempauth=eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJhdWQiOiIwMDAwMDAwMy0wMDAwLTBmZjEtY2UwMC0wMDAwMDAwMDAwMDAvbTM2NXgzMjM3MzIuc2hhcmVwb2ludC5jb21AOG
                               I5Y2ZmMzQtNjg4YS00YTkzLThhZDMtMjNjYTQ3ZWU2ZTcyIiwiaXNzIjoiMDAwMDAwMDMtMDAwMC0wZmYxLWNlMDAtMDAwMDAwMDAwMDAwIiwibmJmIjoiMTY3MjgyMjg4MSIsImV4cCI6IjE
                               2NzI4MjY0ODEiLCJlbmRwb2ludHVybCI6IjYrUUtpd1NldjBJdksyUFkwS2wyV0YveWNLSnYxQkdPc1RFb1pWclRyems9IiwiZW5kcG9pbnR1cmxMZW5ndGgiOiIxNDYiLCJpc2xvb3BiYWNr
                               IjoiVHJ1ZSIsImNpZCI6IlpUSTFaakE0WTJJdE5XUTRPUzAwTldRd0xXSmtPVEV0WlRnMFpEUmhZVFJrTW1VMyIsInZlciI6Imhhc2hlZHByb29mdG9rZW4iLCJzaXRlaWQiOiJaVE0xWTJWb
                               E16TXRObVF4TUMwMFpUSmpMV0U0TTJJdE5EazJZVEkyTURZeVlXUXoiLCJhcHBfZGlzcGxheW5hbWUiOiJTUF9TaXRlcy5TZWxlY3RlZF9TYWxlc2FuZE1hcmtldGluZyIsIm5hbWVpZCI6Im
                               UwYjhhZWZhLWNiNTItNGJkYS05M2EwLTdkODcxMjBiY2RiYkA4YjljZmYzNC02ODhhLTRhOTMtOGFkMy0yM2NhNDdlZTZlNzIiLCJyb2xlcyI6InNlbGVjdGVkc2l0ZXMiLCJ0dCI6IjEiLCJ
                               1c2VQZXJzaXN0ZW50Q29va2llIjpudWxsLCJpcGFkZHIiOiIyMC4xOTAuMTkwLjEwMSJ9.c0kydmY4eUFWS2lvWmJkTG1yTjJGbmV0SkVHVHRtdjNZWHppbm1SKytTRT0&ApiVersion=2.0
createdDateTime              : 2023-01-04T09:01:21Z
eTag                         : "{9F900D6C-D023-41CC-8839-61F079916C03},1"
id                           : 01P5GC6MTMBWIJ6I6QZRAYQOLB6B4ZC3AD
lastModifiedDateTime         : 2023-01-04T09:01:21Z
name                         : security.png
webUrl                       : https://m365x323732.sharepoint.com/sites/SalesAndMarketing/Shared%20Documents/security.png
cTag                         : "c:{9F900D6C-D023-41CC-8839-61F079916C03},2"
size                         : 129678
createdBy                    : @{application=; user=}
lastModifiedBy               : @{application=; user=}
parentReference              : @{driveType=documentLibrary; driveId=b!M-5c4xBtLE6oO0lqJgYq04f6JqJ_iTlEhBdXmkuqxRI4cWqlVo8-QKlAJO6KoBgT; id=01P5GC6MV6Y2GOVW7725BZO354PWSELRRZ; 
                               path=/drives/b!M-5c4xBtLE6oO0lqJgYq04f6JqJ_iTlEhBdXmkuqxRI4cWqlVo8-QKlAJO6KoBgT/root:}
file                         : @{mimeType=image/png; hashes=}
fileSystemInfo               : @{createdDateTime=2023-01-04T09:01:21Z; lastModifiedDateTime=2023-01-04T09:01:21Z}
image                        : 
shared                       : @{scope=users}


Screenshot of the response

As you can see, the file was uploaded successfully to the SharePoint Library

Screenshot of the uploaded files to SharePoint using Graph API
 Screenshot of the picture in the SharePoint Library

How to Upload Files to a Folder in SharePoint using Graph API?

In order to upload files to folders, you just need to make sure that your URI contains the folder structure after root:/.
In my example below, I uploaded apicture to the Subfolder folder.

$Url = "https://graph.microsoft.com/v1.0/drives/$DriveID/items/root:/General/Subfolder/$($FileName):/content"
Param (
    $Tenant = "m365x04995906",
    $AppID = "3669592a-9085-4f09-8c03-2b2223aa002c",
    $SiteID = "0a749590-8778-4779-808a-3bbb9bc1a5e1",
    $LibraryURL = "https://m365x04995906.sharepoint.com/sites/Remoteliving/Shared%20Documents",
    $Path = "C:\Users\Serka\OneDrive\Desktop\pngs\00003.jpg",
    $Folder = "General/Subfolder"
)

#$AppCredential = Get-Credential($AppID)

#region authorize
$Scope = "https://graph.microsoft.com/.default"

$Body = @{
    client_id = $AppCredential.UserName
    client_secret = $AppCredential.GetNetworkCredential().password
    scope = $Scope
    grant_type = 'client_credentials'
}

$GraphUrl = "https://login.microsoftonline.com/$($Tenant).onmicrosoft.com/oauth2/v2.0/token"
$AuthorizationRequest = Invoke-RestMethod -Uri $GraphUrl -Method "Post" -Body $Body
$Access_token = $AuthorizationRequest.Access_token

$Header = @{
    Authorization = $AuthorizationRequest.access_token
    "Content-Type"= "application/json"
}
#endregion

#region get drives


$GraphUrl = "https://graph.microsoft.com/v1.0/sites/$SiteID/drives"

$BodyJSON = $Body | ConvertTo-Json -Compress
$Result = Invoke-RestMethod -Uri $GraphUrl -Method 'GET' -Headers $Header -ContentType "application/json" 
$DriveID = $Result.value| Where-Object {$_.webURL -eq $LibraryURL } | Select-Object id -ExpandProperty id

If ($DriveID -eq $null){

    Throw "SharePoint Library under $LibraryURL could not be found."
}

#endregion

#region upload file

$FileName = $Path.Split("\")[-1]
$Url = "https://graph.microsoft.com/v1.0/drives/$DriveID/items/root:/$Folder/$($FileName):/content"

Invoke-RestMethod -Uri $Url -Headers $Header -Method Put -InFile $Path -ContentType 'multipart/form-data' -Verbose
#endregion 

Once executed, you’ll get back following response:

VERBOSE: HTTP/1.1 PUT with 232877-byte payload
VERBOSE: received -byte response of content type application/json
VERBOSE: Content encoding: utf-8

@odata.context               : https://graph.microsoft.com/v1.0/$metadata#drives('b%21kJV0CniHeUeAiju7m8Gl4ZmfCOoRAXJNrYB9wjbkfZ-Vmuw3EELGQ7bZlNIfSaf4')/items/$entity
@microsoft.graph.downloadUrl : https://m365x04995906.sharepoint.com/sites/Remoteliving/_layouts/15/download.aspx?UniqueId=2c3c2e98-5be4-4ce2-8a81-2c0d4bab00b4&Translate=false&tempauth=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiIwMDAwMDAwMy0wMDAwLTBmZjEtY2UwMC0wMDAwMDAwMDAwMDAvbTM2NXgwNDk5NTkwNi5zaGFyZXBvaW50LmNv 
                               bUAxZjc5NWU5NS1jMDZiLTQxMDktOTI0ZS0zNTY5ZmRkZjQ5OWYiLCJpc3MiOiIwMDAwMDAwMy0wMDAwLTBmZjEtY2UwMC0wMDAwMDAwMDAwMDAiLCJuYmYiOiIxNjk3NDQ0MDk5IiwiZXhwIjoiMTY5NzQ0NzY5OSIsImVuZHBvaW50dXJsIjoiWjA4ZkI5NTdNQklCckgzRUg4VHp1N0RuT3lTWVhCMHQ4VE5zZTNvNmMvMD0iLCJlbmRwb2ludHVybExlbmd0aCI6IjE0MyIsImlzbG 
                               9vcGJhY2siOiJUcnVlIiwiY2lkIjoiWktRTFZjNHhUMEt2RlF2YSsxMjZJZz09IiwidmVyIjoiaGFzaGVkcHJvb2Z0b2tlbiIsInNpdGVpZCI6Ik1HRTNORGsxT1RBdE9EYzNPQzAwTnpjNUxUZ3dPR0V0TTJKaVlqbGlZekZoTldVeCIsImFwcF9kaXNwbGF5bmFtZSI6IlNQU2l0ZXNfUmVhZFdyaXRlQWxsIiwibmFtZWlkIjoiMzY2OTU5MmEtOTA4NS00ZjA5LThjMDMtMmIyMjIz 
                               YWEwMDJjQDFmNzk1ZTk1LWMwNmItNDEwOS05MjRlLTM1NjlmZGRmNDk5ZiIsInJvbGVzIjoiYWxsc2l0ZXMud3JpdGUiLCJ0dCI6IjEiLCJpcGFkZHIiOiIyMC4xOTAuMTkwLjk5In0.2EMXEM184-nAFJnbOJy_PM8q5YKvOK66IoqggTX0g_E&ApiVersion=2.0
createdDateTime              : 16.10.2023 08:14:59
eTag                         : "{2C3C2E98-5BE4-4CE2-8A81-2C0D4BAB00B4},1"
id                           : 01NLC4VWMYFY6CZZC34JGIVAJMBVF2WAFU
lastModifiedDateTime         : 16.10.2023 08:14:59
name                         : 00003.jpg
webUrl                       : https://m365x04995906.sharepoint.com/sites/Remoteliving/Shared%20Documents/General/Subfolder/00003.jpg
cTag                         : "c:{2C3C2E98-5BE4-4CE2-8A81-2C0D4BAB00B4},2"
size                         : 232877
createdBy                    : @{application=; user=}
lastModifiedBy               : @{application=; user=}
parentReference              : @{driveType=documentLibrary; driveId=b!kJV0CniHeUeAiju7m8Gl4ZmfCOoRAXJNrYB9wjbkfZ-Vmuw3EELGQ7bZlNIfSaf4; id=01NLC4VWOFX4E7TTHLCNB256DE3BDS7OML; name=Subfolder; path=/drives/b!kJV0CniHeUeAiju7m8Gl4ZmfCOoRAXJNrYB9wjbkfZ-Vmuw3EELGQ7bZlNIfSaf4/root:/General/Subfolder;
                               siteId=0a749590-8778-4779-808a-3bbb9bc1a5e1}
file                         : @{mimeType=image/jpeg; hashes=}
fileSystemInfo               : @{createdDateTime=16.10.2023 08:14:59; lastModifiedDateTime=16.10.2023 08:14:59}
image                        : 
shared                       : @{scope=users}

Further Reference

You might be also interested in following articles, which are related to MS Graph API:

Security of app registration in Azure Active Directory | SPO Scripts

Create SharePoint list items using Graph API (PowerShell) (sposcripts.com)

How to get SharePoint List Items with Graph API (PowerShell) | SPO Scripts

2 thoughts on “How to upload files to SharePoint using Graph API (PowerShell)”

  1. Pingback: Upload documents to SharePoint with PowerShell solution

  2. Pingback: نحوه آپلود فایل ها در شیرپوینت با استفاده از Graph API (PowerShell) - word-amade

Leave a Comment