AI & Agents

How to Upload Files to SharePoint via API: Graph vs REST Methods

Uploading files to SharePoint via API involves choosing between modern Microsoft Graph endpoints and legacy SharePoint REST methods. While single-call PUT requests handle files up to 250 MB, larger assets require resumable upload sessions with strict 320 KiB chunk alignment. This guide covers simple uploads, chunked transfer implementations, error recovery, and intelligent workspace sync for automated pipelines.

Tom Langridge 14 min read Updated
Uploading files to SharePoint requires choosing between Microsoft Graph, legacy REST methods, and workspace-level connectors.

When to Choose Microsoft Graph vs SharePoint REST for File Uploads

Uploading files to SharePoint via API creates an immediate operational split between lightweight single-request endpoints and stateful chunked upload sessions. If an automated script or agent pushes a 300 MB dataset using a standard HTTP PUT request against Microsoft Graph, the transfer fails immediately because single-call endpoints cap out at 250 MB. Conversely, shifting to chunked sessions requires implementing byte-range arithmetic, session persistence, and retry logic to survive transient network drops.

The SharePoint upload API consists of Microsoft Graph and SharePoint REST endpoints that allow applications to upload small binary files directly or stream large files via chunked upload sessions. Engineering teams building enterprise connectors, automated ingestion pipelines, and agent integrations encounter two distinct API surfaces across Microsoft 365: the modern Microsoft Graph REST API and the legacy SharePoint REST interface.

Microsoft Graph represents Microsoft's unified development surface (https://graph.microsoft.com/v1.0/). It accesses SharePoint document libraries through standardized /sites and /drives endpoints, relying on Microsoft Entra ID OAuth 2.0 bearer tokens. In contrast, the legacy SharePoint REST API (/_api/web/...) dates back to SharePoint 2013 and on-premises deployments. Legacy endpoints require managing SharePoint form digests (X-RequestDigest), navigating site-relative server paths, and interacting with legacy Client-Side Object Model (CSOM) methods.

Decision Framework for SharePoint File Uploads

Choosing the correct upload method depends on file size, network stability, and destination architecture:

File Size / Scenario Recommended Method API Endpoint Max Size Limit Protocol Mechanics
Small Files (< 4 MB) Simple PUT (Graph or REST) PUT .../content or POST .../Files/add 250 MB (Graph) / 2 MB (REST default) Single HTTP request, binary file payload in request body
Medium Files (4 MB - 250 MB) Graph Simple PUT or Upload Session PUT .../content or POST .../createUploadSession 250 MB Simple PUT works up to 250 MB; upload sessions add resumability
Large Files (250 MB - 250 GB) Microsoft Graph Upload Session POST .../createUploadSession -> PUT uploadUrl 250 GB Sliced byte ranges, multiples of 320 KiB, max 60 MiB per chunk
Legacy SharePoint On-Premises SharePoint REST Chunked Upload startupload -> continueupload -> finishupload 2 GB Sequential POST requests with unique GUID and integer byte offsets
AI Agent & Developer Workspaces Fastio Cloud Sync & Remote MCP Remote MCP (https://mcp.fast.io/mcp/tools) 100 GB (Enterprise) Automated workspace sync, hybrid search index, zero local chunk parsing

Modern development on SharePoint Online should standardize on Microsoft Graph. Graph provides unified authentication across Microsoft 365, consistent JSON error responses, higher default payload limits, and active engineering support. Legacy SharePoint REST remains necessary only when maintaining legacy on-premises SharePoint farms or executing legacy CSOM automations that depend on server-relative web contexts.

Audit overview and metadata indexing for SharePoint document synchronization

How to Upload Small Files Using Microsoft Graph and REST

For files under a few megabytes, single-call endpoints offer the simplest implementation. They transmit the entire binary payload in a single HTTP request without creating persistent session state on the server.

Microsoft Graph Simple PUT Upload

Microsoft Graph supports single-call PUT uploads up to 250 MB for SharePoint items. While the API accommodates files up to this ceiling, Microsoft documentation recommends using upload sessions for items larger than 10 MB to prevent socket timeouts on unstable connections.

To upload a new file, construct an HTTP PUT request targeting the target folder DriveItem using its path:

PUT https://graph.microsoft.com/v1.0/sites/{site-id}/drive/items/{parent-id}:/{filename}:/content
Authorization: Bearer {token}
Content-Type: application/octet-stream

<raw file binary bytes>

To implement this upload in Python using the requests library:

pip install requests
import requests

def upload_small_file_graph(
    access_token: str,
    site_id: str,
    parent_folder_id: str,
    file_path: str,
    target_filename: str,
) -> dict:
    """Upload a file under 250 MB to SharePoint in a single Graph API PUT call."""
    url = f"https://graph.microsoft.com/v1.0/sites/{site_id}/drive/items/{parent_folder_id}:/{target_filename}:/content"
    headers = {
        "Authorization": f"Bearer {access_token}",
        "Content-Type": "application/octet-stream",
    }
    with open(file_path, "rb") as f:
        file_bytes = f.read()
    response = requests.put(url, headers=headers, data=file_bytes, timeout=60)
    response.raise_for_status()
    return response.json()

If the file uploads successfully, Microsoft Graph returns HTTP 201 Created for new items or HTTP 200 OK when updating an existing file, accompanied by the DriveItem metadata record.

Legacy SharePoint REST Files/add Method

The legacy SharePoint REST API uploads small files by targeting the folder collection directly:

POST https://{tenant}.sharepoint.com/sites/{site}/_api/web/GetFolderByServerRelativeUrl('{folder_url}')/Files/add(url='{filename}',overwrite=true)
Authorization: Bearer {token}
Accept: application/json;odata=verbose
X-RequestDigest: {form_digest_value}
Content-Type: application/octet-stream

<raw file binary bytes>

Unlike Microsoft Graph, which validates identity entirely through the Entra ID bearer token, legacy SharePoint REST endpoints require a form digest value. The client must first execute a POST request to https://{tenant}.sharepoint.com/sites/{site}/_api/contextinfo to retrieve FormDigestValue before initiating the upload. Furthermore, while the theoretical request limit for Files/add is larger in modern SharePoint Online, sending large payloads in a single request frequently causes connection timeouts and gateway failures.

Steps to Upload Large Files with Microsoft Graph Resumable Sessions

When uploading large datasets, disk images, media archives, or CAD files to SharePoint, single-request uploads become fragile. A brief network interruption terminates the connection, discarding all transferred bytes. Microsoft Graph resolves this problem with resumable upload sessions.

The Three-Step Upload Session Architecture

A Graph upload session breaks file transmission into three distinct phases:

  1. Create the Upload Session: The client requests an upload session for the target item.
  2. Stream Chunks Sequentially: The client slices the file into ordered fragments and PUTs each chunk to a dedicated upload URL.
  3. Commit the File: Once the final byte range arrives, the storage engine commits the file and returns DriveItem metadata.

To create the upload session, issue a POST request to the DriveItem path:

POST https://graph.microsoft.com/v1.0/sites/{site-id}/drive/items/{parent-id}:/{filename}:/createUploadSession
Authorization: Bearer {token}
Content-Type: application/json

{
  "item": {
    "@microsoft.graph.conflictBehavior": "replace",
    "name": "quarterly_financials_archive.zip"
  }
}

The response returns an uploadUrl and an expirationDateTime (typically valid for 24 hours):

{
  "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#microsoft.graph.uploadSession",
  "uploadUrl": "https://sn3302.up.1drv.com/up/fe6987415ace7X4e1eF866337",
  "expirationDateTime": "2026-10-05T10:30:00.000Z",
  "nextExpectedRanges": ["0-"]
}

Chunk Slicing Rules and Alignment Requirements

Uploading large files in chunks via Microsoft Graph upload sessions requires byte ranges to be multiples of 320 KiB. Specifically, each fragment MUST be an exact multiple of 327,680 bytes (such as 3,276,800 bytes for 3.125 MiB, or 10,485,760 bytes for 10 MiB), with a maximum fragment size of 60 MiB. Using a fragment size that does not divide evenly by 320 KiB results in commit errors on the final request. The final fragment containing the remainder of the file does not need to be a multiple of 320 KiB.

Each chunk request requires two critical headers:

  • Content-Length: The exact number of bytes in the current request chunk.
  • Content-Range: The byte range represented by this chunk, formatted as bytes {start}-{end}/{total_file_size}.

Do not include the Authorization header when sending PUT requests to the uploadUrl. The uploadUrl is an authenticated temporary endpoint containing an embedded cryptographic signature. Sending an Authorization: Bearer header can trigger an HTTP 401 Unauthorized response from the storage endpoint.

Python Implementation for Graph Chunked Uploads

The following Python script reads a large local file, requests an upload session, slices the file into 3,276,800-byte chunks (exactly 10 multiples of 320 KiB), and streams the fragments sequentially:

import os
import requests

CHUNK_SIZE = 10 * 320 * 1024  ### 3,276,800 bytes (multiple of 320 KiB)

def create_graph_upload_session(
    token: str, site_id: str, parent_id: str, filename: str
) -> str:
    """Initiate an upload session and return the temporary uploadUrl."""
    url = f"https://graph.microsoft.com/v1.0/sites/{site_id}/drive/items/{parent_id}:/{filename}:/createUploadSession"
    headers = {
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/json",
    }
    payload = {
        "item": {
            "@microsoft.graph.conflictBehavior": "replace",
            "name": filename,
        }
    }
    resp = requests.post(url, headers=headers, json=payload, timeout=30)
    resp.raise_for_status()
    return resp.json()["uploadUrl"]

def upload_file_in_chunks(upload_url: str, file_path: str) -> dict:
    """Upload local file chunks sequentially to the Graph uploadUrl."""
    total_size = os.path.getsize(file_path)
    with open(file_path, "rb") as f:
        start_byte = 0
        while start_byte < total_size:
            chunk_data = f.read(CHUNK_SIZE)
            chunk_length = len(chunk_data)
            end_byte = start_byte + chunk_length - 1
            headers = {
                "Content-Length": str(chunk_length),
                "Content-Range": f"bytes {start_byte}-{end_byte}/{total_size}",
            }
            resp = requests.put(
                upload_url, headers=headers, data=chunk_data, timeout=60
            )
            ### Intermediate chunks return 202 Accepted
            if resp.status_code == 202:
                start_byte += chunk_length
                continue
            ### Final chunk returns 201 Created or 200 OK with DriveItem metadata
            if resp.status_code in (200, 201):
                return resp.json()
            resp.raise_for_status()
    raise RuntimeError("Upload finished without receiving DriveItem metadata")
Fastio features

Connect SharePoint Files to Your Agent Workspaces

Sync SharePoint document libraries into intelligent workspaces with hybrid search and remote MCP tools. Monthly plans start with a 14-day free trial.

How to Handle Errors and Resume Interrupted SharePoint Uploads

In production environments, network drops, socket timeouts, and transient cloud errors inevitably interrupt long-running file transfers. The primary gap in most SharePoint upload guides is omitting error recovery. Microsoft Graph upload sessions provide deterministic inspection and resumption mechanics.

Querying Upload Status and Resuming Transfers

If an upload request drops midway through a multi-gigabyte transfer, all bytes in that active request are discarded, but previously completed fragments remain stored on the server. To discover where the upload should resume, issue an HTTP GET request to the uploadUrl:

GET https://sn3302.up.1drv.com/up/fe6987415ace7X4e1eF866337

The server returns an HTTP 200 OK response with the remaining missing ranges:

{
  "expirationDateTime": "2026-10-05T10:30:00.000Z",
  "nextExpectedRanges": ["32768000-"]
}

The nextExpectedRanges property tells the client the exact starting byte offset. The client seeks to that offset in the local file and resumes streaming subsequent fragments.

Handling Common HTTP Error Codes

Production upload workers must handle standard HTTP failure modes:

  • HTTP 416 (Requested Range Not Satisfiable): Occurs when the client sends a byte range the server has already received. Issue a GET request to the uploadUrl to resynchronize the client byte pointer.
  • HTTP 409 (Conflict): Returned on the final chunk if a conflicting file was added to the directory during the upload window. The client can re-commit the session with an updated filename using @microsoft.graph.sourceUrl and @microsoft.graph.conflictBehavior: "rename".
  • HTTP 429 (Too Many Requests): Microsoft Graph enforces tenant-wide request throttling. When receiving HTTP 429, extract the Retry-After header value and pause execution for the specified duration before attempting retries.
  • HTTP 5xx Server Errors (500, 502, 503, 504): Transient gateway and server issues require exponential backoff with randomized jitter.
  • HTTP 404 (Not Found): Indicates that the upload session expired or was explicitly deleted. The client must abort and generate a new upload session from scratch.

Cancelling Abandoned Upload Sessions

When a user cancels an upload, or when a worker experiences an unrecoverable local exception, cancel the session to clean up temporary storage buffers on Microsoft servers:

DELETE https://sn3302.up.1drv.com/up/fe6987415ace7X4e1eF866337

The server cleans up all temporary data and responds with HTTP 204 No Content.

Legacy SharePoint REST Chunked Upload Architecture

Before Microsoft Graph, SharePoint REST handled large files through three sequential CSOM endpoints on the file object:

+-------------------------------------------------------------------------+
|                  Legacy SharePoint REST Chunk Workflow                  |
+-------------------------------------------------------------------------+
|  1. POST .../Files/add(url='file.bin', overwrite=true)                  |
|     (Create empty placeholder file record)                              |
|                                                                         |
|  2. POST .../startupload(uploadId=guid'{guid}')                         |
|     (Transmit chunk 1, initialize server-side buffer)                   |
|                                                                         |
|  3. POST .../continueupload(uploadId=guid'{guid}', fileOffset={offset}) |
|     (Transmit chunks 2 through N-1, tracking cumulative byte offset)    |
|                                                                         |
|  4. POST .../finishupload(uploadId=guid'{guid}', fileOffset={offset})   |
|     (Transmit final chunk, commit binary to library)                    |
+-------------------------------------------------------------------------+

Unlike Microsoft Graph, which tracks uploaded ranges internally on the server and exposes them via GET requests, legacy REST chunking requires the client to track exact cumulative integer byte offsets across calls. If the client offset drifts by even one byte, the server throws an SPBITSSessionIncompleteException or corrupts the binary. Furthermore, managing form digest token expiration during lengthy multi-gigabyte transfers introduces authentication failure points that Graph eliminates.

Why Intelligent Workspaces Eliminate Upload Pipeline Maintenance

Engineering teams frequently build custom SharePoint upload pipelines not because they want to manage file chunks, but because autonomous agents and analytical pipelines need access to corporate documents. Developing and maintaining custom upload daemons, managing token refreshes across long-running transfers, and handling throttling across enterprise document libraries creates significant infrastructure overhead.

The Workspace Synchronization Approach

Your team keeps their existing storage exactly where it already lives. Rather than writing custom chunked upload daemons to ingest files, you can synchronize designated SharePoint document libraries into a Fast.io workspace using Cloud Sync through the OneDrive connector. Cloud Sync operates one-way or two-way, on a recurring schedule or on demand. (Google Drive, Dropbox, Box, and OneDrive folders sync the same way, on a schedule or on demand).

+-------------------------------------------------------+
|                 Microsoft SharePoint                  |
|              (Authoritative File Store)               |
+---------------------------+---------------------------+
                            |
                            | Cloud Sync (Scheduled or On-Demand)
                            v
+-------------------------------------------------------+
|                   Fast.io Workspace                   |
|  - Automatic Semantic & Hybrid Search Indexing        |
|  - Metadata Views (Structured Schema Extraction)      |
|  - Per-File Version History & Detailed Activity Log   |
+---------------------------+---------------------------+
                            |
                            | Remote MCP (Streamable HTTP)
                            v
+-------------------------------------------------------+
|               Python AI Agent / Script                |
|  - Semantic Querying via MCP Tool Calls               |
|  - Exact Passage Retrieval with File Citations        |
|  - Zero Local Binary File Ingestion                   |
+-------------------------------------------------------+

Once files sync into a Fast.io workspace, Intelligence Mode auto-indexes every document upon arrival. The workspace builds a hybrid search index combining full-text keyword search, semantic search, and search-by-metadata-value filtering.

Autonomous AI agents and developer scripts connect through the remote MCP server (Claude apps and general MCP clients at https://mcp.fast.io/mcp/tools, coding agents such as Claude Code and Cursor at https://mcp.fast.io/mcp/code), querying specific concepts and retrieving targeted passages with document citations instead of downloading whole multi-gigabyte folders.

Structured Extraction with Metadata Views

Beyond semantic search, enterprise workflows often require extracting structured operational data from uploaded files. Fast.io provides Metadata Views to turn document collections into queryable tables.

Users describe fields in natural language, and AI designs a typed schema supporting Text, Integer, Decimal, Boolean, URL, JSON, and Date & Time formats. Metadata Views process PDFs, spreadsheets, presentations, and scanned forms without rigid OCR rules or templates. Agents can trigger extractions and query structured results directly via MCP tools.

Governance, Versioning, and Performance

In every workspace, access is granted per organization, workspace and share through member roles, accompanied by per-file version history and a detailed activity log. When an agent finishes preparing files or configuring a workspace, ownership transfer allows the agent account to hand the organization over to a person with a claim link.

Performance evaluations across cloud workspaces are published in the Fastio benchmark comparison.

Architecture Factor Direct Microsoft Graph Uploads Fast.io Workspace via Remote MCP
Primary Integration Point https://graph.microsoft.com/v1.0/ Remote MCP endpoint (https://mcp.fast.io/mcp/tools)
Authentication Flow Entra ID app registration with admin consent Browser OAuth or scoped API key
Large File Handling Manual chunk calculation in 320 KiB multiples Cloud Sync handles background ingestion
Search & Retrieval Keyword DriveItem queries and local downloads Auto-indexed hybrid search (semantic, text, metadata)
Structured Extraction Custom text extraction scripts and external DBs Native Metadata Views with typed schemas
Throttling Overhead Application handles HTTP 429 and Retry-After Hosted workspace search with zero Entra draw
Governance & Audit SharePoint Online audit log and M365 policies Detailed activity log and per-file version history

Strategic Implementation Recommendation

Standardize on the direct Microsoft Graph API when your application performs administrative site tasks, updates item permissions, creates document libraries, or executes low-frequency direct file transfers.

Adopt intelligent workspace synchronization via MCP when building agentic workflows, RAG applications, or automated data extraction pipelines. By allowing SharePoint to remain your team's system of record while connecting workspaces over MCP, you eliminate chunked upload maintenance, avoid Entra ID API quota exhaustion, and provide autonomous agents with immediate semantic search across enterprise files.

Sources

References used to verify factual claims in this guide.

  1. Microsoft Graph supports single-call PUT uploads up to 250 MB for SharePoint items.

  2. Uploading large files in chunks via Microsoft Graph upload sessions requires byte ranges to be multiples of 320 KiB.

Frequently Asked Questions

How do I upload a file to SharePoint using REST API?

To upload a file using the legacy SharePoint REST API, issue a POST request to https://{tenant}.sharepoint.com/sites/{site}/_api/web/GetFolderByServerRelativeUrl('{folder_path}')/Files/add(url='{filename}',overwrite=true). Include the file binary in the request body, set Content-Type to application/octet-stream, and provide an X-RequestDigest header obtained from /_api/contextinfo. For files larger than a few megabytes, use the startupload, continueupload, and finishupload chunked endpoints.

What is the maximum file size for SharePoint Graph API upload?

Microsoft Graph supports single-call PUT uploads up to 250 MB for SharePoint items. For files exceeding 250 MB, or for files where connection reliability is a concern, Microsoft Graph requires creating an upload session via createUploadSession to stream files to SharePoint in chunks.

How do I use an upload session in SharePoint?

To use an upload session in SharePoint via Microsoft Graph, send a POST request to /sites/{site-id}/drive/items/{parent-id}:/{filename}:/createUploadSession to obtain an uploadUrl. Then, upload chunks sequentially via Microsoft Graph upload session requests where byte ranges are exact multiples of 320 KiB and less than 60 MiB. Upload each chunk via an HTTP PUT request to the uploadUrl with Content-Range and Content-Length headers, omitting the Authorization header. The final chunk returns the completed DriveItem metadata.

Why does Microsoft Graph require chunk sizes in multiples of 320 KiB?

Microsoft Graph requires chunk byte ranges to be exact multiples of 320 KiB (327,680 bytes) because the underlying storage infrastructure processes fragmented byte streams in fixed-size blocks. If a non-final fragment is not divisible by 320 KiB, the storage service rejects the byte range or fails during the final commit.

What causes HTTP 401 Unauthorized errors when uploading chunks to uploadUrl?

An HTTP 401 Unauthorized error during chunk upload usually occurs when a client includes an Authorization header with an Entra ID bearer token in the PUT request to the uploadUrl. The uploadUrl already contains a pre-authenticated signed token; passing an additional Authorization header causes authentication validation conflicts.

Can AI agents access SharePoint documents without implementing upload sessions?

Yes. Rather than writing custom chunked upload daemons and local parsing logic, teams can synchronize SharePoint document libraries into a Fast.io workspace using Cloud Sync via the OneDrive connector. Files are automatically indexed upon arrival for hybrid semantic search, allowing AI agents to query content directly over remote MCP without downloading large binary files.

Related Resources

Fastio features

Connect SharePoint Files to Your Agent Workspaces

Sync SharePoint document libraries into intelligent workspaces with hybrid search and remote MCP tools. Monthly plans start with a 14-day free trial.