How to Upload Files to SharePoint Online Using Microsoft Graph API and PowerShell

Quick Answer: To upload files to SharePoint Online using PowerShell and Microsoft Graph API, create an Azure Entra App Registration with Sites.Selected application permissions, grant write access to your target site via Graph Explorer or PowerShell, generate a client secret, acquire an OAuth 2.0 token using Invoke-RestMethod, create an upload session at /sites/{siteId}/drives/{driveId}/root:/{folder}/{filename}:/createUploadSession, and PUT the file byte stream to the session URL.

If you’re managing files in SharePoint and want to automate uploads, you are in the right place. upload files to SharePoint Online with PowerShell, Whether you’re building automated scripts, scheduling reports, or handling migrations, using the Microsoft Graph API with PowerShell is one of the most flexible and modern ways to do this.

In this guide, I’ll walk you through a detailed, real-world way to upload files to a SharePoint document library securely using Graph API and a registered Azure AD app. This is something I use across many of my client projects and internal automation tasks.

What You’ll Need

Before we get started, make sure you have the following:

  • An active Microsoft 365 tenant

  • Global Admin or Application Admin rights in Azure AD

  • A SharePoint site where you want to upload the file

  • PowerShell with PnP.PowerShell module installed

Register an App in Azure AD

This section covers on how to Register Azure AD App for SharePoint Graph API Access; to interact with Graph API securely, we need to register an app in Azure AD:

  1. Go to Azure Portal

  2. Navigate to Azure Active Directory → App registrations → New registrationHow to Upload Files to SharePoint Online Using Microsoft Graph API and PowerShell - How To Upload Files To Sharepoint With Graph Api Using Powershell

  3. Name it something like Sharepoint_AT and Register itHow to Upload Files to SharePoint Online Using Microsoft Graph API and PowerShell - How To Upload Files To Sharepoint With Graph Api Using Powershell

  4. Once done, copy the Application (client) ID and Directory (tenant) ID, you’ll need both later.How to Upload Files to SharePoint Online Using Microsoft Graph API and PowerShell - How To Upload Files To Sharepoint With Graph Api Using Powershell

Assign Graph API Permissions

Now give the app the ability to talk to SharePoint:

  1. Under the same app, go to API permissions → Add a permissionHow to Upload Files to SharePoint Online Using Microsoft Graph API and PowerShell - How To Upload Files To Sharepoint With Graph Api Using Powershell

  2. Select Microsoft Graph → Application permissionsHow to Upload Files to SharePoint Online Using Microsoft Graph API and PowerShell - How To Upload Files To Sharepoint With Graph Api Using PowershellHow to Upload Files to SharePoint Online Using Microsoft Graph API and PowerShell - How To Upload Files To Sharepoint With Graph Api Using Powershell

  3. Search for Sites.ReadWrite.All and addHow to Upload Files to SharePoint Online Using Microsoft Graph API and PowerShell - How To Upload Files To Sharepoint With Graph Api Using Powershell

  4. Click Grant admin consent for your org

This permission ensures the app has access only to SharePoint sites you explicitly grant access to, ensuring least-privilege security.

Permission for specific site

Now to only add permission on a specific SharePoint site, proceed as below:

1. Go to API permissions and click on Add a permission

2. Select SharePoint

  How to Upload Files to SharePoint Online Using Microsoft Graph API and PowerShell - How To Upload Files To Sharepoint With Graph Api Using Powershell

 3. Now, select Application permissions

How to Upload Files to SharePoint Online Using Microsoft Graph API and PowerShell - AVvXsEi9XtKi2T1dEASdvRdmQJ58aRS3IFiDtVx5gyCLoUdd0JB6Ih NWzM5uWs9XvyrrU7ghuaw98MEE2KjzYQYIIC8er9SKgcM PL8vB3gjQxa3ckt8Hkeu4JiLONX Ps F970MDkiwxS2pZf0jXCshMOg JADAiEROHJacK8 S5Qc1S7uV1UwINOdIbO8PjI

 6. Check Sites.Selected , Sites.FullControl.All and click on Add Permission

 

How to Upload Files to SharePoint Online Using Microsoft Graph API and PowerShell - How To Upload Files To Sharepoint With Graph Api Using Powershell

7. Click on Grant admin consent and done

Granting SharePoint Site Access via Graph Explorer

Once you’ve added the sites.selected graph api permission to your app registration, the app doesn’t automatically get access to any SharePoint sites. You need to explicitly grant access to the specific site you want to work with.

Here’s how to do it using Microsoft Graph Explorer, step-by-step

Step-by-Step: Grant write Access to a Specific SharePoint Site

  1. Open Graph Explorer
  2. Now, We need the sharepointsiteid to apply the permission
  3.  In, Graph Explorer, select get SharePoint site based on relative path of the site under SharePoint sites optionHow to Upload Files to SharePoint Online Using Microsoft Graph API and PowerShell - How To Upload Files To Sharepoint With Graph Api Using Powershell
  4. In place of {host-name} provide your SharePoint domain address and in place of {server-relative-path} provide your site address like in the below. https://graph.microsoft.com/v1.0/sites/tenantname.sharepoint.com:/sites/yoursitename
  5. You can get the tenantname and sitename from your site like belowHow to Upload Files to SharePoint Online Using Microsoft Graph API and PowerShell - How To Upload Files To Sharepoint With Graph Api Using Powershell
  6. Now, use the info and run the query to get the SiteId like below. Copy the second full guid(blackBox) under ID     How to Upload Files to SharePoint Online Using Microsoft Graph API and PowerShell - How To Upload Files To Sharepoint With Graph Api Using Powershell
  7. Now, Change the HTTP method (top-left dropdown) to POST
  8. In the Request URL, paste the following (replace the placeholder with your SharePoint site ID:
  9. Click on Request Body, and paste this JSON (don’t forget to replace the values): https://graph.microsoft.com/v1.0/sites/<Your_SharePoint_Site_ID>/permissions

{   “roles”: [“write”],   “grantedToIdentities”: [{     “application”: {       “id”: “azure app id”,       “displayName”: “azure app displayname”     }   }] }

Boom, now all completed so we can use PowerShell script to Automate the file upload to SharePoint

How to Upload Files to SharePoint Online Using Microsoft Graph API and PowerShell - How To Upload Files To Sharepoint With Graph Api Using Powershell

Generate a Client Secret

If you want to use a secret proceed as below:

1. Go to Azure portal

2. Go to your Azure app which you created

3. Click on Certificates & secrets

How to Upload Files to SharePoint Online Using Microsoft Graph API and PowerShell - AVvXsEitSz1DnnujwUJLb7V KyF8yt3ssbCxHEkPGwfgxMq0Aj MpzLOUgxUupDiWKbrTY6WqbaUL3QPcZTYmd3lYPl8gRCKJzl5BsavBd4MTnwk DPZ3A5PbK76EBgjdZ81Jz7NIn5GQT Pm4sj72nvw0E2ZSiry8T5c XhrvSqREIi4uSD7fbDAqwv0SbCIq4=w262 H177

4. Click on New client secret

How to Upload Files to SharePoint Online Using Microsoft Graph API and PowerShell - AVvXsEiHM242wrNBdw6ILdHlZLRzoKdKZR An3IMlwqr9jzBQvAjiPYHF3T64U53OTxs7O1mCa3sbSO M8na40i5FcpSJTTBlQhRWl6UalnUz4wy52nnhpQFpfwfepRlnwLgLCgGBHrGuD07K0JXJS9r9RDdznM OHB4CS3FEV9EWeyITBTJ9Vo5GFmyHlETWRU

5. Create your secret and save it securely

Upload content to SharePoint using GraphAPI PowerShell

To connect to your SharePoint site using the Azure AD application and upload files securely with Microsoft Graph API, you’ll need the following:

  • The SharePoint site URL (where the file will be uploaded)

  • The Azure app Client ID (from App Registration)

  • The Azure app secret (or certificate thumbprint if you’re using a cert-based auth)

  • The file path to the document you want to upload

  • Here’s the PowerShell script that makes it all work: This script works for uploading all the files which are under the folder. Also, The script will check if the files re already uploaded then it will skip it! 

    This is the main part: uploading a file using Graph API.

POWERSHELL • Upload-FilesToSharePoint.ps1

Param (
    $Tenant                  = "your-tenant-name",
    $ClientID                = "your-app-client-id",
    $Secret                  = "your-client-secret",
    $SharePoint_SiteID       = "your-site-id",
    $SharePoint_Path         = "https://yourtenant.sharepoint.com/sites/YourSite/Shared%20Documents",
    $SharePoint_ExportFolder = "Uploads",
    $LocalFolder             = "$env:USERPROFILE\OneDrive - CompanyRecordings"
)

Function Write_Log {
    param($Message_Type, $Message)
    $MyDate = "[{0:MM/dd/yy} {0:HH:mm:ss}]" -f (Get-Date)
    Write-Host "$MyDate - $Message_Type : $Message"
}

# 1. Authenticate to Microsoft Graph via OAuth 2.0
$Body = @{
    client_id     = $ClientID
    client_secret = $Secret
    scope         = "https://graph.microsoft.com/.default"
    grant_type    = 'client_credentials'
}

Write_Log INFO "Connecting to Microsoft Graph API..."
$Graph_Url = "https://login.microsoftonline.com/$Tenant.onmicrosoft.com/oauth2/v2.0/token"

Try {
    $AuthorizationRequest = Invoke-RestMethod -Uri $Graph_Url -Method Post -Body $Body
    Write_Log SUCCESS "Connected to Microsoft Graph successfully."
} Catch {
    Write_Log ERROR "Authentication to SharePoint failed: $_"
    Exit 1
}

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

# 2. Locate the SharePoint Document Library Drive ID
$SharePoint_Graph_URL = "https://graph.microsoft.com/v1.0/sites/$SharePoint_SiteID/drives"
Write_Log INFO "Retrieving SharePoint drive information..."

Try {
    $Result = Invoke-RestMethod -Uri $SharePoint_Graph_URL -Method GET -Headers $Header
    Write_Log SUCCESS "Retrieved SharePoint site and drive info."
} Catch {
    Write_Log ERROR "Failed to retrieve SharePoint drives: $_"
    Exit 1
}

$DriveID = $Result.value | Where-Object { $_.webURL -eq $SharePoint_Path } | Select-Object -ExpandProperty id

# 3. Enumerate Local Files and Upload to SharePoint
$files = Get-ChildItem -Path $LocalFolder -File
Write_Log INFO "Found $($files.Count) files in '$LocalFolder'"

foreach ($f in $files) {
    $File_Path = $f.FullName
    $FileName  = $f.Name

    Write_Log INFO "Checking: $FileName"

    # Check if file already exists
    $checkUrl = "https://graph.microsoft.com/v1.0/sites/${SharePoint_SiteID}/drives/${DriveID}/root:/${SharePoint_ExportFolder}/${FileName}"
    try {
        Invoke-RestMethod -Uri $checkUrl -Method GET -Headers $Header -ErrorAction Stop
        Write_Log INFO "Skipping '$FileName' - already uploaded."
        continue
    } catch {
        # 404 indicates file does not exist, proceed with upload
        if ($_.Exception.Response.StatusCode.Value__ -ne 404) {
            Write_Log ERROR "Error verifying '$FileName': $_"
            continue
        }
    }

    Write_Log INFO "Creating upload session for: $FileName"
    $createUploadSessionUri = "https://graph.microsoft.com/v1.0/sites/${SharePoint_SiteID}/drives/${DriveID}/root:/${SharePoint_ExportFolder}/${FileName}:/createUploadSession"
    Try {
        $uploadSession = Invoke-RestMethod -Uri $createUploadSessionUri -Method POST -Headers $Header -ContentType "application/json"
        Write_Log SUCCESS "Upload session created for $FileName"
    } Catch {
        Write_Log ERROR "Failed to create upload session for $FileName: $_"
        continue
    }

    # Read file bytes and stream to upload session
    $fileInBytes = [System.IO.File]::ReadAllBytes($File_Path)
    $fileLength  = $fileInBytes.Length
    $headers = @{
        'Content-Range' = "bytes 0-$($fileLength-1)/$fileLength"
    }

    Write_Log INFO "Uploading $FileName ($([math]::Round($fileLength / 1MB, 2)) MB)..."
    Try {
        Invoke-RestMethod -Method Put -Uri $uploadSession.uploadUrl -Body $fileInBytes -Headers $headers
        Write_Log SUCCESS "Successfully uploaded $FileName"
    } Catch {
        Write_Log ERROR "Failed to upload $FileName: $_"
    }
}

Write_Log SUCCESS "All file uploads completed."

Next Steps in Production

This method is incredibly powerful and secure when you’re working across different tenants or automating data flows into SharePoint.

A few closing thoughts:

  • Rotate secrets regularly and use Azure Key Vault for storing secrets securely

  • You can easily convert this to use certificates instead of secrets for extra security

  • Always test with test data before touching production libraries

🛡️ Bonus Tip: Automate Microsoft Teams Recordings to SharePoint

If you’re using Microsoft Teams for meetings and recordings, one common problem is that those recordings expire or get deleted after a certain retention period. By combining Graph API with PowerShell or Logic Apps, you can automatically move or copy Teams recordings to a dedicated SharePoint document library.

This not only prevents accidental deletion but also ensures that all recordings are retained for compliance, training, or auditing purposes. If you’d like a step-by-step guide on that, let me know and I’ll publish a full blog soon!

Looking for an end-to-end practical implementation? Check out our complete playbook on Automating File Inventory Scanning and Uploading to SharePoint Using PowerShell and Intune.

If you want help building reusable modules or Logic Apps around this, connect with us on me a line on TechEuc.com or if you are facing any issues, you can comment or would need this implemented then you can check out my freelance profile too.

This method is incredibly powerful and secure when you’re working across different tenants or automating data flows into SharePoint.

A few closing thoughts:

  • Rotate secrets regularly and use Azure Key Vault for storing secrets securely

  • You can easily convert this to use certificates instead of secrets for extra security

  • Always test with test data before touching production libraries

Looking for an end-to-end practical implementation? Check out our complete playbook on Automating File Inventory Scanning and Uploading to SharePoint Using PowerShell and Intune.

If you want help building reusable modules or Logic Apps around this, connect with us on me a line on TechEuc.com 

TechEUC - Atoofa Shaikh
FIVERR PRO VERIFIED 12+ YRS EXPERIENCE

Atoofa Shaikh

Senior Microsoft 365, EUC & Cloud Endpoint Architect

Need custom Win32 App Packaging, PowerShell Automation, Zero-Touch Intune Autopilot, or SCCM Co-Management for your enterprise or MSP? I specialize in production-grade deployment architectures with zero downtime.