Skip to content

feat(box): add Box and Box Sign integrations#3660

Merged
waleedlatif1 merged 16 commits intostagingfrom
waleedlatif1/box-sign-integration
Mar 19, 2026
Merged

feat(box): add Box and Box Sign integrations#3660
waleedlatif1 merged 16 commits intostagingfrom
waleedlatif1/box-sign-integration

Conversation

@waleedlatif1
Copy link
Collaborator

@waleedlatif1 waleedlatif1 commented Mar 19, 2026

Summary

  • Add Box integration with 10 file management tools: upload, download, get file info, list folder items, create folder, delete file, delete folder, copy file, search, and update file metadata
  • Add Box Sign integration with 5 e-signature tools: create sign request, get sign request, list sign requests, cancel sign request, and resend sign request
  • Add OAuth provider configuration with root_readwrite scope, token refresh support, and user info via Box API
  • Add internal upload API route (/api/tools/box/upload) following the Dropbox pattern for proper UserFile handling
  • Add block configurations for both Box and Box Sign with operation dropdowns and conditional fields
  • Add BoxCompanyIcon and generated documentation with manual intro sections

Test plan

  • Verify OAuth flow connects to Box successfully
  • Test file upload via the Box block (both basic file-upload and advanced reference modes)
  • Test file download returns proper UserFile object
  • Test Box Sign create request sends document for e-signature
  • Test list/get/cancel/resend sign request operations
  • Verify block UI shows correct fields per operation
  • Verify docs pages render correctly at /tools/box and /tools/box_sign

@vercel
Copy link

vercel bot commented Mar 19, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
docs Ready Ready Preview, Comment Mar 19, 2026 6:07am

Request Review

@cursor
Copy link

cursor bot commented Mar 19, 2026

PR Summary

Medium Risk
Adds a new OAuth provider (box) plus new API route and tool implementations that call external Box/Box Sign APIs; mistakes could impact auth flows or file upload handling.

Overview
Adds new Box and Box Sign integrations end-to-end: new BoxBlock/BoxSignBlock with operation-driven UI fields, and registers 15 new tools for Box file operations and Box Sign request management.

Introduces box as an OAuth provider (env vars, provider types/config, scopes, and user-info fetch) and adds an internal upload endpoint (/api/tools/box/upload) to handle UserFile uploads to Box.

Updates docs to include box/box_sign pages and icon mapping, and tweaks AmplitudeIcon to use currentColor instead of a hardcoded fill.

Written by Cursor Bugbot for commit 8bd8170. Configure here.

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 19, 2026

Greptile Summary

This PR adds a comprehensive Box integration (10 file management tools) and Box Sign e-signature integration (5 tools) via a unified block config, an internal upload API route, OAuth provider registration, and generated documentation. The implementation closely follows the existing Dropbox/Attio patterns and addresses several issues raised in prior review rounds (silent signer JSON failure, empty file ID filtering, docs link fix, tags split guard). Two new functional issues were identified during this review: the direction sort parameter is always sent to the list_folder_items endpoint even when no sort is specified (which the Box API docs explicitly prohibit), and the fileExtensions search filter is passed raw without per-extension trimming (silently breaking searches with spaced inputs like "pdf, docx"). A cosmetic inconsistency also remains in the cancel endpoint, which still sends an unnecessary empty JSON body.

  • direction always sent without sort (apps/sim/blocks/blocks/box.ts): The direction dropdown defaults to 'ASC' and is always truthy, so direction=ASC is unconditionally appended to list_folder_items requests even when sort is left at "Default". Box API docs state the field must be used with sort.
  • fileExtensions not split/trimmed (apps/sim/tools/box/search.ts): Space-padded extensions like "pdf, docx" are passed verbatim, causing silent filter failures. The same class of bug was already fixed for sourceFileIds in create_request.ts.
  • Cancel endpoint sends empty body (apps/sim/tools/box_sign/cancel_request.ts): The reason parameter was correctly removed, but body: () => ({}) and a Content-Type: application/json header remain on an endpoint that accepts no body.
  • Dead code in the box block tool selector (both branches of the if (op.startsWith('sign_')) check return identical values) was noted in prior threads and is not repeated here.

Confidence Score: 3/5

  • Safe to merge after fixing the direction/sort contract violation and the fileExtensions trimming gap.
  • The core OAuth flow, upload route, and all Box Sign tools are well-implemented and consistent with codebase patterns. Two P1 logic issues exist: unconditionally sending direction without sort violates the Box API spec and could cause unexpected list behavior, and untrimmed fileExtensions silently breaks search filters with natural user input. These are functional regressions in otherwise new code, pulling the score down from a 4.
  • apps/sim/blocks/blocks/box.ts (direction/sort guard) and apps/sim/tools/box/search.ts (fileExtensions trimming) need fixes before merge.

Important Files Changed

Filename Overview
apps/sim/blocks/blocks/box.ts Unified Box + Box Sign block config with 15 operations; contains dead code in the tool selector (both if/else branches return identical values) and the direction parameter is unconditionally sent without the required sort parameter.
apps/sim/tools/box/search.ts Box search tool; fileExtensions is passed directly to the API without splitting/trimming per extension, meaning inputs like "pdf, docx" will silently produce incorrect filters — unlike the already-fixed sourceFileIds handling.
apps/sim/tools/box_sign/cancel_request.ts Cancel sign request tool; correctly has no reason parameter (fixed per prior thread), but still sends an unnecessary Content-Type header and empty JSON body to an endpoint that accepts no request body.
apps/sim/app/api/tools/box/upload/route.ts Internal upload route following the Dropbox pattern; correctly handles both UserFile and legacy base64 paths, uses checkInternalAuth, and properly constructs the multipart FormData request to the Box upload endpoint.
apps/sim/tools/box_sign/create_request.ts Box Sign create request tool; properly throws on malformed additionalSigners JSON (fixed per prior thread) and filters empty file IDs (fixed per prior thread). Clean implementation.
apps/sim/lib/auth/auth.ts Adds Box OAuth provider config with correct authorization/token URLs and getUserInfo implementation; uses the same randomUUID id pattern as all other providers in the codebase (intentional design).
apps/sim/tools/box/upload_file.ts Delegates to the internal /api/tools/box/upload route; accessToken in body follows the same pattern as the Dropbox integration (acknowledged in prior thread).
apps/sim/tools/box/update_file.ts Update file tool; correctly applies .filter(Boolean) on tags split (fixed per prior thread). All optional fields guarded appropriately.
apps/sim/tools/box_sign/resend_request.ts Resend sign request tool; correctly sends no body, handles 202 Accepted (response.ok is true for 2xx), and avoids parsing empty response body on success path.
apps/sim/lib/oauth/oauth.ts Adds Box OAuth provider config with root_readwrite scope and token refresh support; follows the same pattern as all other providers in the file.

Sequence Diagram

sequenceDiagram
    participant User as User / LLM
    participant Block as Box Block (box.ts)
    participant UploadRoute as /api/tools/box/upload
    participant BoxUpload as upload.box.com
    participant BoxAPI as api.box.com
    participant BoxSign as api.box.com/sign_requests

    User->>Block: Select operation + provide params
    Block->>Block: tool() → box_${op}
    Block->>Block: params() → baseParams with accessToken

    alt upload_file
        Block->>UploadRoute: POST {accessToken, parentFolderId, file}
        UploadRoute->>UploadRoute: checkInternalAuth()
        UploadRoute->>UploadRoute: processFilesToUserFiles()
        UploadRoute->>UploadRoute: downloadFileFromStorage()
        UploadRoute->>BoxUpload: POST multipart/form-data
        BoxUpload-->>UploadRoute: 201 {entries[0]}
        UploadRoute-->>Block: {success, output}
    else download_file / get_file_info / list / create / delete / copy / search / update
        Block->>BoxAPI: GET/POST/PUT/DELETE with Bearer token
        BoxAPI-->>Block: JSON response
    else sign_create_request
        Block->>BoxSign: POST /sign_requests {source_files, signers, …}
        BoxSign-->>Block: Sign request object
    else sign_get / sign_list / sign_cancel / sign_resend
        Block->>BoxSign: GET/POST /sign_requests/{id}
        BoxSign-->>Block: Response (object or 202 no-body)
    end

    Block-->>User: Structured output
Loading

Comments Outside Diff (3)

  1. apps/sim/blocks/blocks/box.ts, line 1120-1124 (link)

    direction always sent without sort violates Box API contract

    The direction dropdown defaults to 'ASC' (always truthy), so baseParams.direction is unconditionally added for every list_folder_items call. However, sort uses value: () => '' and is only added when non-empty — meaning when the user leaves "Sort By" at "Default", the request includes direction=ASC but no sort parameter.

    The Box API documentation explicitly states: "This field must be used in conjunction with the sort field." Sending direction without sort is technically against the API contract and may produce unexpected results or errors for users who never open the advanced panel.

    Consider guarding the direction param on whether sort is also set:

  2. apps/sim/tools/box/search.ts, line 2092 (link)

    fileExtensions not trimmed per extension

    fileExtensions is passed directly to the file_extensions query parameter without splitting and trimming individual values. If a user enters "pdf, docx" (common natural input with a space after the comma), the URL will contain file_extensions=pdf%2C+docx, and Box will interpret one extension as pdf and a second as docx (with a leading space), causing the filter to silently fail.

    The same class of bug was already fixed for sourceFileIds in create_request.ts using .filter(Boolean) and .trim(). The same treatment should apply here:

  3. apps/sim/tools/box_sign/cancel_request.ts, line 2637-2642 (link)

    Unnecessary Content-Type header and empty body on cancel endpoint

    The previous thread fixed the reason parameter, but the request still sends a Content-Type: application/json header and an empty body {} to an endpoint that accepts no request body at all. While Box silently ignores the extra payload, the header and body are incorrect per the API spec and add unnecessary bytes to every cancel call.

Last reviewed commit: "style(box,docusign):..."

@waleedlatif1
Copy link
Collaborator Author

@greptile

@waleedlatif1
Copy link
Collaborator Author

@greptile

@waleedlatif1
Copy link
Collaborator Author

@greptile

@waleedlatif1
Copy link
Collaborator Author

@greptile

@waleedlatif1
Copy link
Collaborator Author

@greptile

@waleedlatif1
Copy link
Collaborator Author

@greptile review

@waleedlatif1
Copy link
Collaborator Author

@greptile review

waleedlatif1 and others added 3 commits March 18, 2026 22:09
Add complete Box integration with file management (upload, download, get info, list folders, create/delete folders, copy, search, update metadata) and Box Sign e-signature support (create/get/list/cancel/resend sign requests). Includes OAuth provider setup, internal upload API route following the Dropbox pattern, block configurations, icon, and generated docs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix docsLink for Box Sign: use underscore (box_sign) to match docs URL
- Move normalizeFileInput from tool() to params() in Box block config to match Dropbox pattern
- Throw error on invalid additionalSigners JSON instead of silently dropping signers

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The Box Sign cancel endpoint (POST /sign_requests/{id}/cancel) does not
accept a request body per the API specification. Remove the misleading
reason parameter from the tool, types, block config, and docs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
waleedlatif1 and others added 8 commits March 18, 2026 22:09
The params function must reference canonical IDs (params.file), not raw
subBlock IDs (uploadFile/fileRef) which are deleted after canonical
transformation. Matches the Dropbox block pattern.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Rename "Uploaded file ID/name" to "File ID/name" in
UPLOAD_FILE_OUTPUT_PROPERTIES since the constant is shared by both
upload and copy operations.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Rename the output field from "items" to "entries" to match Box API
naming and avoid collision with JSON schema "items" keyword that
prevented the docs generator from rendering the nested array structure.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add .filter(Boolean) after splitting sourceFileIds to prevent empty
strings from trailing/double commas being sent as invalid file IDs
to the Box Sign API.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Combine Box and Box Sign into one unified block with all 15 operations
accessible via a single dropdown, removing the separate box_sign block.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@waleedlatif1
Copy link
Collaborator Author

@greptile

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Box's OAuth2 token endpoint does not return a scope field in the
response, so Better Auth stores nothing in the DB. This causes the
credential selector to always show "Additional permissions required".
Fix by populating the scope from the requested scopes in the
account.create.before hook.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Box Sign API requires the sign_requests.readwrite scope in addition
to root_readwrite. Without it, sign requests fail with "The request
requires higher privileges than provided by the access token."

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@waleedlatif1 waleedlatif1 merged commit cef321b into staging Mar 19, 2026
5 of 6 checks passed
@waleedlatif1 waleedlatif1 deleted the waleedlatif1/box-sign-integration branch March 19, 2026 06:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant