How to Upload Files to Dropbox via API: Simple vs Upload Sessions
Choosing how to use the Dropbox API to upload file contents depends on asset size and network reliability. The Dropbox file upload API provides two endpoints: /files/upload for single-request payloads under 150 MB and /files/upload_session for multi-chunk transfers up to 350 GB with resumable commit offsets. While simple uploads execute in a single HTTP call, larger assets require dividing payloads into discrete byte chunks, tracking sequential session offsets, and handling rate limits.
When to Choose Between Simple Uploads and Upload Sessions
Uploading a 200 MB dataset to Dropbox using a standard single-request endpoint immediately returns an HTTP 413 error because the platform strictly caps direct uploads at 150 MB. Shifting to multi-part upload sessions solves the payload limit but introduces stateful chunk management, byte offset tracking, and network retry logic.
The Dropbox file upload API provides two endpoints: /files/upload for single-request payloads under 150 MB and /files/upload_session for multi-chunk transfers up to 350 GB with resumable commit offsets. Choosing the right path depends on payload size, network reliability, and how the destination files are consumed by downstream applications.
When engineering ingestion pipelines, data connectors, or AI agent integrations, handling file transfers requires understanding the trade-offs between stateless calls and stateful sessions. A single-request upload sends the entire file body in one HTTP POST request. This approach is simple and fast for smaller files like log snippets, images, or configuration files, but it presents major failure modes over variable networks: if a network socket drops midway through a large direct upload, the client must retransmit the entire payload from byte zero.
Upload sessions decouple data transfer from file commitment. You initiate a session, push sequential byte ranges, and commit the file once all chunks arrive on Dropbox servers. This multi-step workflow prevents network timeouts, keeps client memory footprints small by streaming chunks, and provides resumability when connection drops interrupt data transmission.
Decision Matrix for Dropbox File Uploads
Use the following framework to select the appropriate endpoint and architecture for your data payloads:
For automated agents and production microservices, the choice is not merely an API concern. Uploading large files directly into storage creates local compute overhead, requires token management, and leaves downstream agents with raw unstructured blobs. Connecting existing storage to intelligent workspaces allows teams to keep Dropbox as their system of record while giving agents structured, searchable access.
Related guides
- Google Drive Resumable Upload: Architecture, Limits, and Workspace SolutionsGoogle Drive resumable upload is an HTTP protocol for transferring files larger than 5 MB in chunks, using a temporary...
- How to Download Files from Box via API: Endpoints, Tokens & LimitsDownloading files through the Box REST API requires requesting the GET /files/{file_id}/content endpoint and following...
- How to List Files with the Dropbox API: Pagination, Cursors, and Agent WorkspacesListing files through the Dropbox API requires managing cursor-based pagination across the /files/list_folder and...
- How to Download Files with Google Drive API: Media vs Export MethodsDownloading files through the Google Drive API requires using files.get with alt=media for binary files or files.export...
- 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`...
- How to List Files with Google Drive API: Pagination, Queries, and Agent WorkspacesListing files with the Google Drive API requires using the files.list method with structured query parameters, explicit...
More on this subject: Agent File and Document Workflows (269 guides)
How to Use the Dropbox API Upload File Endpoint for Small Payloads
The /2/files/upload endpoint (the primary dropbox files upload endpoint) handles files up to 150 MB in a single request. Because Dropbox uses a content endpoint (https://content.dropboxapi.com/2/files/upload), request metadata travels in an HTTP header while the file contents occupy the raw body.
Stateless HTTP Request Mechanics
Unlike standard JSON endpoints that accept JSON in the request body, Dropbox content upload endpoints require passing parameters inside the Dropbox-API-Arg header as serialized JSON. The request headers must include:
Authorization: Bearer <access_token>: OAuth 2.0 bearer token.Dropbox-API-Arg: JSON object containing file metadata fields.Content-Type: application/octet-stream: Declares the raw binary payload.
The Dropbox-API-Arg parameter supports key configuration fields:
path: The full destination path in Dropbox (for example,/reports/q3_summary.pdf).mode: Controls conflict behavior:add(creates file or fails on collision),overwrite(replaces existing file), orupdate(updates file matching a specific revision ID).autorename: Boolean. When true, Dropbox appends a numerical suffix if a collision occurs instead of failing.mute: Boolean. When true, prevents background sync notifications from chiming on connected desktop clients.strict_conflict: Boolean. When true, enforces strict conflict checking against existing paths.
Here is a minimal curl command executing a direct file upload:
curl -X POST https://content.dropboxapi.com/2/files/upload \
--header "Authorization: Bearer YOUR_ACCESS_TOKEN" \
--header "Dropbox-API-Arg: {\"path\": \"/backups/system_metrics.json\", \"mode\": \"overwrite\", \"autorename\": false, \"mute\": true}" \
--header "Content-Type: application/octet-stream" \
--data-binary "@system_metrics.json"
Upon success, Dropbox returns HTTP 200 OK with a JSON payload representing the file's metadata:
{
"name": "system_metrics.json",
"id": "id:a4ayc_80_OEAAAAAAAAAXw",
"client_modified": "2026-10-05T09:00:00Z",
"server_modified": "2026-10-05T09:00:02Z",
"rev": "015c71d2e1b8a900000001a",
"size": 482910,
"path_lower": "/backups/system_metrics.json",
"path_display": "/backups/system_metrics.json",
"content_hash": "2a8d6a8f130d9124458f2d59e392233959141f17540203f1917f86f7842600ff"
}
Python Implementation with Requests and the Dropbox SDK
Developers can implement this transfer either via direct HTTP requests using requests or via the official dropbox Python SDK.
pip install requests dropbox
import json
import requests
###
def upload_simple_http(
access_token: str,
local_path: str,
dropbox_path: str,
) -> dict:
"""Upload a file under 150 MB using raw HTTP requests against Dropbox."""
url = "https://content.dropboxapi.com/2/files/upload"
headers = {
"Authorization": f"Bearer {access_token}",
"Dropbox-API-Arg": json.dumps({
"path": dropbox_path,
"mode": "overwrite",
"autorename": False,
"mute": True,
}),
"Content-Type": "application/octet-stream",
}
### Read file bytes from local disk
with open(local_path, "rb") as f:
file_data = f.read()
response = requests.post(url, headers=headers, data=file_data, timeout=120)
response.raise_for_status()
return response.json()
Using the official Python SDK simplifies authentication and header formatting:
import dropbox
from dropbox.files import WriteMode
from dropbox.exceptions import ApiError
###
def upload_simple_sdk(
access_token: str,
local_path: str,
dropbox_path: str,
) -> dropbox.files.FileMetadata:
"""Upload a file under 150 MB using the official Dropbox Python SDK."""
dbx = dropbox.Dropbox(access_token)
### Read raw binary payload
with open(local_path, "rb") as f:
file_bytes = f.read()
try:
metadata = dbx.files_upload(
file_bytes,
dropbox_path,
mode=WriteMode.overwrite,
mute=True,
)
return metadata
except ApiError as err:
print(f"Dropbox API upload error: {err}")
raise
Attempting to upload files larger than the 150 MB maximum payload limit through direct Dropbox calls results in an error, requiring an upload session. For production pipelines, any file approaching double-digit megabytes benefits from chunked upload sessions to mitigate connection instability.
Building Resumable Transfers with the Dropbox Upload File Python API
When handling large datasets, video files, disk images, or database dumps, single-call uploads become unreliable. The dropbox api resumable upload protocol solves this by partitioning files into a sequence of chunks managed under an upload session. Using the dropbox upload file python api pattern allows engineering teams to stream multi-gigabyte payloads while keeping memory consumption bounded.
The Three-Step Upload Session Protocol
A Dropbox upload session operates across three distinct stages:
- Start the Session (
/2/files/upload_session/start): The client sends the initial chunk of binary data (or an empty body). The endpoint generates and returns a uniquesession_id. Ifcloseis set tofalse, the session remains open for subsequent chunks. - Append Subsequent Chunks (
/2/files/upload_session/append_v2): The client streams intermediate chunks to the server. Each append request requires anUploadSessionCursorcontaining thesession_idand the exact integeroffsetrepresenting the total cumulative bytes uploaded to that point. The server verifies that the incoming chunk starts exactly at this byte offset. - Finish and Commit the File (
/2/files/upload_session/finish): The client sends the final chunk along with both the final cursor offset and aCommitInfoobject defining the destination path and write mode. Once processed, Dropbox writes the file into storage and returns the permanentFileMetadata.
Upload sessions are valid for 7 days from creation, allowing long-running background workers to pause and resume uploads across system restarts.
Complete Python Implementation for Chunked Uploads
The following production script implements a complete chunked uploader using the official Dropbox Python SDK. It inspects local file size, routes small files through the simple endpoint, and streams larger files in discrete chunks through upload sessions:
import os
import dropbox
from dropbox.files import CommitInfo, UploadSessionCursor, WriteMode
from dropbox.exceptions import ApiError
###
### Configure 8 MB chunk size and 150 MB partitioning boundary
CHUNK_SIZE = 8 * 1024 * 1024
MAX_SIMPLE_UPLOAD_SIZE = 150 * 1024 * 1024
###
def upload_file_resumable(
access_token: str,
local_path: str,
dropbox_path: str,
) -> dropbox.files.FileMetadata:
"""Upload files to Dropbox using simple upload or resumable upload sessions."""
dbx = dropbox.Dropbox(access_token)
file_size = os.path.getsize(local_path)
###
with open(local_path, "rb") as f:
### Route small files through single-call upload
if file_size <= MAX_SIMPLE_UPLOAD_SIZE:
print(f"Uploading {local_path} ({file_size} bytes) via simple upload...")
return dbx.files_upload(
f.read(),
dropbox_path,
mode=WriteMode.overwrite,
mute=True,
)
###
print(f"Uploading {local_path} ({file_size} bytes) via upload session...")
###
### Step 1: Start upload session with first chunk
first_chunk = f.read(CHUNK_SIZE)
session_start = dbx.files_upload_session_start(first_chunk)
session_id = session_start.session_id
###
cursor = UploadSessionCursor(session_id=session_id, offset=f.tell())
commit = CommitInfo(
path=dropbox_path,
mode=WriteMode.overwrite,
mute=True,
)
###
### Step 2: Append subsequent chunks
while f.tell() < file_size:
bytes_remaining = file_size - f.tell()
if bytes_remaining <= CHUNK_SIZE:
### Step 3: Finish upload session with the final chunk
final_chunk = f.read(bytes_remaining)
metadata = dbx.files_upload_session_finish(
final_chunk,
cursor,
commit,
)
print(f"Upload complete: {metadata.path_display}")
return metadata
else:
chunk = f.read(CHUNK_SIZE)
dbx.files_upload_session_append_v2(chunk, cursor)
cursor.offset = f.tell()
print(f"Uploaded chunk up to byte offset: {cursor.offset}/{file_size}")
###
raise RuntimeError("Unexpected failure during chunked file upload.")
This pattern streams chunks from disk without reading the entire file into system RAM. For large multi-gigabyte files, client memory usage remains bounded to the configured chunk size.
Managing Chunk Offsets, Rate Limits, and Retry-After Headers
Building reliable upload daemons requires accounting for two primary failure modes: network drops during chunk transmission and API throttling when multiple threads write concurrently.
Handling Incorrect Offset Errors and Network Interruption
In distributed networks, a client may send a chunk, and Dropbox may receive and append the bytes successfully, but the network connection drops before the client receives the HTTP 200 response. If the client retries with its previous offset, Dropbox rejects the request with an HTTP 409 Conflict status and an incorrect_offset error tag.
The error payload explicitly returns the server's current byte position in correct_offset:
{
"error_summary": "lookup_failed/incorrect_offset/...",
"error": {
".tag": "lookup_failed",
"lookup_failed": {
".tag": "incorrect_offset",
"correct_offset": 16777216
}
}
}
Rather than restarting the entire transfer from byte zero, your client must catch this exception, parse correct_offset, reposition the local file pointer using f.seek(correct_offset), update cursor.offset = correct_offset, and resume uploading from the new position:
import time
import dropbox
from dropbox.exceptions import ApiError
###
def append_chunk_with_offset_recovery(
dbx: dropbox.Dropbox,
file_handle,
cursor: dropbox.files.UploadSessionCursor,
chunk_size: int,
max_retries: int = 5,
):
"""Append a chunk with automatic offset recovery and network retries."""
for attempt in range(max_retries):
try:
data = file_handle.read(chunk_size)
dbx.files_upload_session_append_v2(data, cursor)
cursor.offset = file_handle.tell()
return
except ApiError as err:
### Inspect error union for incorrect_offset tag
if err.error.is_lookup_failed():
lookup_err = err.error.get_lookup_failed()
if lookup_err.is_incorrect_offset():
offset_err = lookup_err.get_incorrect_offset()
correct_offset = offset_err.correct_offset
print(f"Offset mismatch detected. Repositioning from {cursor.offset} to {correct_offset}")
file_handle.seek(correct_offset)
cursor.offset = correct_offset
continue
print(f"Transient error on attempt {attempt + 1}: {err}")
time.sleep(2 ** attempt)
###
raise RuntimeError("Exceeded maximum retries during chunk append.")
Handling HTTP 429 Rate Limits and Lock Contention
Dropbox enforces rate limits dynamically to protect platform stability. When an application issues requests too rapidly, or when multiple concurrent workers write to the same folder structure, Dropbox returns HTTP status 429 Too Many Requests.
Dropbox rate limits fall into two categories:
- Volume Limits: Triggered by exceeding request thresholds over a rolling window.
- Lock Contention: Triggered when multiple requests attempt to modify the same folder metadata concurrently. File commits serialize per parent folder; writing dozens of files simultaneously into one directory generates lock contention 429 errors.
When Dropbox responds with HTTP 429, it includes a Retry-After header indicating the number of seconds to wait before retrying. Production code must read this header and sleep accordingly. If the header is absent (common during lock contention), apply exponential backoff with randomized jitter:
import random
import time
import requests
###
def post_with_backoff(url: str, headers: dict, data: bytes, max_attempts: int = 6) -> requests.Response:
"""Execute an HTTP POST request with Retry-After and exponential backoff handling."""
for attempt in range(max_attempts):
response = requests.post(url, headers=headers, data=data, timeout=60)
###
if response.status_code == 429:
retry_after = response.headers.get("Retry-After")
if retry_after:
wait_seconds = float(retry_after)
else:
### Exponential backoff with randomized jitter
wait_seconds = (2 ** attempt) + random.uniform(0.1, 1.0)
###
print(f"Rate limited (HTTP 429). Retrying in {wait_seconds:.2f} seconds...")
time.sleep(wait_seconds)
continue
###
response.raise_for_status()
return response
###
raise RuntimeError("Failed after reaching maximum retry attempts.")
Connect Dropbox Storage to Your AI Workspaces
Sync Dropbox files into shared workspaces with automatic hybrid search and remote MCP tools. Monthly plans start with a 30-day free trial.
Connecting Dropbox to Fast.io Intelligent Workspaces via MCP
Building and maintaining custom upload pipelines, token refresh daemons, and chunk-offset repair scripts creates significant technical overhead. For teams deploying autonomous AI agents, writing custom upload scripts is often the wrong layer of abstraction.
The Operational Cost of Custom Storage Pipelines
Consider what an AI agent or data pipeline actually needs when interacting with files stored in Dropbox. An agent researching market trends, auditing contracts, or parsing engineering logs does not need to download large binary files to local disk, parse raw formats, and chunk text for vector databases. Downloading whole folders over the Dropbox API consumes network bandwidth, triggers HTTP 429 rate limits, and requires writing custom chunked upload daemons whenever the agent produces new deliverables.
Fast.io Cloud Sync and Remote MCP Integration
Fast.io provides an alternative architecture for agentic teams. Rather than replacing Dropbox, teams connect their existing Dropbox folders directly into a Fast.io workspace using Cloud Sync.
Cloud Sync runs one-way or two-way synchronization on a schedule or on demand (never continuous, live, or real-time). Your team retains Dropbox as the primary system of record, while files automatically populate the Fast.io workspace.
+-------------------------------------------------------+
| Dropbox Storage |
| (Team System of Record: Reports, PDFs, Datasets) |
+-------------------------------------------------------+
|
| Cloud Sync (Scheduled / On-Demand)
v
+-------------------------------------------------------+
| Fast.io Intelligent Workspace |
| - Auto-Indexed Hybrid Search (Semantic + Full-Text) |
| - Structured Metadata Views |
| - Per-File Version History & Append-Only Audit Log |
+-------------------------------------------------------+
|
| Streamable HTTP (/mcp)
v
+-------------------------------------------------------+
| Autonomous AI Agents & Scripts |
| - Claude Code, Codex, Cursor, Custom Python Agents |
| - Targeted Semantic Querying with Citations |
| - Direct Workspace File Reads & Writes via MCP |
+-------------------------------------------------------+
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.
AI agents connect to the workspace through the remote MCP server at https://mcp.fast.io/mcp/tools over Streamable HTTP. Using consolidated MCP tools, agents execute natural language queries against documents, retrieving exact textual excerpts and citations without downloading whole multi-gigabyte files. When agents produce finished documents, they write them directly into the workspace, where version history tracks every iteration.
Structured Extraction with Metadata Views
Beyond unstructured semantic search, enterprise workflows frequently require extracting structured data from incoming files. Fast.io provides Metadata Views to turn document collections into live, 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 and Performance
Every workspace provides granular permissions at the organization, workspace, folder, and file level, accompanied by per-file version history and an append-only audit log. When an agent finishes preparing files or configuring a workspace, ownership transfer allows the agent account to hand the organization over to human administrators while maintaining administrative access.
In evaluations published in the Fastio benchmark comparison, Fastio was measured the fastest and the lowest cost of the providers tested. (Every measured row in that evaluation was that provider's native connector in Claude Cowork; no row was a local stdio server, a Files-On-Demand stub or SharePoint, and SharePoint was not measured in that test).
Architecture Comparison: Direct API vs Workspace Sync
Use the direct Dropbox API when building low-level storage utilities, mobile file sync apps, or administrative scripts managing user folders.
Choose Fast.io Intelligent Workspaces when enabling AI agents to read, query, and collaborate on files stored in Dropbox. By letting Cloud Sync maintain alignment between Dropbox and Fast.io, you eliminate chunked upload maintenance, protect against rate limit exhaustion, and provide AI agents with immediate semantic search across your entire file corpus.
Sources
References used to verify factual claims in this guide.
-
Direct file uploads through the Dropbox API are limited to a maximum payload size of 150 MB before requiring an upload session. Upload session chunks require explicit byte offset verification to prevent corrupted commits if network interruptions occur.
Frequently Asked Questions
What is the maximum file size for the Dropbox upload API?
The maximum file size for the simple Dropbox upload API endpoint (/2/files/upload) is 150 MB. For files larger than 150 MB, the Dropbox API requires using upload sessions (/2/files/upload_session), which support files up to 350 GB when uploading via API chunks.
How do you upload large files to Dropbox in Python?
To upload large files to Dropbox in Python, use the official Dropbox SDK upload session workflow: call files_upload_session_start with the first chunk, append intermediate chunks sequentially with files_upload_session_append_v2 while tracking the byte offset, and commit the file using files_upload_session_finish with a CommitInfo object.
How do you handle Dropbox API rate limits during file uploads?
To handle Dropbox API rate limits (HTTP status 429), inspect the Retry-After response header and pause execution for the specified number of seconds before retrying. If the Retry-After header is absent, such as during folder lock contention, apply exponential backoff with randomized jitter across retries.
What causes the incorrect_offset error in Dropbox upload sessions?
An incorrect_offset error occurs when the byte offset provided in the UploadSessionCursor does not match the total bytes received by Dropbox. This happens when a previous chunk was processed successfully by the server but a network interruption prevented the client from receiving the HTTP 200 response. Clients should read the correct_offset field from the error and seek their local file pointer to that position.
What is the difference between Dropbox files/upload and files/upload_session?
The /2/files/upload endpoint is a single-call endpoint for payloads under the direct Dropbox upload 150 MB limit, where the entire file body travels in one request. The /2/files/upload_session endpoint is a 3-step stateful protocol that splits large files up to 350 GB into sequential chunks, offering resumability if network connections drop.
Can AI agents interact with Dropbox files without custom chunked upload scripts?
Yes. Teams can connect Dropbox folders directly into a Fast.io workspace using Cloud Sync, running one-way or two-way on a schedule or on demand. Documents are automatically indexed for hybrid semantic search upon arrival, allowing AI agents to query and retrieve excerpts over remote MCP without writing local chunked upload daemons.
Related Resources
Connect Dropbox Storage to Your AI Workspaces
Sync Dropbox files into shared workspaces with automatic hybrid search and remote MCP tools. Monthly plans start with a 30-day free trial.