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.
Install
Section titled “Install”npm install @alter-ai/sdk @alter-ai/dropbox# Python (installs core automatically)pip install alter-sdk-dropboxThe provider package includes only Dropbox types and response schemas and pins its contract version.
Connect and call
Section titled “Connect and call”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 Appfrom 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()Complete versioned contract
Section titled “Complete versioned contract”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.
alter integrations execute dropbox dropbox.files_create_folder_v2 \ --version 2026-11-01 --grant "$DROPBOX_GRANT_ID" \ --input '{"body": {"path": "/Clients/Wallflower/2026-11"}}' --waitArguments 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.paperCreateandfiles.paperUpdate) take their arguments underheaders["Dropbox-API-Arg"]and the file asbody. - Download routes (
files.download,files.downloadZip,files.export,files.getPreview,files.getThumbnail,files.getThumbnailV2,account.getPhoto,sharing.getSharedLinkFileandriviera.downloadTransformOutput) take their arguments underheaders["Dropbox-API-Arg"]and answer the file’s bytes, read withbodyBytes()/body_bytes(). Dropbox returns the route’s result (the file’s metadata) in theDropbox-API-Resultresponse 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); // FilesFileMetadataconst 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) # FilesFileMetadatastream = 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.
Approvals
Section titled “Approvals”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.
Uploads and approvals
Section titled “Uploads and approvals”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>.
Policy and sensitive data
Section titled “Policy and sensitive data”Every operation keeps the families of Dropbox’s policy catalog, so the same rules govern a raw request and an SDK call:
readfor reads, listings, searches, downloads and job-status checks.writefor uploads, folder creation, copies, moves, restores, tags, properties, Paper documents and locks.deletefor deletes, archives, and member or group removal.adminfor 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.sendfor 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.
Not published
Section titled “Not published”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/revokerevokes the connection’s own token andauth/token/from_oauth1returns a new one. Both are refused by default as credential minting; an organization admin can allow them with acredential_mintingrule. - 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).
Maintenance
Section titled “Maintenance”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.
Resume after a restart
Section titled “Resume after a restart”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.
Rules for SDK functions
Section titled “Rules for SDK functions”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.