Overview
Client-mode connectors for the Box Platform API that move plant files between the broker and Box. A typical flow writes a shift report, batch record or alarm snapshot as a JSON or CSV file into a plant folder, uploads today’s setpoint table as a new version of the same file, reads a recipe back when a line changes over, tags a batch record with metadata (line, batch, product, quality state) and releases it with a metadata update, finds files by metadata or by search, moves processed files to an archive folder, and shares a weekly report with a shared link. New files in an inbox folder can be picked up with a V2 webhook (needs a public HTTPS receiver) or by polling the user event stream with a stream position. Box serves uploads from a separate host, so the template fileBoxRestApi.lot holds two connectors:
The connectors carry 44 events (24 GET, 14 POST, 6 PUT; 18 writes, no delete). Topics use
storage/box/<object>/<verb>; each response is published on <source topic>/response.
The template was checked against the Box OpenAPI spec (version 2024.0: host, method, path, path and required query parameters, required headers, request content type, and every example body, query and upload attribute against the request schema) and against a local mock of the API, upload and download hosts. Box checks the token before it connectors a request on
api.box.com, so without a token every event answers 400 Malformed auth header (empty token) or 401 invalid_token (dummy token). On upload.box.com the two upload paths answered 401 while the same paths with a suffix answered 400 Invalid API request path. /oauth2/token was called live and rejected dummy client credentials and an unknown box_subject_type. Nothing has run with a real token yet, so the status stays blocked until an authenticated read and an upload pass.Setup
- In the Box Developer Console, create a Platform App (Custom App) with Server Authentication (Client Credentials Grant). JWT server authentication works the same way, but the broker then needs a signed JWT assertion for each token request.
- Under App Access Level, keep App Access Only (the app works as its own service account) or pick App + Enterprise Access if it must act as a managed user. Under Application Scopes, enable Read all files and folders stored in Box and Write all files and folders stored in Box (
root_readwrite), Manage webhooks (manage_webhook) for the webhook events, and Manage enterprise properties (manage_enterprise_properties) only if the broker reads enterprise metadata templates. - Authorize the app in the Box Admin Console (free developer accounts authorize it automatically) and reauthorize it after every scope change.
- Note the Client ID and Client Secret (Configuration tab) and the Enterprise ID (General Settings). Keep them in broker secrets, for example
BOX_CLIENT_ID,BOX_CLIENT_SECRETandBOX_ENTERPRISE_ID, and the current token inBOX_ACCESS_TOKEN. Inject them in a LoT action withGET SECRET. - The service account has its own, empty root folder. Invite it (its login looks like
AutomationUser_…@boxdevedition.com, returned byUserMe) as an Editor collaborator on the plant folders the broker should use, and use those folder ids in payloads.
Authentication
Every event exceptOAuthToken sends Authorization: Bearer <token> built from the access_token field of the payload:
OAuthToken (storage/box/oauth/token/create). It sends no Authorization header; the client credentials travel in the form. Use box_subject_type enterprise with the enterprise id for the service account, or user with a user id for a managed user (needs App + Enterprise Access and Generate user access tokens):
access_token and expires_in (about 3600 seconds). The Client Credentials Grant returns no refresh token, so request a new token before the old one expires. JWT apps send grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=<signed JWT>&client_id=...&client_secret=... instead.
Payloads
Send
query as an empty string when you need no parameters; the connector then calls, for example, /2.0/users/me?. Use fields to keep responses small enough for MQTT.
Uploading files
Box takes uploads asmultipart/form-data with two parts: attributes (JSON with name and, for a new file, parent.id) and then file. The attributes part must come first; otherwise Box answers 400 metadata_after_file_contents. The upload connector sets Content-Type: multipart/form-data; boundary=CorefluxBoxBoundary, so the payload field multipart must hold the whole body with that boundary and CRLF line ends:
storage/box/files/upload (build the string in a LoT action or on the publishing client; \r\n are the CRLF line ends):
201 with a collection holding the new file (id, sha1, file_version). If a file with that name already exists in the folder, Box answers 409 item_name_in_use; upload a new version instead with FileVersionUpload (storage/box/files/versions/upload, same body, file_id in the payload, attributes with only name). Direct uploads accept up to 50 MB, but keep MQTT payloads small.
Examples
List a folder (storage/box/folders/items/list):
storage/box/files/download):
302 with a short-lived dl.boxcloud.com link, which needs no token. The broker’s HTTP client must follow it to publish the file content. Keep downloads to text and JSON files that fit an MQTT message.
Tag a batch record and release it later (storage/box/files/metadata/create, then storage/box/files/metadata/update with JSON Patch):
test operation makes the update fail with 409 if somebody changed the value in the meantime.
Find released batch records of line 2 (storage/box/metadata/query):
storage/box/files/update):
storage/box/files/shared-link/add):
storage/box/webhooks/create). The address must be HTTPS on port 443:
storage/box/events/list):
- Get the current position:
{"access_token": "<token>", "query": "stream_position=now"}returnsnext_stream_positionand no events. - Ask for changes since then:
{"access_token": "<token>", "query": "stream_type=changes&stream_position=<next_stream_position>&limit=100"}. Store the newnext_stream_positionafter every call. Box may return an event more than once or out of order, so de-duplicate byevent_id.
Events
Limits
- Box allows about 1000 API requests per minute and 240 upload requests per minute per user, and 6 searches per second (60 per minute) per user. Above the limit it answers
429with aretry-afterheader. Wait that long before you retry. - Direct uploads accept files up to 50 MB. Larger files need chunked upload sessions, which are not packaged.
FolderItemsListreturns at most 1000 entries per page (useusemarker=trueandmarker),Searchat most 200,EventsListat most 500.- One webhook per item and app, at most 1000 webhooks per app and user, HTTPS on port 443 only.
- File versions are tracked on paid accounts only. Recent items cover the last 90 days or 1000 items.
- Box indexes new and changed files with a delay, so
Searchmay not find a file that was just uploaded.MetadataQueryandFolderItemsListsee it right away.
Not packaged
- Delete events on purpose: files, folders, trash (permanent delete), file versions, metadata instances, shared link removal, collaborations, comments, tasks and webhooks. Archive files with
FileUpdateorFolderUpdate(move) instead. - Chunked upload sessions for files over 50 MB, the upload preflight check (
OPTIONS /2.0/files/content), thumbnails, zip downloads and the long-poll real-time server (OPTIONS /2.0/events). - The
As-Userheader (act on behalf of another user from an admin token); request a user token withbox_subject_type=userinstead. TheIf-Match/If-None-Matchheaders and thecontent-md5upload header. - Collaboration create and update (granting access), users and groups administration, legal holds, retention, Shield, Sign, Box AI, Hubs, Doc Gen and enterprise events (
admin_logs). - The webhook receiver. A receiver would be a separate
ENABLE_SERVERREST_API connector on a public HTTPS address that checksBOX-SIGNATURE-PRIMARY/BOX-SIGNATURE-SECONDARY(HMAC-SHA256 of the body plusBOX-DELIVERY-TIMESTAMPwith the app’s signature keys) and rejects old timestamps.EventsListcovers the same need without a public endpoint.
Suggested branches
feat/rest-api-route-box for the broker template and feat/docs-rest-api-box for this page.
