Connectors
/
Box
Live · 79 tools

Box Integration for AI Agents

The Box API is well-documented. Getting your agent to manage files, folders, and tasks across multiple enterprise accounts — with OAuth scopes, per-user token isolation, and credential refresh — is the part that adds weeks.
Box
Live

Productivity

Storage

Status
Live
Tools
79 pre-built
Auth
OAuth 2.0
Credential storage
Sandbox support

OAuth 2.0

Auto token refresh

Per-user isolation

Enterprise file management

The real problem

Why this is harder than it looks

The Box API is clean and the OAuth 2.0 flow is standard. A working single-user prototype takes an afternoon. The complexity arrives when you try to do this for real users in a multi-tenant product.

Box's OAuth scopes are not fine-grained by default — granting root_readwrite gives your agent full read-write access to everything the user owns. In enterprise Box deployments, admins can restrict which OAuth apps are allowed to connect via Box's application approval process. If your OAuth app isn't explicitly approved in their Box Admin Console, your authorization flow silently fails after the redirect. There's no OAuth error — the user just doesn't land back in your app. Debugging this requires knowing to look at Box Admin Console → Apps → Custom Apps, which most developers find only after hours of investigation.

Then there's the token lifecycle. Box access tokens expire after 60 minutes. Refresh tokens last 60 days but are single-use — every refresh issues a new refresh token that must be stored, replacing the old one. If two concurrent requests trigger a refresh race, one will succeed and the other will invalidate a now-stale token, leaving that user's session broken until they re-authorize. In a multi-tenant system, you need per-user token storage with atomic refresh logic, or you'll see intermittent auth failures that are nearly impossible to reproduce.

Finally, Box requires you to register your own OAuth app — there is no shared developer app you can use for production. Every deployment needs a Box Connected App with its own Client ID and Secret, which means your onboarding process must handle credential collection before any user can authorize.

Scalekit handles token storage, atomic refresh, and per-user isolation. Your agent names a tool and passes parameters. The auth plumbing is not your problem.

Capabilities

What your agent can do with Box

Once connected, your agent has 79 pre-built tools covering the full Box API surface:

  • Browse and manage files and folders: list folder contents, get file details, copy, move, rename, and delete files and folders end-to-end
  • Search across the entire Box instance: full-text search with type, extension, date range, and folder scope filters
  • Create and assign tasks: attach review or completion tasks to files, assign them to users, and track resolution state
  • Share files and folders: create shared links with configurable access levels, download permissions, passwords, and expiry dates
  • Manage collaborations: grant and revoke user or group access to specific files and folders with role-based permissions
  • Manage users, groups, and enterprise metadata: create and update users, manage group memberships, apply metadata templates, and stream enterprise events
Setup context

What we're building

This guide connects a document operations agent to Box — helping teams search content, manage file workflows, assign review tasks, and control sharing permissions without leaving your product.

🤖
Example agent
Document assistant searching files, managing folder structure, assigning review tasks, and controlling sharing on behalf of each user
🔐
Auth model
B2B SaaS — each user connects their own Box account. identifier = your user ID
⚙️
Scalekit account
app.scalekit.com — Client ID, Secret, Env URL
📦
Box developer app
Register a Custom App with User Authentication (OAuth 2.0) at developer.box.com
Setup

1 Setup: One SDK, One credential

Install the Scalekit SDK. The only credential your application manages is the Scalekit API key — no Box secrets, no user tokens, nothing belonging to your users.

pip install scalekit-sdk-python
npm install @scalekit-sdk/node
import scalekit.client import os from dotenv import load_dotenv load_dotenv() scalekit = scalekit.client.ScalekitClient( client_id=os.getenv("SCALEKIT_CLIENT_ID"), client_secret=os.getenv("SCALEKIT_CLIENT_SECRET"), env_url=os.getenv("SCALEKIT_ENV_URL"), ) actions = scalekit.actions
import { ScalekitClient } from '@scalekit-sdk/node'; import 'dotenv/config'; const scalekit = new ScalekitClient( process.env.SCALEKIT_ENV_URL, process.env.SCALEKIT_CLIENT_ID, process.env.SCALEKIT_CLIENT_SECRET ); const actions = scalekit.actions;
Already have credentials?
Connected Accounts

2 Per-User Auth: Creating connected accounts

Each user gets their own Connected Account, giving them a dedicated auth context. The identifier is any unique string from your system — a UUID, email, whatever you use internally.

response = actions.get_or_create_connected_account( connection_name="box", identifier="user_box_123" # your internal user ID ) connected_account = response.connected_account print(f"Status: {connected_account.status}") # Status: PENDING — user hasn't authorized yet
const response = await actions.getOrCreateConnectedAccount({ connectionName: "box", identifier: "user_box_123" // your internal user ID }); const connectedAccount = response.connectedAccount; console.log(`Status: ${connectedAccount.status}`); // Status: PENDING — user hasn't authorized yet

This call is idempotent — safe to call on every session start. Returns the existing account if one already exists.

Authorization Flow

3 The authorization flow

The user authorizes your agent once. Scalekit generates the OAuth URL with correct scopes, PKCE challenge, and redirect handling pre-configured. After approval, you never see the token.

if connected_account.status != "ACTIVE": link = actions.get_authorization_link( connection_name="box", identifier="user_box_123" ) # Redirect user → Box's native OAuth consent screen # Scalekit captures the token on callback return redirect(link.link)
if (connectedAccount.status !== "ACTIVE") { const { link } = await actions.getAuthorizationLink({ connectionName: "box", identifier: "user_box_123" }); // Redirect user → Box's native OAuth consent screen // Scalekit captures the token on callback return redirect(link); }
Token management is automatic
After the user approves, Scalekit stores encrypted tokens and the connected account moves to ACTIVE. Box access tokens expire after 60 minutes — Scalekit refreshes them automatically before expiry using the refresh token. Refresh tokens are single-use; Scalekit handles the rotation atomically to prevent race conditions. Check account.status before critical operations.
Bring Your Own Credentials — required for production
Box requires you to register your own Custom App with User Authentication (OAuth 2.0) at developer.box.com and supply your Client ID and Secret. Scalekit does not provide a managed Box app. In the Scalekit dashboard, go to AgentKit → Connections → your Box connection, click "Use your own credentials," and paste your Box credentials. Token management stays fully handled.
Calling Box

4 Calling Box: What your agent writes

With the connected account active, your agent calls Box actions using actions.execute_tool(). Name the tool, pass parameters. Scalekit handles token retrieval and request construction.

List folder contents

Start here to discover file and folder IDs. Pass "0" for the root folder. Use limit and offset for pagination.

result = actions.execute_tool( identifier="user_box_123", tool_name="box_folder_items_list", tool_input={ "folder_id": "0", "limit": 50, "sort": "name", "direction": "ASC" } ) # Returns: entries[] with id, name, type (file/folder), modified_at
const result = await actions.executeTool({ identifier: "user_box_123", toolName: "box_folder_items_list", toolInput: { "folder_id": "0", "limit": 50, "sort": "name", "direction": "ASC" } }); // Returns: entries[] with id, name, type (file/folder), modified_at

Search files and folders

Search using a query string. Scope to a specific folder with ancestor_folder_ids, filter by file type, extension, or date range. Returns up to 200 results per call.

result = actions.execute_tool( identifier="user_box_123", tool_name="box_search", tool_input={ "query": "Q2 2026 budget", "type": "file", "file_extensions": "xlsx,pdf", "ancestor_folder_ids": "12345678", "limit": 25 } ) # Returns: entries[] with file id, name, path, modified_at
const result = await actions.executeTool({ identifier: "user_box_123", toolName: "box_search", toolInput: { "query": "Q2 2026 budget", "type": "file", "file_extensions": "xlsx,pdf", "ancestor_folder_ids": "12345678", "limit": 25 } }); // Returns: entries[] with file id, name, path, modified_at

Create a task and assign it

Attach a review task to a file, then assign it to a user. The task action can be review or complete. Use the task ID from the first call in the assignment.

# 1. Create the task task = actions.execute_tool( identifier="user_box_123", tool_name="box_task_create", tool_input={ "file_id": "98765432", "message": "Please review and approve before Friday", "action": "review", "due_at": "2026-05-02T17:00:00Z" } ) task_id = task["id"] # 2. Assign to a user result = actions.execute_tool( identifier="user_box_123", tool_name="box_task_assignment_create", tool_input={ "task_id": task_id, "user_login": "reviewer@company.com" } )
// 1. Create the task const task = await actions.executeTool({ identifier: "user_box_123", toolName: "box_task_create", toolInput: { "file_id": "98765432", "message": "Please review and approve before Friday", "action": "review", "due_at": "2026-05-02T17:00:00Z" } }); const taskId = task.id; // 2. Assign to a user const result = await actions.executeTool({ identifier: "user_box_123", toolName: "box_task_assignment_create", toolInput: { "task_id": taskId, "user_login": "reviewer@company.com" } });

Create a shared link for a file

Generate a shared link with access level, download permission, and optional expiry. access can be open, company, or collaborators.

result = actions.execute_tool( identifier="user_box_123", tool_name="box_shared_link_file_create", tool_input={ "file_id": "98765432", "access": "company", "can_download": True, "unshared_at": "2026-06-30T00:00:00Z" } ) # Returns: shared_link.url — ready to distribute
const result = await actions.executeTool({ identifier: "user_box_123", toolName: "box_shared_link_file_create", toolInput: { "file_id": "98765432", "access": "company", "can_download": true, "unshared_at": "2026-06-30T00:00:00Z" } }); // Returns: shared_link.url — ready to distribute
Framework wiring

5 Wiring into your agent framework

Scalekit integrates directly with LangChain. The agent decides what to call; Scalekit handles auth on every invocation. No token plumbing in your agent logic.

from langchain_anthropic import ChatAnthropic from langchain.agents import AgentExecutor, create_tool_calling_agent from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder from scalekit.langchain import get_tools box_tools = get_tools( connection_name="box", identifier="user_box_123" ) prompt = ChatPromptTemplate.from_messages([ ("system", "You are a document assistant. Use the available tools to help manage Box files, folders, tasks, and sharing."), MessagesPlaceholder("chat_history", optional=True), ("human", "{input}"), MessagesPlaceholder("agent_scratchpad"), ]) agent = create_tool_calling_agent(ChatAnthropic(model="claude-sonnet-4-6"), box_tools, prompt) result = AgentExecutor(agent=agent, tools=box_tools).invoke({ "input": "Find all PDF files modified this month in the Legal folder and create review tasks for each one assigned to legal@company.com" })
import { ChatAnthropic } from "@langchain/anthropic"; import { AgentExecutor, createToolCallingAgent } from "langchain/agents"; import { ChatPromptTemplate, MessagesPlaceholder } from "@langchain/core/prompts"; import { getTools } from "@scalekit-sdk/langchain"; const boxTools = getTools({ connectionName: "box", identifier: "user_box_123" }); const prompt = ChatPromptTemplate.fromMessages([ ["system", "You are a document assistant. Use the available tools to help manage Box files, folders, tasks, and sharing."], new MessagesPlaceholder("chat_history", true), ["human", "{input}"], new MessagesPlaceholder("agent_scratchpad"), ]); const agent = await createToolCallingAgent({ llm: new ChatAnthropic({ model: "claude-sonnet-4-6" }), tools: boxTools, prompt }); const result = await AgentExecutor.fromAgentAndTools({ agent, tools: boxTools }).invoke({ input: "Find all PDF files modified this month in the Legal folder and create review tasks for each one assigned to legal@company.com" });
Other frameworks supported
Tool reference

All 79 Box tools

Grouped by capability. Your agent calls tools by name — no API wrappers to write.

Files
box_file_get
Retrieve detailed metadata for a file including name, size, path, owner, and modified date
box_file_update
Update a file's name, description, tags, or move it to a different folder
box_file_copy
Copy a file to a specified destination folder, with optional rename
box_file_delete
Move a file to trash. Use box_trash_file_permanently_delete to purge it
box_file_versions_list
List all previous versions of a file with version IDs and timestamps
box_file_representations_get
Retrieve available representations (PDF, extracted text, image thumbnails) for a file. Poll until status is success before downloading
box_file_thumbnail_get
Retrieve a thumbnail image (jpg or png) for a file at specified dimensions
box_file_collaborations_list
List all collaborations on a file — who has access and at what role
box_file_comments_list
Retrieve all comments on a file
box_file_tasks_list
List all tasks attached to a file
box_file_metadata_create
Apply a metadata template instance to a file with field values
box_file_metadata_get
Retrieve a specific metadata instance on a file by scope and template key
box_file_metadata_delete
Remove a metadata instance from a file
box_file_metadata_list
List all metadata instances attached to a file
Folders
box_folder_get
Retrieve a folder's details and its items. Use '0' for the root folder
box_folder_items_list
Paginated list of items in a folder. Supports sort by id, name, date, or size
box_folder_create
Create a new folder inside a parent folder. Use '0' as parent for root-level folders
box_folder_update
Update a folder's name, description, or move it to a new parent
box_folder_copy
Copy a folder and all its contents to a destination, with optional rename
box_folder_delete
Move a folder to trash. Set recursive to true for non-empty folders
box_folder_collaborations_list
List all collaborations on a folder — use this to find collaboration IDs before updating or deleting access
box_folder_metadata_list
List all metadata instances on a folder
Search
box_search
Full-text search across files, folders, and web links. Filter by type, extension, date range, folder scope, and content type. Returns up to 200 results
Tasks & Assignments
box_task_create
Create a review or completion task on a file with a message, action type, and due date
box_task_get
Retrieve a task's details including message, action, due date, and completion rule
box_task_update
Update a task's message, due date, action, or completion rule
box_task_delete
Remove a task from a file
box_task_assignment_create
Assign a task to a user by user ID or email login
box_task_assignment_get
Retrieve a specific task assignment
box_task_assignment_update
Update a task assignment — mark as completed, approved, or rejected with an optional message
box_task_assignment_delete
Remove a task assignment from a user
box_task_assignments_list
List all assignments for a task
Shared Links
box_shared_link_file_create
Create or update a shared link for a file. Set access (open/company/collaborators), download permission, password, and expiry
box_shared_link_folder_create
Create or update a shared link for a folder with the same access and permission options
Collaborations
box_collaboration_create
Grant a user or group access to a file or folder with a specified role (viewer, editor, co-owner, etc.)
box_collaboration_get
Retrieve details of a collaboration by its ID
box_collaboration_update
Update a collaboration's role or status (accepted/rejected)
box_collaboration_delete
Revoke a collaboration, removing the user or group's access to the item
Comments
box_comment_create
Add a comment to a file. Supports @mentions using the tagged_message field
box_comment_get
Retrieve a comment by ID
box_comment_update
Update the text of an existing comment
box_comment_delete
Remove a comment from a file
Users
box_user_me_get
Retrieve information about the currently authenticated user
box_user_get
Retrieve information about a specific user by ID
box_users_list
List enterprise users filtered by name or login. Filter by type: all, managed, or external
box_user_create
Create a new managed user or app user in the enterprise with name, login, role, and storage quota
box_user_update
Update a user's name, role, status, or storage quota
box_user_delete
Remove a user from the enterprise. Set force to true to delete even if they own content
box_user_memberships_list
List all group memberships for a specific user
Groups
box_groups_list
List all groups in the enterprise with optional name filter
box_group_create
Create a new enterprise group with name, description, and visibility settings
box_group_get
Retrieve information about a specific group
box_group_update
Update a group's name, description, or membership visibility settings
box_group_delete
Permanently delete a group from the enterprise
box_group_members_list
Retrieve all members of a group with pagination
box_group_membership_add
Add a user to a group as a member or admin
box_group_membership_get
Retrieve a specific group membership by membership ID
box_group_membership_update
Update a user's role within a group (member or admin)
box_group_membership_remove
Remove a user from a group using the membership ID
Webhooks
box_webhook_create
Create a webhook on a file or folder to receive event notifications at an HTTPS endpoint. Requires manage_webhook scope
box_webhook_get
Retrieve a webhook's details including target, address, and trigger list
box_webhook_update
Update a webhook's address, target, or trigger event list
box_webhook_delete
Remove a webhook
box_webhooks_list
List all webhooks registered for the application with pagination
Collections, Trash & Events
box_collections_list
Retrieve all collections for the user (e.g. Favorites)
box_collection_items_list
List items in a collection with pagination
box_recent_items_list
Retrieve files and folders the authenticated user has accessed recently
box_events_list
Stream enterprise or user events filtered by type and date range. Use stream_type admin_logs for audit events
box_trash_list
List items currently in the user's trash
box_trash_file_restore
Restore a trashed file. Supply a new name or parent if the original location is taken
box_trash_file_permanently_delete
Permanently delete a trashed file. Cannot be undone
box_trash_folder_restore
Restore a trashed folder. Supply a new name or parent if the original location is unavailable
box_trash_folder_permanently_delete
Permanently delete a trashed folder. Cannot be undone
Metadata & Web Links
box_metadata_templates_list
List all metadata templates available in the enterprise
box_metadata_template_get
Retrieve a metadata template schema by scope and template key
box_web_link_create
Create a bookmark (web link) inside a folder pointing to an external URL
box_web_link_get
Retrieve a web link's details by ID
box_web_link_update
Update a web link's URL, name, description, or parent folder
box_web_link_delete
Remove a web link from Box
Connector notes

Box-specific behavior

Refresh tokens are single-use — race conditions matter
Box issues a new refresh token on every access token refresh, invalidating the previous one. If two concurrent requests both attempt a refresh, one will succeed and one will invalidate a now-stale token. Scalekit handles this atomically. If you're calling the Box API directly outside of Scalekit tools, implement a mutex around your refresh logic or use a token locking mechanism.
Collaboration ID ≠ User ID
box_collaboration_get, box_collaboration_update, and box_collaboration_delete all require a collaboration_id — not the user's Box user ID. After creating a collaboration, retrieve its ID from box_folder_collaborations_list or box_file_collaborations_list. Passing a user ID to these tools returns a 404.
Enterprise app approval may be required
Enterprise Box admins can restrict which OAuth apps are permitted to connect via the Custom Apps section of Box Admin Console. If users in a specific enterprise cannot complete the authorization flow, ask their Box admin to approve your app under Admin Console → Apps → Custom Apps Manager. This is an enterprise policy setting — it is not an error in your OAuth configuration.
File uploads use a different base URL
Box file uploads go to upload.box.com, not api.box.com. The Scalekit proxy does not cover this endpoint. To upload files, extract the OAuth token from the connected account and call the Box upload API at https://upload.box.com/api/2.0/files/content directly.
Infrastructure decision

Why not build this yourself

The Box OAuth flow is documented. Token storage isn't technically hard. But here's what you're actually signing up for:

PROBLEM 01
Single-use refresh tokens with no grace period — concurrent requests cause token invalidation that silently breaks user sessions until re-authorization
PROBLEM 02
Enterprise admin approval is required for each Box instance — your OAuth app must be explicitly allowlisted in Box Admin Console before any enterprise user can connect
PROBLEM 03
Per-user token isolation across a multi-tenant system — one user's Box credentials must never be accessible to another, even within the same organization
PROBLEM 04
No managed Box app is available — every deployment requires you to register your own OAuth app, configure scopes, and supply credentials before any user can authorize

That's one connector. Your agent product will eventually need Salesforce, Gmail, Slack, Notion, and whatever else your customers ask for. Each has its own OAuth quirks and failure modes.

Scalekit maintains every connector. You maintain none of them.

Ready to ship

Ship Box in minutes

Free to start. Single-use token rotation handled. Enterprise app approval documented.