Skip to content

Integrations

Dropbox SDK: get started

The complete Dropbox API through typed application or agent clients

Use an ordinary App, or an Agent when the workload needs agent identity. Alter builds provider requests from a reviewed contract and applies the same connection authorization, policy, approvals, and audit records as raw requests.

Terminal window
npm install @alter-ai/sdk @alter-ai/dropbox
# Python (installs core automatically)
pip install alter-sdk-dropbox

The provider package includes only Dropbox types and response schemas and pins its contract version.

Configure Dropbox, request the scopes the application needs, and retain each customer’s grant ID after Connect consent. Alter supplies the credential; it never belongs in operation input.

import { App } from "@alter-ai/sdk";
import { DropboxIntegration } from "@alter-ai/dropbox";
const app = new App({ apiKey: process.env.ALTER_API_KEY! });
try {
const client = new DropboxIntegration(app, { grantId: process.env.DROPBOX_GRANT_ID! });
const result = await (
await client.files.listFolder({ body: { path: "/Clients/Wallflower" } })
).wait();
console.log(result.bodyJson());
} finally {
await app.close();
}
from alter_sdk import App
from alter_sdk_dropbox import DropboxIntegration
async def first_call(api_key: str, grant_id: str):
async with App(api_key=api_key) as app:
client = DropboxIntegration(app, {"grant_id": grant_id})
call = await client.files.list_folder({"body": {"path": "/Clients/Wallflower"}})
result = await call.wait()
return result.body_json()

Contract 2026-11-01 is generated from Dropbox’s official API specification, the Stone files Dropbox publishes, pinned to one revision. It publishes every route of the user and Business APIs except the ones listed under Not published, each with its arguments, results and errors as Dropbox types them. The API reference links every operation to its complete input fields, response models, TypeScript and Python examples, and policy identity. Browse by resource under this provider’s API reference in the Integrations sidebar, or download the pinned specification as OpenAPI. The Developer Portal provider view and alter integrations operations dropbox --version 2026-11-01 also expose the schemas.

SDK methods follow Dropbox’s route names: files/list_folder/continue is files.listFolderContinue in TypeScript and files.list_folder_continue in Python, and files/copy:2 is files.copyV2 / files.copy_v2.

Generated calls pin the Alter contract version. Dropbox’s own product, role, scope and subscription requirements still apply. There is no silent version fallback and no automatic write retry or pagination.

Terminal window
alter integrations execute dropbox dropbox.files_create_folder_v2 \
--version 2026-11-01 --grant "$DROPBOX_GRANT_ID" \
--input '{"body": {"path": "/Clients/Wallflower/2026-11"}}' --wait

Arguments use native headers and body containers. Dropbox has three call styles, and each route keeps its own:

  • RPC routes (most of the API) take their arguments as the JSON body.
  • Upload routes (files.upload, files.uploadSessionStart, files.uploadSessionAppendV2, files.uploadSessionAppendBatch, files.uploadSessionFinish, files.paperCreate and files.paperUpdate) take their arguments under headers["Dropbox-API-Arg"] and the file as body.
  • Download routes (files.download, files.downloadZip, files.export, files.getPreview, files.getThumbnail, files.getThumbnailV2, account.getPhoto, sharing.getSharedLinkFile and riviera.downloadTransformOutput) take their arguments under headers["Dropbox-API-Arg"] and answer the file’s bytes, read with bodyBytes() / body_bytes(). Dropbox returns the route’s result (the file’s metadata) in the Dropbox-API-Result response header, a JSON document.

Alter sends Dropbox-API-Arg as the compact, ASCII-escaped JSON Dropbox requires, so a path with non-ASCII characters needs no escaping by the caller. path arguments carry Dropbox’s own patterns: a value Dropbox would refuse (no leading /, and not an id:, rev:, ns: or nspath: form) is refused before any request is sent.

Every route also takes three optional context headers: Dropbox-API-Path-Root (the namespace paths are relative to, such as a team space root: {".tag": "root", "root": "<namespace id>"}), and, for a team-linked app, Dropbox-API-Select-User and Dropbox-API-Select-Admin. On a grant governed by operation rules, a request carrying one is refused unless a rule names it, so a folder rule cannot be sidestepped by switching namespace.

Each download route also has two typed companions. <method>Result() / <method>_result() reads the Dropbox-API-Result header from a finished call’s result (or a stream response), validates it against the contract and returns it typed, so a malformed or missing header raises an error instead of reaching the application. <method>Stream() / <method>_stream() validates the arguments like the buffered method and returns the core SDK’s streamed response, for files of any size:

const call = await client.files.download({
headers: { "Dropbox-API-Arg": { path: "/Clients/Wallflower/statement.pdf" } },
});
const result = await call.wait();
const metadata = client.files.downloadResult(result); // FilesFileMetadata
const bytes = result.bodyBytes();
const stream = await client.files.downloadStream({
headers: { "Dropbox-API-Arg": { path: "/Clients/Wallflower/archive.zip" } },
});
console.log(client.files.downloadResult(stream).size);
call = await client.files.download({"headers": {"Dropbox-API-Arg": {"path": "/Clients/Wallflower/statement.pdf"}}})
result = await call.wait()
metadata = client.files.download_result(result) # FilesFileMetadata
stream = await client.files.download_stream({"headers": {"Dropbox-API-Arg": {"path": "/Clients/Wallflower/archive.zip"}}})

A stream method needs a core SDK that supports streamed managed operations, and raises ManagedOperationError with managed_stream_unsupported otherwise. An operation a policy holds for approval is refused on the streamed route (proxy_stream_approval_required); use the buffered method for it.

HTTP 204 returns null / None from the typed decoder. Dropbox reports errors as HTTP 409 with an error_summary, which reach the caller as a provider error.

A batch, an asynchronous job or a member removal answers HTTP 200 even when it failed. A batch in which every entry is a failure (an upload session that expired before files.uploadSessionAppendBatch, a copy whose every destination exists), a job status that is failed, a team result in which no item is success, a secondary-email change in which no email of any user succeeded while some user or email failed (an address already added, already removed or already verified is a failure, as Dropbox reports it), a revocation batch in which every item has success: false, and a member_error from sharing.removeFileMember2 are provider faults: ok is false and bodyJson() / body_json() raises ProviderAPIError. A batch that partly succeeded, a secondary-email change in which any email succeeded, and a job still in_progress are ordinary results; read each entry’s .tag. A lookup whose every item is id_not_found or access_error is an answer, not a fault, and a member-suspension job’s complete status reports counts only: its report says which members were suspended.

A policy rule can require approval for any operation. The call returns a pending approval; wait() resolves once the approver decides, and resume(approvalId) picks a pending approval up after a restart. Approval cards show the operation, its contract version and the request input the sensitivity review marked safe to display.

An upload’s body is a JSON object with filename, content_type and content_base64; Alter sends the decoded bytes as the request body, exactly as Dropbox expects. Under a require_approval rule an upload is held with the pending approval: the approver sees the file’s name and media type and a masked size, never its contents, and the approved upload sends the exact bytes that were held.

An inline call carries up to 5 MiB of serialized input, and base64 adds a third. A larger file for files.upload (or any upload route) is sent as an upload instead, with no inline limit: files.upload() switches by itself in both SDKs when the file object is too large (about 3.7 MiB of file), and integrations.executeUpload() / integrations.execute_upload() take the file as a path or bytes directly. The call is declared with the file’s name, media type, size and SHA-256, every policy runs on that declaration, and only then are the bytes sent, once. Under a require_approval rule nothing is sent until the approval: wait() on the call then delivers the same bytes (or deliverApprovedUpload() / deliver_approved_upload() with the approval id), and only bytes with the approved size and SHA-256 reach Dropbox. An upload may be up to 50,000,000 bytes, including when it needs approval (proxy_upload_too_large / proxy_approved_upload_too_large, see errors). On the CLI, alter integrations execute dropbox dropbox.files_upload --body-file <path> sends a large file the same way.

Dropbox accepts up to 150 MB per files.upload call, but one upload through Alter carries at most 50,000,000 bytes. A larger file goes up in pieces of at most that size with Dropbox’s upload sessions: files.uploadSessionStart with the first piece, files.uploadSessionAppendV2 for each next piece (with the session id and the byte offset), and files.uploadSessionFinish with the last piece and the destination commit arguments. Only uploadSessionFinish creates the file, so a folder or approval rule placed on it (and on files.upload) governs every file a session writes.

A download of any size can be streamed instead of buffered: the typed <method>Stream() / <method>_stream() methods (or integrations.executeStream() / integrations.execute_stream() with the operation id), and alter integrations execute ... --output-file <path> --stream on the CLI, write the bytes as they arrive. A buffered call whose response is larger than 5 MiB is never returned partially: it raises ProviderResponseTooLargeError (the provider answered, so a write may have happened), whose message names the streaming method to use instead. The CLI exits 1 and suggests --stream --output-file <path>.

Every operation keeps the families of Dropbox’s policy catalog, so the same rules govern a raw request and an SDK call:

  • read for reads, listings, searches, downloads and job-status checks.
  • write for uploads, folder creation, copies, moves, restores, tags, properties, Paper documents and locks.
  • delete for deletes, archives, and member or group removal.
  • admin for sharing settings and membership, Business member, group, session, legal-hold and team-folder management, and every route that hands out access outside the account (temporary links, shared links, copy references and file requests). These are ordinary operations: a family or operation rule can deny, limit or hold them like any other.
  • send for every route that emails people (member invitations, welcome and verification mails).

A folder rule reads one path parameter on every location-taking route, from the JSON body or from Dropbox-API-Arg: {"name": "path", "op": "not_under", "value": ["/clients/wallflower"]} keeps a grant inside one folder. Dropbox compares paths ignoring case, and so does the rule. A listing’s continuation cursor stays bound to the folder it was issued for. See Set policies.

Payload capture follows the application’s setting for managed, raw and SDK-reported Dropbox calls alike. In a stored capture, shared and temporary links, file-request URLs, copy references and passwords are masked wherever they appear, and file bytes (uploads and downloads) are not stored. Shared-link passwords (in link settings and when reading through a protected link) and an upload’s bytes are held encrypted under an approval and shown masked.

These routes stay cataloged, so policy and audit name them on a raw request, but they are not SDK methods:

  • The token lifecycle: auth/token/revoke revokes the connection’s own token and auth/token/from_oauth1 returns a new one. Both are refused by default as credential minting; an organization admin can allow them with a credential_minting rule.
  • Privilege grants: adding or changing file and folder collaborators (sharing/add_file_member, add_folder_member, update_file_member, update_folder_member), transferring folder ownership (sharing/transfer_folder), adding team members with a role, assigning admin roles (team/members/add, members/add:2, members/set_admin_permissions, members/set_admin_permissions:2) and making a group member an owner (team/groups/members/add, groups/members/set_access_type). They remain callable as raw requests, where policy governs them like any write.
  • check/app (app authentication with the app key and secret, which a connection does not hold), files/list_folder/longpoll (it takes no authentication, and Alter always sends the connection’s token), sharing/relinquish_access (it needs a scope Dropbox does not offer to third-party apps), and every deprecated route (use its replacement).

The pinned official source (Dropbox’s Stone files at one commit), its hash, the generated methods and the policy mapping are checked together. Scheduled checks save upstream candidates and report additions, removals and schema changes; they never replace a published contract automatically. Existing contract versions remain available for installed SDKs and pending approvals.

Persist call.approvalId (TypeScript) or call.approval_id (Python), then construct a fresh provider client and call resume(savedId), followed by wait(). The stored approval selects the operation; this installed package verifies its provider and contract version before attaching the response validator. Mismatches raise ManagedOperationError, never silently decode using another contract. See persist-and-resume examples.

Policy operation fields also accept the published SDK function IDs listed by alter integrations operations dropbox. Use when.operation for a json_match or conditional require_approval rule, or match.operations for content_match (including redaction and step-up). Conditional approval can also use when.match.operations with parameter conditions. alter policy simulate --operation <function-id> tests that exact function.

Managed calls carry a server-verified function identity. Alter still evaluates policy against the actual method, URL and body after building the request from the authorized connection. Existing endpoint, method, host, catalog-operation and family rules continue to apply unchanged. A raw call can share an endpoint with several SDK functions and matches all of them; a function name never grants permission or bypasses existing restrictions.

For example, this rule requires approval for one function:

{
"effect": "require_approval",
"when": { "operation": "dropbox.files_upload" },
"approval": { "approvers": ["reviewer@example.com"] }
}

Save it with alter policy rules create --app <app-id> --grant <grant-id> --type require_approval --body @rule.json, or select the function in the portal.

Report an issue with this page

Necessary

Required for sign-in, security, authorization, and remembering your choices.

Always active

Analytics

Helps us understand which product and documentation features are useful.

Performance diagnostics

Uses performance tracing and privacy-masked session replay to diagnose problems.

You can change these choices at any time from Cookie settings.