Box
Box API integration with managed OAuth. Manage files, folders, collaborations, and cloud storage. Use this skill when users want to upload, download, share,...
Box API integration with managed OAuth. Manage files, folders, collaborations, and cloud storage. Use this skill when users want to upload, download, share,...
Real data. Real impact.
Emerging
Developers
Per week
Open source
Skills give you superpowers. Install in 30 seconds.
Access the Box API with managed OAuth authentication. Manage files, folders, collaborations, shared links, and cloud storage.
# Get current user info python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://gateway.maton.ai/box/2.0/users/me') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF
https://gateway.maton.ai/box/2.0/{resource}
The gateway proxies requests to
api.box.com/2.0 (for most endpoints) or upload.box.com/api/2.0 (for upload endpoints) and automatically injects your OAuth token. The routing is handled automatically based on the endpoint path.
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"
Manage your Box OAuth connections at
https://ctrl.maton.ai.
python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://ctrl.maton.ai/connections?app=box&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
python <<'EOF' import urllib.request, os, json data = json.dumps({'app': 'box'}).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
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:
{ "connection": { "connection_id": "{connection_id}", "status": "ACTIVE", "creation_time": "2026-02-08T21:14:41.808115Z", "last_updated_time": "2026-02-08T21:16:10.100340Z", "url": "https://connect.maton.ai/?session_token=...", "app": "box", "metadata": {} } }
Open the returned
url in a browser to complete OAuth authorization.
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
If you have multiple Box connections, specify which one to use with the
Maton-Connection header:
python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://gateway.maton.ai/box/2.0/users/me') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('Maton-Connection', '{connection_id}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF
If omitted, the gateway uses the default (oldest) active connection.
GET /box/2.0/users/me
Response:
{ "type": "user", "id": "48806418054", "name": "Chris", "login": "chris@example.com", "created_at": "2026-02-08T13:12:34-08:00", "modified_at": "2026-02-08T13:12:35-08:00", "language": "en", "timezone": "America/Los_Angeles", "space_amount": 10737418240, "space_used": 0, "max_upload_size": 262144000, "status": "active", "avatar_url": "https://app.box.com/api/avatar/large/48806418054" }
GET /box/2.0/users/{user_id}
The root folder has ID
0:
GET /box/2.0/folders/0
GET /box/2.0/folders/{folder_id}
Response:
{ "type": "folder", "id": "365037181307", "name": "My Folder", "description": "Folder description", "size": 0, "path_collection": { "total_count": 1, "entries": [ {"type": "folder", "id": "0", "name": "All Files"} ] }, "created_by": {"type": "user", "id": "48806418054", "name": "Chris"}, "owned_by": {"type": "user", "id": "48806418054", "name": "Chris"}, "item_status": "active" }
GET /box/2.0/folders/{folder_id}/items
Query parameters:
limit - Maximum items to return (default 100, max 1000)offset - Offset for paginationfields - Comma-separated list of fields to includeResponse:
{ "total_count": 1, "entries": [ { "type": "folder", "id": "365036703666", "name": "Subfolder" } ], "offset": 0, "limit": 100 }
POST /box/2.0/folders Content-Type: application/json{ "name": "New Folder", "parent": {"id": "0"} }
Response:
{ "type": "folder", "id": "365037181307", "name": "New Folder", "created_at": "2026-02-08T14:56:17-08:00" }
PUT /box/2.0/folders/{folder_id} Content-Type: application/json{ "name": "Updated Folder Name", "description": "Updated description" }
POST /box/2.0/folders/{folder_id}/copy Content-Type: application/json{ "name": "Copied Folder", "parent": {"id": "0"} }
DELETE /box/2.0/folders/{folder_id}
Query parameters:
recursive - Set to true to delete non-empty foldersReturns 204 No Content on success.
GET /box/2.0/files/{file_id}
GET /box/2.0/files/{file_id}/content
Returns a redirect to the download URL.
Upload a new file (up to 50 MB for direct upload):
POST /box/api/2.0/files/content Content-Type: multipart/form-dataattributes={"name":"file.txt","parent":{"id":"0"}} file=<binary data>
The
attributes field is a JSON string with:
name (required) - Filename to useparent.id (required) - Folder ID to upload to (use "0" for root)content_created_at - Optional timestampcontent_modified_at - Optional timestampResponse:
{ "total_count": 1, "entries": [ { "type": "file", "id": "123456789", "name": "file.txt", "size": 1024, "created_at": "2026-04-14T10:00:00-07:00", "modified_at": "2026-04-14T10:00:00-07:00", "parent": {"type": "folder", "id": "0", "name": "All Files"} } ] }
Note: The gateway automatically routes upload endpoints to
upload.box.com.
Upload a new version of an existing file:
POST /box/api/2.0/files/{file_id}/content Content-Type: multipart/form-dataattributes={"name":"file.txt"} file=<binary data>
For files larger than 50 MB (up to 50 GB), use chunked upload sessions. The gateway automatically routes these endpoints to
upload.box.com.
POST /box/api/2.0/files/upload_sessions Content-Type: application/json{ "folder_id": "0", "file_size": 104857600, "file_name": "large_file.zip" }
Response:
{ "id": "F971964745A5CD0C001BBE4E58196BFD", "type": "upload_session", "session_expires_at": "2026-04-15T10:00:00-07:00", "part_size": 8388608, "total_parts": 13, "num_parts_processed": 0, "session_endpoints": { "list_parts": "https://upload.box.com/api/2.0/files/upload_sessions/F971964745A5CD0C001BBE4E58196BFD/parts", "commit": "https://upload.box.com/api/2.0/files/upload_sessions/F971964745A5CD0C001BBE4E58196BFD/commit", "upload_part": "https://upload.box.com/api/2.0/files/upload_sessions/F971964745A5CD0C001BBE4E58196BFD", "status": "https://upload.box.com/api/2.0/files/upload_sessions/F971964745A5CD0C001BBE4E58196BFD", "abort": "https://upload.box.com/api/2.0/files/upload_sessions/F971964745A5CD0C001BBE4E58196BFD" } }
POST /box/api/2.0/files/{file_id}/upload_sessions Content-Type: application/json{ "file_size": 104857600, "file_name": "large_file.zip" }
PUT /box/api/2.0/files/upload_sessions/{session_id} Content-Type: application/octet-stream Content-Range: bytes 0-8388607/104857600 Digest: sha=<base64-encoded SHA-1 of part><part data>
Response:
{ "part": { "part_id": "6F2D3A7B8C4E5F6A", "offset": 0, "size": 8388608, "sha1": "134b65991ed521fcfe4724b7d814ab8ded5185dc" } }
GET /box/api/2.0/files/upload_sessions/{session_id}/parts
After all parts are uploaded:
POST /box/api/2.0/files/upload_sessions/{session_id}/commit Content-Type: application/json Digest: sha=<base64-encoded SHA-1 of entire file>{ "parts": [ {"part_id": "6F2D3A7B8C4E5F6A", "offset": 0, "size": 8388608}, {"part_id": "7G3E4B8D9F5A6C7B", "offset": 8388608, "size": 8388608} ] }
Response: Returns the created file object.
DELETE /box/api/2.0/files/upload_sessions/{session_id}
Returns 204 No Content on success
PUT /box/2.0/files/{file_id} Content-Type: application/json{ "name": "renamed-file.txt", "description": "File description" }
POST /box/2.0/files/{file_id}/copy Content-Type: application/json{ "name": "copied-file.txt", "parent": {"id": "0"} }
DELETE /box/2.0/files/{file_id}
Returns 204 No Content on success.
GET /box/2.0/files/{file_id}/versions
Create a shared link by updating a file or folder:
PUT /box/2.0/folders/{folder_id} Content-Type: application/json{ "shared_link": { "access": "open" } }
Access levels:
open - Anyone with the linkcompany - Only users in the enterprisecollaborators - Only collaboratorsResponse includes:
{ "shared_link": { "url": "https://app.box.com/s/sisarrztrenabyygfwqggbwommf8uucv", "access": "open", "effective_access": "open", "is_password_enabled": false, "permissions": { "can_preview": true, "can_download": true, "can_edit": false } } }
GET /box/2.0/folders/{folder_id}/collaborations
POST /box/2.0/collaborations Content-Type: application/json{ "item": {"type": "folder", "id": "365037181307"}, "accessible_by": {"type": "user", "login": "user@example.com"}, "role": "editor" }
Roles:
editor, viewer, previewer, uploader, previewer_uploader, viewer_uploader, co-owner
PUT /box/2.0/collaborations/{collaboration_id} Content-Type: application/json{ "role": "viewer" }
DELETE /box/2.0/collaborations/{collaboration_id}
GET /box/2.0/search?query=document
Query parameters:
query - Search query (required)type - Filter by type: file, folder, web_linkfile_extensions - Comma-separated extensionsancestor_folder_ids - Limit to specific folderslimit - Max results (default 30)offset - Pagination offsetResponse:
{ "total_count": 5, "entries": [...], "limit": 30, "offset": 0, "type": "search_results_items" }
GET /box/2.0/events
Query parameters:
stream_type - all, changes, sync, admin_logsstream_position - Position to start fromlimit - Max events to returnResponse:
{ "chunk_size": 4, "next_stream_position": "30401068076164269", "entries": [...] }
GET /box/2.0/folders/trash/items
GET /box/2.0/files/{file_id}/trash GET /box/2.0/folders/{folder_id}/trash
POST /box/2.0/files/{file_id} POST /box/2.0/folders/{folder_id}
DELETE /box/2.0/files/{file_id}/trash DELETE /box/2.0/folders/{folder_id}/trash
GET /box/2.0/collections
Response:
{ "total_count": 1, "entries": [ { "type": "collection", "name": "Favorites", "collection_type": "favorites", "id": "35223030868" } ] }
GET /box/2.0/collections/{collection_id}/items
GET /box/2.0/recent_items
GET /box/2.0/webhooks
POST /box/2.0/webhooks Content-Type: application/json{ "target": {"id": "365037181307", "type": "folder"}, "address": "https://example.com/webhook", "triggers": ["FILE.UPLOADED", "FILE.DOWNLOADED"] }
Note: Webhook creation may require enterprise permissions.
DELETE /box/2.0/webhooks/{webhook_id}
Box uses offset-based pagination:
GET /box/2.0/folders/0/items?limit=100&offset=0 GET /box/2.0/folders/0/items?limit=100&offset=100
Some endpoints use marker-based pagination with
marker parameter.
Response:
{ "total_count": 250, "entries": [...], "offset": 0, "limit": 100 }
const response = await fetch( 'https://gateway.maton.ai/box/2.0/folders/0/items', { headers: { 'Authorization': `Bearer ${process.env.MATON_API_KEY}` } } ); const data = await response.json();
import os import requestsresponse = requests.get( 'https://gateway.maton.ai/box/2.0/folders/0/items', headers={'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'} ) data = response.json()
import os import requestsresponse = requests.post( 'https://gateway.maton.ai/box/2.0/folders', headers={ 'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}', 'Content-Type': 'application/json' }, json={ 'name': 'New Folder', 'parent': {'id': '0'} } ) folder = response.json() print(f"Created folder: {folder['id']}")
import os import json import requestsfile_path = '/path/to/local/file.txt' parent_folder_id = '0' # Root folder
with open(file_path, 'rb') as f: response = requests.post( 'https://gateway.maton.ai/box/api/2.0/files/content', headers={ 'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}' }, files={ 'attributes': (None, json.dumps({ 'name': os.path.basename(file_path), 'parent': {'id': parent_folder_id} })), 'file': (os.path.basename(file_path), f) } ) result = response.json() file_entry = result['entries'][0] print(f"Uploaded: {file_entry['name']} (ID: {file_entry['id']})")
import os import json import hashlib import base64 import requestsCHUNK_SIZE = 8 * 1024 * 1024 # 8 MB (Box's default part size) file_path = '/path/to/large/file.zip' parent_folder_id = '0'
headers = {'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'} file_size = os.path.getsize(file_path) file_name = os.path.basename(file_path)
Step 1: Create upload session
response = requests.post( 'https://gateway.maton.ai/box/api/2.0/files/upload_sessions', headers={**headers, 'Content-Type': 'application/json'}, json={ 'folder_id': parent_folder_id, 'file_size': file_size, 'file_name': file_name } ) session = response.json() session_id = session['id'] part_size = session['part_size']
Step 2: Upload parts
parts = [] file_sha1 = hashlib.sha1()
with open(file_path, 'rb') as f: offset = 0 while offset < file_size: chunk = f.read(part_size) chunk_size = len(chunk) end_byte = offset + chunk_size - 1
# Calculate SHA-1 for this part part_sha1 = hashlib.sha1(chunk).digest() file_sha1.update(chunk) response = requests.put( f'https://gateway.maton.ai/box/api/2.0/files/upload_sessions/{session_id}', headers={ **headers, 'Content-Type': 'application/octet-stream', 'Content-Range': f'bytes {offset}-{end_byte}/{file_size}', 'Digest': f'sha={base64.b64encode(part_sha1).decode()}' }, data=chunk ) part_info = response.json()['part'] parts.append({ 'part_id': part_info['part_id'], 'offset': part_info['offset'], 'size': part_info['size'] }) offset += chunk_size print(f"Uploaded part {len(parts)}: {offset}/{file_size} bytes")Step 3: Commit upload session
response = requests.post( f'https://gateway.maton.ai/box/api/2.0/files/upload_sessions/{session_id}/commit', headers={ **headers, 'Content-Type': 'application/json', 'Digest': f'sha={base64.b64encode(file_sha1.digest()).decode()}' }, json={'parts': parts} ) result = response.json() print(f"Upload complete: {result['entries'][0]['name']}")
0upload.box.comattributes JSON and file fieldsfields parameter to request specific fields and reduce response sizeIf-Match headerjq or other commands, environment variables like $MATON_API_KEY may not expand correctly in some shell environments| Status | Meaning |
|---|---|
| 400 | Missing Box connection or bad request |
| 401 | Invalid or missing Maton API key |
| 403 | Insufficient permissions for the operation |
| 404 | Resource not found |
| 409 | Conflict (e.g., item with same name exists) |
| 429 | Rate limited |
| 4xx/5xx | Passthrough error from Box API |
Box errors include detailed messages:
{ "type": "error", "status": 409, "code": "item_name_in_use", "message": "Item with the same name already exists" }
MATON_API_KEY environment variable is set:echo $MATON_API_KEY
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
box. For example:https://gateway.maton.ai/box/2.0/users/mehttps://gateway.maton.ai/2.0/users/meNo automatic installation available. Please visit the source repository for installation instructions.
View Installation Instructions1,500+ AI skills, agents & workflows. Install in 30 seconds. Part of the Torly.ai family.
© 2026 Torly.ai. All rights reserved.