Dropbox
Access the Dropbox API with managed OAuth authentication. Manage files and folders, search content, retrieve metadata, and work with file revisions.
Quick Start
# List files in root folder
python <<'EOF'
import urllib.request, os, json
data = json.dumps({"path": ""}).encode()
req = urllib.request.Request('https://gateway.maton.ai/dropbox/2/files/list_folder', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Base URL
https://gateway.maton.ai/dropbox/2/{endpoint}
The gateway proxies requests to api.dropboxapi.com and automatically injects your OAuth token.
Important: Dropbox API v2 uses POST for all endpoints with JSON request bodies.
Authentication
All requests require the Maton API key in the Authorization header:
Authorization: Bearer $MATON_API_KEY
Environment Variable: Set your API key as MATON_API_KEY:
export MATON_API_KEY="YOUR_API_KEY"
Getting Your API Key
- Sign in or create an account at maton.ai
- Go to maton.ai/settings
- Copy your API key
Connection Management
Manage your Dropbox OAuth connections at https://ctrl.maton.ai.
List Connections
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.maton.ai/connections?app=dropbox&status=ACTIVE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Create Connection
python <<'EOF'
import urllib.request, os, json
data = json.dumps({'app': 'dropbox'}).encode()
req = urllib.request.Request('https://ctrl.maton.ai/connections', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Get Connection
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.maton.ai/connections/{connection_id}')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Response:
json
{
"connection": {
"connection_id": "1efbb655-88e9-4a23-ad3b-f3e19cbff279",
"status": "ACTIVE",
"creation_time": "2026-02-09T23:34:49.818074Z",
"last_updated_time": "2026-02-09T23:37:09.697559Z",
"url": "https://connect.maton.ai/?session_token=...",
"app": "dropbox",
"metadata": {}
}
}
Open the returned url in a browser to complete OAuth authorization.
Delete Connection
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.maton.ai/connections/{connection_id}', method='DELETE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Specifying Connection
If you have multiple Dropbox connections, specify which one to use with the Maton-Connection header:
python <<'EOF'
import urllib.request, os, json
data = json.dumps({"path": ""}).encode()
req = urllib.request.Request('https://gateway.maton.ai/dropbox/2/files/list_folder', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
req.add_header('Maton-Connection', '1efbb655-88e9-4a23-ad3b-f3e19cbff279')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
If omitted, the gateway uses the default (oldest) active connection.
API Reference
Users
Get Current Account
POST /dropbox/2/users/get_current_account
Content-Type: application/json
null
Response:
json
{
"account_id": "dbid:AAA-AdT84WzkyLw5s590DbYF1nGomiAoO8I",
"name": {
"given_name": "John",
"surname": "Doe",
"familiar_name": "John",
"display_name": "John Doe",
"abbreviated_name": "JD"
},
"email": "[email protected]",
"email_verified": true,
"disabled": false,
"country": "US",
"locale": "en",
"account_type": {
".tag": "basic"
},
"root_info": {
".tag": "user",
"root_namespace_id": "11989877987",
"home_namespace_id": "11989877987"
}
}
Get Space Usage
POST /dropbox/2/users/get_space_usage
Content-Type: application/json
null
Response:
json
{
"used": 538371,
"allocation": {
".tag": "individual",
"allocated": 2147483648
}
}
Files and Folders
List Folder
POST /dropbox/2/files/list_folder
Content-Type: application/json
{
"path": "",
"recursive": false,
"include_deleted": false,
"include_has_explicit_shared_members": false
}
Use empty string "" for the root folder.
Optional Parameters:
- recursive - Include contents of subdirectories (default: false)
- include_deleted - Include deleted files (default: false)
- include_media_info - Include media info for photos/videos
- limit - Maximum entries per response (1-2000)
Response:
json
{
"entries": [
{
".tag": "file",
"name": "document.pdf",
"path_lower": "/document.pdf",
"path_display": "/document.pdf",
"id": "id:Awe3Av8A8YYAAAAAAAAABQ",
"client_modified": "2026-02-09T19:58:12Z",
"server_modified": "2026-02-09T19:58:13Z",
"rev": "016311c063b4f8700000002caa704e3",
"size": 538371,
"is_downloadable": true,
"content_hash": "6542845d7b65ffc5358ebaa6981d991bab9fda194afa48bd727fcbe9e4a3158b"
},
{
".tag": "folder",
"name": "Documents",
"path_lower": "/documents",
"path_display": "/Documents",
"id": "id:Awe3Av8A8YYAAAAAAAAABw"
}
],
"cursor": "AAVqv-MUYFlM98b1QpFK6YaYC8L1s39lWjqbeqgWu4un...",
"has_more": false
}
Continue Listing Folder
POST /dropbox/2/files/list_folder/continue
Content-Type: application/json
{
"cursor": "AAVqv-MUYFlM98b1QpFK6YaYC8L1s39lWjqbeqgWu4un..."
}
Use when has_more is true in the previous response.
Get Metadata
POST /dropbox/2/files/get_metadata
Content-Type: application/json
{
"path": "/document.pdf",
"include_media_info": false,
"include_deleted": false,
"include_has_explicit_shared_members": false
}
Response:
json
{
".tag": "file",
"name": "document.pdf",
"path_lower": "/document.pdf",
"path_display": "/document.pdf",
"id": "id:Awe3Av8A8YYAAAAAAAAABQ",
"client_modified": "2026-02-09T19:58:12Z",
"server_modified": "2026-02-09T19:58:13Z",
"rev": "016311c063b4f8700000002caa704e3",
"size": 538371,
"is_downloadable": true,
"content_hash": "6542845d7b65ffc5358ebaa6981d991bab9fda194afa48bd727fcbe9e4a3158b"
}
Create Folder
POST /dropbox/2/files/create_folder_v2
Content-Type: application/json
{
"path": "/New Folder",
"autorename": false
}
Response:
json
{
"metadata": {
"name": "New Folder",
"path_lower": "/new folder",
"path_display": "/New Folder",
"id": "id:Awe3Av8A8YYAAAAAAAAABw"
}
}
Copy File or Folder
POST /dropbox/2/files/copy_v2
Content-Type: application/json
{
"from_path": "/source/file.pdf",
"to_path": "/destination/file.pdf",
"autorename": false
}
Response:
json
{
"metadata": {
".tag": "file",
"name": "file.pdf",
"path_lower": "/destination/file.pdf",
"path_display": "/destination/file.pdf",
"id": "id:Awe3Av8A8YYAAAAAAAAACA"
}
}
Move File or Folder
POST /dropbox/2/files/move_v2
Content-Type: application/json
{
"from_path": "/old/location/file.pdf",
"to_path": "/new/location/file.pdf",
"autorename": false
}
Response:
json
{
"metadata": {
".tag": "file",
"name": "file.pdf",
"path_lower": "/new/location/file.pdf",
"path_display": "/new/location/file.pdf",
"id": "id:Awe3Av8A8YYAAAAAAAAACA"
}
}
Delete File or Folder
POST /dropbox/2/files/delete_v2
Content-Type: application/json
{
"path": "/file-to-delete.pdf"
}
Response:
json
{
"metadata": {
".tag": "file",
"name": "file-to-delete.pdf",
"path_lower": "/file-to-delete.pdf",
"path_display": "/file-to-delete.pdf",
"id": "id:Awe3Av8A8YYAAAAAAAAABQ"
}
}
Get Temporary Download Link
POST /dropbox/2/files/get_temporary_link
Content-Type: application/json
{
"path": "/document.pdf"
}
Response:
json
{
"metadata": {
"name": "document.pdf",
"path_lower": "/document.pdf",
"path_display": "/document.pdf",
"id": "id:Awe3Av8A8YYAAAAAAAAABQ",
"size": 538371,
"is_downloadable": true
},
"link": "https://uc785ee484c03b6556c091ea4491.dl.dropboxusercontent.com/cd/0/get/..."
}
The link is valid for 4 hours.
Search
Search Files
POST /dropbox/2/files/search_v2
Content-Type: application/json
{
"query": "document",
"options": {
"path": "",
"max_results": 100,
"file_status": "active",
"filename_only": false
}
}
Response:
json
{
"has_more": false,
"matches": [
{
"highlight_spans": [],
"match_type": {
".tag": "filename"
},
"metadata": {
".tag": "metadata",
"metadata": {
".tag": "file",
"name": "document.pdf",
"path_display": "/document.pdf",
"path_lower": "/document.pdf",
"id": "id:Awe3Av8A8YYAAAAAAAAABw"
}
}
}
]
}
Continue Search
POST /dropbox/2/files/search/continue_v2
Content-Type: application/json
{
"cursor": "..."
}
File Revisions
List Revisions
POST /dropbox/2/files/list_revisions
Content-Type: application/json
{
"path": "/document.pdf",
"mode": "path",
"limit": 10
}
Response:
json
{
"is_deleted": false,
"entries": [
{
"name": "document.pdf",
"path_lower": "/document.pdf",
"path_display": "/document.pdf",
"id": "id:Awe3Av8A8YYAAAAAAAAABQ",
"client_modified": "2026-02-09T19:58:12Z",
"server_modified": "2026-02-09T19:58:13Z",
"rev": "016311c063b4f8700000002caa704e3",
"size": 538371,
"is_downloadable": true
}
],
"has_more": false
}
Restore File
POST /dropbox/2/files/restore
Content-Type: application/json
{
"path": "/document.pdf",
"rev": "016311c063b4f8700000002caa704e3"
}
Tags
Get Tags
POST /dropbox/2/files/tags/get
Content-Type: application/json
{
"paths": ["/document.pdf", "/folder"]
}
Response:
json
{
"paths_to_tags": [
{
"path": "/document.pdf",
"tags": [
{
".tag": "user_generated_tag",
"tag_text": "important"
}
]
},
{
"path": "/folder",
"tags": []
}
]
}
Add Tag
POST /dropbox/2/files/tags/add
Content-Type: application/json
{
"path": "/document.pdf",
"tag_text": "important"
}
Returns null on success.
Note: Tag text must match pattern [\w]+ (alphanumeric and underscores only, no hyphens or spaces).
Remove Tag
POST /dropbox/2/files/tags/remove
Content-Type: application/json
{
"path": "/document.pdf",
"tag_text": "important"
}
Returns null on success.
Batch Operations
Delete Batch
POST /dropbox/2/files/delete_batch
Content-Type: application/json
{
"entries": [
{"path": "/file1.pdf"},
{"path": "/file2.pdf"}
]
}
Returns async job ID. Check status with /files/delete_batch/check.
Copy Batch
POST /dropbox/2/files/copy_batch_v2
Content-Type: application/json
{
"entries": [
{"from_path": "/source/file1.pdf", "to_path": "/dest/file1.pdf"},
{"from_path": "/source/file2.pdf", "to_path": "/dest/file2.pdf"}
],
"autorename": false
}
Move Batch
POST /dropbox/2/files/move_batch_v2
Content-Type: application/json
{
"entries": [
{"from_path": "/old/file1.pdf", "to_path": "/new/file1.pdf"},
{"from_path": "/old/file2.pdf", "to_path": "/new/file2.pdf"}
],
"autorename": false
}
Pagination
Dropbox uses cursor-based pagination. When has_more is true, use the /continue endpoint with the returned cursor.
import os
import requests
headers = {
'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}',
'Content-Type': 'application/json'
}
# Initial request
response = requests.post(
'https://gateway.maton.ai/dropbox/2/files/list_folder',
headers=headers,
json={'path': '', 'limit': 100}
)
result = response.json()
all_entries = result['entries']
# Continue while has_more is True
while result.get('has_more'):
response = requests.post(
'https://gateway.maton.ai/dropbox/2/files/list_folder/continue',
headers=headers,
json={'cursor': result['cursor']}
)
result = response.json()
all_entries.extend(result['entries'])
print(f"Total entries: {len(all_entries)}")
Code Examples
JavaScript
const response = await fetch(
'https://gateway.maton.ai/dropbox/2/files/list_folder',
{
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.MATON_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ path: '' })
}
);
const data = await response.json();
console.log(data.entries);
Python
import os
import requests
response = requests.post(
'https://gateway.maton.ai/dropbox/2/files/list_folder',
headers={
'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}',
'Content-Type': 'application/json'
},
json={'path': ''}
)
data = response.json()
print(data['entries'])
Python (Create Folder and Search)
import os
import requests
headers = {
'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}',
'Content-Type': 'application/json'
}
# Create folder
response = requests.post(
'https://gateway.maton.ai/dropbox/2/files/create_folder_v2',
headers=headers,
json={'path': '/My New Folder', 'autorename': False}
)
folder = response.json()
print(f"Created folder: {folder['metadata']['path_display']}")
# Search for files
response = requests.post(
'https://gateway.maton.ai/dropbox/2/files/search_v2',
headers=headers,
json={'query': 'document'}
)
results = response.json()
print(f"Found {len(results['matches'])} matches")
Notes
- All Dropbox API v2 endpoints use HTTP POST method
- Request bodies are JSON (not form-urlencoded)
- Use empty string
""for the root folder path - Paths are case-insensitive but case-preserving
- File IDs (e.g.,
id:Awe3Av8A8YYAAAAAAAAABQ) persist even when files are moved or renamed - Tag text must match pattern
[\w]+(alphanumeric and underscores only) - Temporary download links expire after 4 hours
- Rate limits are generous and per-user
- IMPORTANT: When piping curl output to
jqor other commands, environment variables like$MATON_API_KEYmay not expand correctly in some shell environments
Error Handling
| Status | Meaning |
|---|---|
| 400 | Missing Dropbox connection or bad request |
| 401 | Invalid or missing Maton API key |
| 404 | Resource not found |
| 409 | Conflict (path doesn't exist, already exists, etc.) |
| 429 | Rate limited |
| 4xx/5xx | Passthrough error from Dropbox API |
Error responses include details:
json
{
"error_summary": "path/not_found/...",
"error": {
".tag": "path",
"path": {
".tag": "not_found"
}
}
}
Troubleshooting: Invalid API Key
When you receive an "Invalid API key" error, ALWAYS follow these steps before concluding there is an issue:
- Check that the
MATON_API_KEYenvironment variable is set:
echo $MATON_API_KEY
- Verify the API key is valid by listing connections:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.maton.ai/connections')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF