Skip to main content
SFDC Developers
Apex

Box.com Salesforce Integration: Apex Backend Guide

Vinay Vernekar · · 4 min read

Introduction

Integrating Salesforce with Box.com is a common requirement for organizations looking to offload file storage while maintaining a seamless user experience within the CRM. While managed packages exist, building a custom backend integration using Apex provides the granular control, performance optimization, and custom logic necessary for enterprise-scale operations. In this guide, we'll explore how to architect a custom integration using the Box REST API.

Establishing Secure Connectivity with OAuth 2.0

The foundation of any backend integration is authentication. Box uses OAuth 2.0. In a server-to-server or app-user scenario, we typically use JWT (JSON Web Token) authentication to avoid manual user login prompts.

First, you must create a Custom App in the Box Developer Console, configure the public/private key pair, and add the App Service Account to your target Box folder. In Salesforce, you need to store your Private Key securely in a Custom Metadata Type or an encrypted field.

To initiate the flow, use a service class to generate a JWT assertion, sign it using Crypto.sign(), and exchange it for an access token:

public class BoxAuthService {
    private static final String BOX_TOKEN_URL = 'https://api.box.com/oauth2/token';

    public static String getAccessToken() {
        // Generate JWT assertion here...
        // Prepare request body for OAuth exchange
        HttpRequest req = new HttpRequest();
        req.setEndpoint(BOX_TOKEN_URL);
        req.setMethod('POST');
        req.setBody('grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=' + assertion + ...);
        
        Http http = new Http();
        HTTPResponse res = http.send(req);
        // Parse JSON response to extract access_token
        return token;
    }
}

Implementing File Uploads via Apex REST

Once authorized, the most frequent use case is uploading Salesforce files or attachments to Box. Box expects a multipart/form-data request for file uploads. This is often the most challenging part for developers due to the complexity of building the boundary string.

We recommend building a helper method to construct the request body. Ensure your Named Credential is configured for api.box.com to manage endpoints cleanly.

public static void uploadFileToBox(String fileName, Blob fileContent, String folderId) {
    String boundary = '--------------------------' + String.valueOf(Crypto.getRandomInteger());
    String body = '--' + boundary + '\r\n' +
        'Content-Disposition: form-data; name="attributes"; filename="' + fileName + '"\r\n' +
        'Content-Type: application/json\r\n\r\n' +
        '{"name":"' + fileName + '", "parent":{"id":"' + folderId + '"}}\r\n' +
        '--' + boundary + '\r\n' +
        'Content-Disposition: form-data; name="file"; filename="' + fileName + '"\r\n' +
        'Content-Type: application/octet-stream\r\n\r\n';
    
    // Append binary file content and closing boundary...
}

Handling Asynchronous Operations

Salesforce governor limits on heap size and callout counts make synchronous file processing risky for large files. Always offload your Box integrations to Queueable Apex. This allows you to retry failed requests and ensures that the user interface remains responsive.

Here is a pattern for an asynchronous file uploader:

public class BoxUploadQueueable implements Queueable, Database.AllowsCallouts {
    private Id contentVersionId;

    public BoxUploadQueueable(Id cvId) { this.contentVersionId = cvId; }

    public void execute(QueueableContext qc) {
        ContentVersion cv = [SELECT Title, VersionData FROM ContentVersion WHERE Id = :contentVersionId];
        // Perform Box API Callout
        // Handle 429 (Rate Limit) errors with a retry policy
    }
}

Monitoring and Error Handling

Integration failure is inevitable. Implementing a robust logging framework is critical for debugging Box API errors. We suggest capturing the X-Box-Request-Id header from every response. If an upload fails, log the response body and the request ID to a custom Integration_Log__c object.

  • 401 Unauthorized: Refresh your JWT token and retry.
  • 429 Too Many Requests: Implement a Retry-After header check.
  • 404 Not Found: Validate the parent folderId exists before proceeding.

Key Takeaways

  • Authentication: Use JWT authentication for server-side integration to ensure headless, secure connectivity.
  • Multipart/Form-Data: Carefully construct the multipart boundary when performing file uploads via HttpRequest.
  • Scalability: Always use Queueable Apex for callouts to respect governor limits and allow for asynchronous retries.
  • Security: Never hardcode credentials; use Named Credentials and Custom Metadata or Encrypted Fields for sensitive keys.
  • Monitoring: Log specific Box Request IDs to simplify troubleshooting when the API returns an error.

Share this article

Vinay Vernekar

Vinay Vernekar

Salesforce Developer & Founder

Vinay is a seasoned Salesforce developer with over a decade of experience building enterprise solutions on the Salesforce platform. He founded SFDCDevelopers.com to share practical tutorials, best practices, and career guidance with the global Salesforce community.

Get weekly Salesforce dev tutorials in your inbox

Comments

Loading comments...

Leave a Comment

Trending Now