Skip to main content
Technical Preview

Overview

Client-mode connectors for the Dropbox API v2 that move plant files between the broker and Dropbox. A typical flow writes a shift report, batch record or alarm snapshot as a JSON or CSV file into a plant folder, reads a recipe or configuration file back when a line changes over, watches an inbox folder for files that people drop in (cursor plus longpoll, no polling loop), moves processed files to an archive folder, and hands out a temporary link or a shared link to a report. File requests let technicians and suppliers upload photos, certificates and PDFs into a plant folder without a Dropbox account. Dropbox splits its API over three hosts with different request formats, so the template file DropboxRestApi.lot holds three connectors: The connectors carry 38 events (36 POST, 2 GET; 13 writes, no delete). Topics use storage/dropbox/<object>/<verb>; each response is published on <source topic>/response.
The template was checked against the Dropbox Stone API spec (host, request style, argument fields, required fields, deprecation and latest version of every function) and against a local mock of all three hosts. Without a token, Dropbox answered every packaged function with 400 Error in call to API function "<function>": Invalid authorization value, which names the function, while the same path with a suffix answered 404. With a dummy token every Bearer event answered 401 invalid_access_token. files/list_folder/longpoll and /oauth2/token were also called live and rejected the dummy cursor and app credentials. Nothing has run with a real token yet, so the status stays blocked until an authenticated read and an upload pass.

Setup

  1. In the App Console, create a Scoped access app. Pick App folder to keep the broker inside /Apps/<app name>/, or Full Dropbox if it must reach existing team folders. Paths in payloads are relative to that root.
  2. Under Permissions, enable the scopes the events need: account_info.read, files.metadata.read, files.metadata.write, files.content.read, files.content.write, sharing.read, sharing.write, file_requests.read, file_requests.write. Leave out the ones you do not use.
  3. Authorise the app once with token_access_type=offline (for example https://www.dropbox.com/oauth2/authorize?client_id=<APP_KEY>&token_access_type=offline&response_type=code) and exchange the code at /oauth2/token. Keep the refresh token, app key and app secret in broker secrets (for example DROPBOX_REFRESH_TOKEN, DROPBOX_APP_KEY, DROPBOX_APP_SECRET). For a quick test, Generate access token on the app’s settings page gives a short-lived token.
  4. Keep the current access token in a broker secret (for example DROPBOX_ACCESS_TOKEN) and inject it in a LoT action with GET SECRET. Never retain topics that carry it.

Authentication

Every event on DropboxRestApi and DropboxContentRestApi sends Authorization: Bearer <token> built from the access_token field of the payload:
Dropbox access tokens are short-lived: /oauth2/token returns expires_in 14400 (4 hours). Refresh the token before it expires with OAuthTokenRefresh (storage/dropbox/oauth/token/refresh). That event sends no Authorization header; the app key and secret travel in the form:
The OAuthTokenRefresh response carries the new access_token, and the request carries the app secret. Restrict storage/dropbox/oauth/# with ACLs, never retain those topics, and store the new token in the secret instead of passing it around on open topics.
FolderLongpoll takes no token at all. Dropbox answers 400 if a longpoll request includes an Authorization header, so DropboxNotifyRestApi sends none.

Payloads

Paths are relative to the app folder or the Dropbox root. The root is ""; every other path starts with / and never ends with /. File ids (id:...) work wherever the reference accepts a path or id. The Dropbox-API-Arg header must be HTTP-header-safe: escape non-ASCII characters and 0x7F as \uXXXX (a standard JSON encoder with ASCII output does this).

Examples

Write a shift report as a JSON file (storage/dropbox/files/upload):
Dropbox answers with the file metadata (id, rev, size, content_hash). Use "mode": "overwrite" to replace a file, or {".tag": "update", "update": "<rev>"} to replace it only if nobody changed it since that revision. Read a recipe back on changeover (storage/dropbox/files/download):
The response body is the file content. Dropbox sends the file metadata in the Dropbox-API-Result response header. Keep downloads to text and JSON files that fit an MQTT message. Watch an inbox folder for new files without polling:
  1. Get a cursor for future changes (storage/dropbox/folders/latest-cursor/get):
  2. Wait for a change (storage/dropbox/folders/longpoll, no token). The call blocks for up to timeout seconds plus up to 90 seconds of jitter, then returns {"changes": true} or {"changes": false}, sometimes with backoff (seconds to wait before the next longpoll):
  3. When changes is true, list them (storage/dropbox/folders/list/continue) and store the new cursor from the response:
A 409 with reset means the cursor expired. Start again with FolderList or FolderLatestCursorGet. Archive a processed file instead of deleting it (storage/dropbox/files/move):
Hand a firmware file to an edge device with a direct link that expires after four hours (storage/dropbox/files/temporary-link/get):
Ask a technician for photos of a failed bearing (storage/dropbox/file-requests/create):

Events

Limits

  • Dropbox rate-limits per linked user (per team for team-linked apps) and does not publish the numbers. Above the limit it answers 429 with a Retry-After header. Wait that long, and batch work (FolderCreateBatch, CopyBatch, MoveBatch) instead of sending many single calls.
  • FileUpload accepts up to 150 MiB per file, but keep MQTT payloads small. Larger files need upload sessions, which are not packaged.
  • On Dropbox Business plans with a data transport limit, upload and download calls count against the team’s monthly allowance. Over the limit Dropbox answers 403 invalid_account_type/feature.
  • FolderList returns at most 2000 entries per page; follow has_more with FolderListContinue. FolderLongpoll accepts a timeout from 30 to 480 seconds, and the notify connector allows 600 seconds per request.
  • Temporary links expire after four hours. Temporary upload links last 60 to 14400 seconds. SaveUrl transfers must finish within 15 minutes.

Not packaged

  • Delete-style functions on purpose: files/delete_v2, delete_batch, permanently_delete, files/tags/remove, shared link revoke and file request delete. Archive files with FileMove instead.
  • Upload sessions (upload_session/start, append_v2, finish, batch variants) for files over 150 MiB, and binary downloads such as thumbnails, previews, download_zip and export.
  • Team (Business) endpoints and the Dropbox-API-Select-User, Dropbox-API-Select-Admin and Dropbox-API-Path-Root headers for team spaces. Shared folder membership, Paper, file properties templates, file locking, contacts and account administration.
  • Webhooks. Dropbox registers webhook URIs in the App Console, not through the API. A receiver would be a separate ENABLE_SERVER REST_API connector that answers the GET verification by echoing challenge within ten seconds and checks X-Dropbox-Signature (HMAC-SHA256 of the body with the app secret). Notifications only carry account ids, so the connector would then call FolderListContinue. FolderLongpoll covers the same need without a public endpoint.

Suggested branches

feat/rest-api-route-dropbox for the broker template and feat/docs-rest-api-dropbox for this page.
Last modified on October 21, 2026