How to Upload Files to OneDrive via API: Simple PUT vs Upload Sessions
Uploading files to OneDrive through the Microsoft Graph API requires selecting between simple PUT requests and multi-part upload sessions. Small files under four megabytes can transfer in a single call, while larger files demand chunked byte ranges aligned to 320 KiB increments with automated retry logic.
How Microsoft Graph Structures OneDrive File Uploads
A naive file upload script pointed at Microsoft Graph works reliably during local testing with small sample documents, then fails without explanation the moment an automated pipeline sends a large payload. The failure rarely stems from authentication; it happens because Microsoft Graph splits file uploads across two incompatible API pathways with strict byte-alignment constraints.
The OneDrive upload API is a set of Microsoft Graph endpoints that allows programs to send files to OneDrive using simple PUT requests for small files or multi-part upload sessions for larger files. Microsoft structures cloud storage around two foundational resources: drive, representing a logical container such as a personal drive or a SharePoint document library, and driveItem, representing an individual file or directory.
Addressing these resources follows two distinct conventions:
- Unique identifier addressing:
/drives/{driveId}/items/{itemId}/contenttargets an existing item directly. - Path-based addressing:
/me/drive/root:/{path-to-file}:/contentaddresses an item by its human-readable directory hierarchy.
For enterprise environments running unattended automations or agent pipelines, your Microsoft Entra ID application registration requires specific permission scopes:
- Delegated access:
Files.ReadWriteprovides least-privileged read and write access on behalf of the signed-in user.Files.ReadWrite.Allbroadens this access across all drives the user can reach. - Application access:
Files.ReadWrite.Allallows background services and automated daemons to read and write files across all tenant drives without interactive user sign-in.
Understanding the architectural distinction between simple PUT and upload sessions determines whether your integration handles production workloads or encounters frequent connection failures. Simple PUT transmits the entire binary payload inside a single HTTP request body. An upload session creates an ephemeral staging allocation on Microsoft ingestion servers, generating a preauthenticated upload URL that accepts sequential byte ranges.
Related guides
- How to Download Files via OneDrive API: Microsoft Graph GuideDownloading a file via the OneDrive API requires requesting the binary stream from a driveItem content endpoint using...
- How to Upload Files to Dropbox via API: Simple vs Upload SessionsChoosing how to use the Dropbox API to upload file contents depends on asset size and network reliability. The Dropbox...
- How to Upload a Base64 String as a File to the Fastio APIAgents can upload a file as a Base64 string through the Fastio MCP upload_manage tool. Pass content_base64 on a...
- How to Manage Files with the Gemini APIGoogle's Gemini API offers powerful multimodal capabilities, allowing you to analyze images, audio, and video directly....
- How to List Files with OneDrive API: Graph Endpoints and Agent WorkspacesThe OneDrive API, integrated into Microsoft Graph, lists drive items using the /me/drive/root/children or...
- FastAPI Upload File Size Limits: Memory Spooling, Middleware, and Direct StorageFastAPI imposes no native file size limit, but Starlette spools multipart uploads in memory up to `1,048,576 bytes`...
More on this subject: Agent File and Document Workflows (269 guides)
When to Use Simple PUT Uploads for Small Payloads
For lightweight documents, JSON configuration payloads, and small text logs, simple PUT requests provide a straightforward ingestion route. The client issues a single HTTP PUT request directly to the drive item content endpoint.
The endpoint for path-based creation in the signed-in user's drive is:
PUT https://graph.microsoft.com/v1.0/me/drive/root:/Documents/report.pdf:/content
Authorization: Bearer {token}
Content-Type: application/pdf
<binary file content>
When the transfer succeeds, Microsoft Graph returns an HTTP 201 Created status code for new files or HTTP 200 OK when updating an existing item. The response payload returns the complete driveItem resource containing unique item IDs, file size, web URLs, and cryptographic hashes such as SHA1 and QuickXorHash.
Production Constraints and Failure Modes
Microsoft Graph simple PUT content endpoint accepts file uploads up to 250 MB in a single call. However, relying on a single HTTP call for payloads exceeding four megabytes introduces severe reliability problems:
- Socket Drops and Lack of Resumability: Single PUT transfers cannot resume if interrupted. If a network dropout occurs midway through a monolithic transfer, the entire progress is discarded, forcing the client to retransmit from the beginning.
- Proxy and Gateway Timeouts: Enterprise reverse proxies, API gateways, and web application firewalls frequently enforce body size limits or terminate idle connections with
504 Gateway Timeoutor413 Request Entity Too Large. - Resource Locks: If an Office desktop application or concurrent process holds a write lease on the target file, Microsoft Graph returns
HTTP 423 Locked.
Python Implementation for Simple PUT Upload
The following script demonstrates uploading small files using Python and the requests library:
import os
import requests
def upload_small_file(access_token: str, local_path: str, remote_path: str) -> dict:
file_size = os.path.getsize(local_path)
if file_size > 4 * 1024 * 1024:
raise ValueError("Files 4 MB and larger should use createUploadSession instead.")
url = f"https://graph.microsoft.com/v1.0/me/drive/root:/{remote_path}:/content"
headers = {
"Authorization": f"Bearer {access_token}",
"Content-Type": "application/octet-stream"
}
with open(local_path, "rb") as f:
response = requests.put(url, headers=headers, data=f)
if response.status_code in (200, 201):
return response.json()
response.raise_for_status()
Steps to Execute Multi-Part Upload Sessions for Large Datasets
When transferring large files, multi-part upload sessions provide fault-tolerant chunking. Instead of sending one massive payload, the client creates a temporary upload session and streams the file in smaller byte fragments.
Step-by-Step Workflow Outline
Initiating and completing a OneDrive upload session follows a six-step lifecycle:
- Create the session: Send a POST request to
createUploadSessionat the target item path. - Extract session metadata: Parse the returned
uploadUrlandexpirationDateTime. - Partition the file: Slice the local file into byte chunks that conform to Graph alignment rules.
- Upload byte ranges: Issue sequential PUT calls to the
uploadUrlwithContent-Rangeheaders. - Process intermediate responses: Confirm
HTTP 202 Acceptedafter each slice and verifynextExpectedRanges. - Finalize the transfer: Transmit the final byte slice, receiving
HTTP 201 CreatedorHTTP 200 OKwith the finisheddriveItem.
Creating the Upload Session
To begin, the application sends a POST request specifying conflict behavior:
POST https://graph.microsoft.com/v1.0/me/drive/root:/Archives/backup.zip:/createUploadSession
Authorization: Bearer {token}
Content-Type: application/json
{
"item": {
"@microsoft.graph.conflictBehavior": "replace",
"name": "backup.zip"
}
}
The @microsoft.graph.conflictBehavior property accepts three options: fail (the default, which halts the request if a file with that name already exists), replace (which overwrites the existing item and updates its version history), or rename (which appends an incremented number to the file name).
Microsoft Graph responds with HTTP 200 OK containing the temporary session details:
{
"uploadUrl": "https://sn3302.up.1drv.com/up/fe6987415ace7X4e1eF866337",
"expirationDateTime": "2026-10-05T09:21:55.523Z"
}
Two critical rules govern this uploadUrl:
- Preauthentication: The URL contains an embedded authorization signature. Do not send the standard
Authorization: Bearerheader during chunk PUT calls; passing token headers to the upload URL can causeHTTP 401 Unauthorizedresponses. - Expiration: Sessions remain valid for a finite window, typically 24 hours. Each successfully accepted fragment extends the expiration timestamp.
Connect OneDrive Storage to Agent Workspaces
Sync your existing OneDrive directories into a Fastio workspace on a schedule or on demand, giving your AI agents indexed semantic search over remote files without local chunking. Starts with a 30-day free trial.
Why the 320 KiB Alignment Rule Governs Byte Ranges
The single most common defect in custom OneDrive upload implementations is ignoring chunk alignment requirements. While general HTTP chunked uploads permit arbitrary partition sizes, Microsoft Graph enforces a strict mathematical rule on byte ranges.
The 320 KiB Requirement
Microsoft Graph upload sessions require fragment sizes to be multiples of 320 KiB. Specifically, 320 KiB corresponds to exactly 327,680 bytes. Every byte fragment uploaded to the session URL must contain a length that divides evenly by 327,680, with exactly one exception: the final fragment representing the end of the file.
Why does Microsoft enforce this constraint? Microsoft Graph routes upload streams directly into Azure storage backend blocks. These storage nodes process block allocations structured in 320 KiB increments. If a client transmits an unaligned middle slice (for example, a 500,000-byte chunk), the ingestion cluster accepts the intermediate chunk with a 202 Accepted status, but the final commit fails with 400 Bad Request or causes silent file corruption.
Valid Chunk Multiples
When designing your chunking logic, select a multiple of 320 KiB based on network throughput and stability:
- 1 multiple:
320 KiB(327,680 bytes), useful for unstable links. - 10 multiples:
3,200 KiB(3,276,800 bytes, approximately 3.125 MiB). - 32 multiples:
10,240 KiB(10,485,760 bytes, exactly 10 MiB), which Microsoft recommends as the optimal balance between request overhead and retry cost for high-speed connections. - Maximum slice size: Individual PUT requests to the upload session must remain under
60 MiB(62,914,560 bytes).
Constructing Content-Range Headers
HTTP byte ranges use zero-based inclusive index bounds: bytes START-END/TOTAL. For example, consider a file with a total length of 1,000,000 bytes uploaded in 327,680-byte slices:
- Slice 0: bytes 0 through 327,679 (
Content-Length: 327680,Content-Range: bytes 0-327679/1000000). - Slice 1: bytes 327,680 through 655,359 (
Content-Length: 327680,Content-Range: bytes 327680-655359/1000000). - Slice 2: bytes 655,360 through 983,039 (
Content-Length: 327680,Content-Range: bytes 655360-983039/1000000). - Slice 3 (final remainder): bytes 983,040 through 999,999 (
Content-Length: 16960,Content-Range: bytes 983040-999999/1000000).
Notice that the final slice is only 16,960 bytes. Because it terminates at the total file boundary (byte index 999,999 of 1,000,000 bytes), Microsoft Graph accepts the non-aligned remainder.
How to Handle Session Recovery, Network Drops, and Retries
Production file transfers must survive network drops, server throttling, and process interruptions. The strength of upload sessions lies in their resumability. When a transfer encounters an unexpected error, your client does not need to restart from scratch.
Querying Session Status
If a socket disconnects mid-upload, the client may be uncertain which bytes the server committed. To inspect session state, issue a GET request to the uploadUrl with no request body and no authorization header:
GET https://sn3302.up.1drv.com/up/fe6987415ace7X4e1eF866337
The server returns HTTP 200 OK with the current session state:
{
"expirationDateTime": "2026-10-05T09:21:55.523Z",
"nextExpectedRanges": ["655360-"]
}
The nextExpectedRanges array indicates the starting byte index expected by the server. In this example, the server has received all bytes up through 655,359, allowing the client to resume transmission directly at byte 655,360.
Handling HTTP Response Status Codes
An automated client must handle several specific status codes:
HTTP 202 Accepted: The byte fragment was saved successfully. The response body includes an updatedexpirationDateTimeand the next expected byte range.HTTP 201 CreatedorHTTP 200 OK: Returned when the final byte slice completes the file. The response contains the completeddriveItem.HTTP 416 Requested Range Not Satisfiable: The transmitted byte range was rejected, typically because the server already holds those bytes or received slices out of order. Query the session status to re-align your file pointer.HTTP 404 Not Found: The upload session expired, was cleaned up, or was deleted. The client must start a brand-new upload session from byte zero.HTTP 409 Conflict: If an item with the same name was created during the upload window, the final commit fails. Resolve this by issuing a PUT commit request with@microsoft.graph.conflictBehaviorset torenameor specifying@microsoft.graph.sourceUrl.HTTP 429 Too Many Requestsand5xx Server Errors: When Microsoft Graph encounters throttling or temporary server faults (500 Internal Server Error,502 Bad Gateway,503 Service Unavailable,504 Gateway Timeout), apply exponential backoff. Inspect theRetry-Afterresponse header if present, or wait with jittered intervals before retrying the failed fragment.
Canceling an Incomplete Session
If a user aborts an upload, or an unrecoverable local error occurs, clean up server storage by sending a DELETE request to the uploadUrl:
DELETE https://sn3302.up.1drv.com/up/fe6987415ace7X4e1eF866337
Microsoft Graph returns HTTP 204 No Content and purges the temporary byte buffers immediately.
Resilient Chunked Upload Implementation
The following Python script implements 320 KiB chunk alignment, status inspection, and automated retries:
import os
import time
import requests
CHUNK_SIZE = 10 * 320 * 1024 # 3,276,800 bytes (10 multiples of 320 KiB)
def upload_large_file(upload_url: str, file_path: str, max_retries: int = 5) -> dict:
total_size = os.path.getsize(file_path)
with open(file_path, "rb") as f:
start_byte = 0
while start_byte < total_size:
end_byte = min(start_byte + CHUNK_SIZE, total_size) - 1
chunk_length = end_byte - start_byte + 1
f.seek(start_byte)
chunk_data = f.read(chunk_length)
headers = {
"Content-Length": str(chunk_length),
"Content-Range": f"bytes {start_byte}-{end_byte}/{total_size}"
}
retries = 0
while retries < max_retries:
try:
response = requests.put(upload_url, headers=headers, data=chunk_data, timeout=60)
if response.status_code in (200, 201):
return response.json()
elif response.status_code == 202:
start_byte = end_byte + 1
break
elif response.status_code == 416:
status_res = requests.get(upload_url)
if status_res.status_code == 200:
next_range = status_res.json().get("nextExpectedRanges", ["0-"])[0]
start_byte = int(next_range.split("-")[0])
break
raise RuntimeError("Failed to resynchronize upload session state.")
elif response.status_code in (429, 500, 502, 503, 504):
retry_after = int(response.headers.get("Retry-After", 2 ** retries))
time.sleep(retry_after)
retries += 1
else:
response.raise_for_status()
except (requests.RequestException, IOError) as exc:
retries += 1
if retries >= max_retries:
raise RuntimeError(f"Upload failed after {max_retries} attempts.") from exc
time.sleep(2 ** retries)
raise RuntimeError("Upload completed loop without receiving completion response.")
How Intelligent Workspaces Connect OneDrive Storage to AI Agents
Autonomous AI agents, coding assistants, and operational pipelines such as Claude Code, Cursor, and Codex increasingly depend on enterprise knowledge stored in Microsoft OneDrive and SharePoint. However, connecting AI agents directly to raw Microsoft Graph upload and download endpoints creates substantial architecture overhead.
The Cost of Raw API Integrations in Agent Loops
When an agent interacts directly with Microsoft Graph, it must maintain refresh tokens, traverse complex directory trees, partition outgoing files into 320 KiB chunks, and repeatedly download multi-megabyte source files into prompt context. This consumes thousands of tokens, introduces latency into agent execution loops, and exposes workflows to Graph rate limiting.
The Fastio Workspace Architecture
The Fastio path eliminates this overhead while preserving your team's existing cloud storage:
- Retain existing storage: Your organization keeps its files in Microsoft OneDrive or SharePoint document libraries.
- Cloud sync into workspaces: Folders sync into a Fast.io workspace (one-way or two-way, on a schedule or on demand; never continuous, live, or real-time).
- Connect agents via remote MCP: The agent connects to the Fast.io Model Context Protocol server over Streamable HTTP at
https://mcp.fast.io/mcp/codefor coding agents (orhttps://mcp.fast.io/mcp/toolsfor general MCP clients), signing in with OAuth in the browser or sending anAuthorization: Bearer <api key>header on the connection for headless pipelines, with setup instructions at Fast.io MCP documentation, agent instructions athttps://mcp.fast.io/skill.md, and the agent onboarding reference. - Search indexed knowledge: Rather than pulling entire folders across Microsoft Graph, agents query files through Fast.io AI Intelligence Mode, which indexes documents for hybrid search combining full-text search and semantic vector embeddings. Agents retrieve relevant excerpts with exact citations.
In cross-provider connector benchmarks published at Fast.io connector benchmarks, Fastio was measured the fastest and the lowest cost of the providers tested.
When agents generate deliverables, reports, or updated codebases, they write directly into shared workspaces or branded shares configured for storage for agents. Per-file version history tracks every modification, and the append-only audit log records who edited what and when. Monthly plans start with a 30-day free trial on Fast.io pricing. Teams maintain centralized visibility over agent activity without managing low-level byte fragmentation or socket timeouts.
Sources
References used to verify factual claims in this guide.
-
Microsoft Graph upload sessions require fragment sizes to be multiples of 320 KiB.
-
Microsoft Graph simple PUT content endpoint accepts file uploads up to 250 MB in a single call.
Frequently Asked Questions
How do I upload a file to OneDrive using API?
Upload small files under four megabytes by issuing an HTTP PUT request with the binary payload directly to `/me/drive/root:/{path}:/content`. For files four megabytes and larger, send a POST request to `/me/drive/root:/{path}:/createUploadSession` to obtain a preauthenticated upload URL, then stream byte fragments sequentially in multiples of 320 KiB using HTTP PUT calls with Content-Range headers.
What is the file size limit for OneDrive simple upload API?
Microsoft Graph simple PUT content endpoint accepts file uploads up to 250 MB in a single call. However, production workflows should limit simple PUT requests to smaller payloads under four megabytes. Larger files lack pause and resume capabilities, making them vulnerable to network interruptions, reverse proxy timeouts, and socket drops.
How do I resume an interrupted OneDrive upload session?
Issue an HTTP GET request to the session upload URL without an authorization header. Microsoft Graph responds with HTTP 200 OK and a nextExpectedRanges array indicating the missing byte positions. Use the first range offset to seek your local file pointer and resume sequential chunk PUT requests.
Why must OneDrive upload session chunks be multiples of 320 KiB?
Microsoft Graph upload sessions require fragment sizes to be multiples of 320 KiB because backend Azure storage clusters allocate data in 320 KiB (327,680 bytes) blocks. Slices that do not divide evenly by 320 KiB cause commit errors or silent file corruption, except for the final remainder slice that terminates at the end of the file.
How long does a OneDrive upload session remain active before expiring?
Upload sessions typically remain active for 24 hours from creation. Every successfully accepted byte fragment extends the session expiration timestamp, which is returned in the expirationDateTime field of each HTTP 202 Accepted response. Inactive sessions are purged automatically.
Related Resources
Connect OneDrive Storage to Agent Workspaces
Sync your existing OneDrive directories into a Fastio workspace on a schedule or on demand, giving your AI agents indexed semantic search over remote files without local chunking. Starts with a 30-day free trial.