Box integrates with Bolt.new via Box's REST API using OAuth 2.0 or JWT server authentication. Register a Box developer app to get OAuth credentials, implement the authorization code flow in Next.js API routes (requires deployment for redirect URI), then use the box-node-sdk to upload, download, manage folders, and generate shareable links. Box is enterprise-focused with granular permissions and compliance features — OAuth callback requires a deployed URL, not the Bolt preview.
Box in Bolt.new: Enterprise File Management with Content Preview
Box occupies a distinct position in enterprise software: it is not a consumer storage service like Dropbox, nor raw cloud storage like S3. Box is a content management platform built specifically for enterprises that need compliance certifications (HIPAA, FedRAMP, SOC 2, ISO 27001), legal hold capabilities, granular permission management, and admin-level governance over who can access what files. Companies in healthcare, finance, government, and legal sectors often mandate Box as their file storage standard.
For Bolt.new developers building internal enterprise tools — admin dashboards, workflow automation apps, document management systems — Box integration means your app can read and write files that already exist in the organization's Box account. Users don't need to re-upload files; your app accesses the authoritative version. Box's granular sharing model (Viewer, Previewer, Uploader, Editor, Co-owner, Owner) lets you grant precisely the right level of access rather than all-or-nothing sharing.
Box's Content Preview feature is particularly useful in Bolt apps: you can embed a Box-hosted document viewer for PDF, Word, Excel, PowerPoint, and hundreds of other file formats using a preview URL. Users see documents rendered in Box's high-fidelity viewer without downloading them. This eliminates the need for a separate document viewing library in your app. The preview URL is an HTTPS endpoint that Box serves — no special setup required, just include it in an iframe or as a link.
Integration method
Box integrates via its REST API using OAuth 2.0 user authentication or JWT app authentication. You register a Box developer app to get client credentials, implement OAuth authorization in Next.js API routes, use the box-node-sdk to interact with files and folders. Box's Content Preview URL enables embedding document previews directly in your Bolt app. OAuth redirect URI requires a deployed URL — file operations via the SDK are outbound HTTPS and work in the Bolt preview after you have a valid token.
Prerequisites
- A Box developer account at developer.box.com (requires a Box account — free personal Box account works for development)
- A Box application registered in the Box Developer Console (developer.box.com/console) with OAuth 2.0 authentication type
- A Bolt.new Next.js project for API routes and server-side SDK usage
- A deployed Netlify or Bolt Cloud URL for the OAuth redirect URI — Box OAuth callback requires a stable registered URL
- Basic understanding of Box concepts: files vs items, folder IDs (root is '0'), and Box's access level model (Viewer, Editor, Co-owner)
Step-by-step guide
Register a Box App and Configure OAuth
Register a Box App and Configure OAuth
Create a Box application in the Box Developer Console at developer.box.com/console. Click 'Create New App', select 'Custom App', then choose 'User Authentication (OAuth 2.0)' — this is the standard flow for apps that access files on behalf of users. Give your app a name and finish creation. On the app configuration page, the Configuration tab shows your Client ID and Client Secret. Under OAuth 2.0 Redirect URI, add your Netlify callback URL: https://your-app.netlify.app/api/auth/box/callback. Also add http://localhost:3000/api/auth/box/callback for local development (Box allows multiple redirect URIs). Under Application Scopes, enable the permissions your app needs: Read all files and folders stored in Box (read access), Write all files and folders stored in Box (upload/delete), Manage enterprise properties (only needed for metadata and enterprise features). For basic file operations, read + write is sufficient. Copy the Client ID and Client Secret. Add them to your .env file as BOX_CLIENT_ID and BOX_CLIENT_SECRET. Never commit these to git — Box client secrets grant access to your users' files when used with their OAuth token.
Create a .env file with Box OAuth credentials: BOX_CLIENT_ID=your_box_client_id, BOX_CLIENT_SECRET=your_box_client_secret, BOX_REDIRECT_URI=https://your-app.netlify.app/api/auth/box/callback. Add a BOX_CONTRACTS_FOLDER_ID=your_folder_id variable for the specific folder used in upload operations (find folder IDs in the Box URL when browsing: box.com/folder/{id}).
Paste this in Bolt.new chat
1# .env2BOX_CLIENT_ID=your_box_client_id3BOX_CLIENT_SECRET=your_box_client_secret4BOX_REDIRECT_URI=https://your-app.netlify.app/api/auth/box/callback56# Box folder ID for document uploads (get from Box URL: box.com/folder/{ID})7BOX_CONTRACTS_FOLDER_ID=0 # '0' means root folder89# After deployment, add to Netlify Dashboard:10# Site Settings → Environment Variables → add all fourPro tip: Find Box folder IDs by navigating to the folder in box.com — the ID is in the URL: box.com/folder/123456789. The root folder ID is always '0'. Store frequently used folder IDs as environment variables to avoid hardcoding them.
Expected result: Box app is registered with Client ID and Client Secret. OAuth redirect URI points to your Netlify callback URL. Application scopes include read and write access. .env has all Box OAuth variables.
Install box-node-sdk and Set Up OAuth Routes
Install box-node-sdk and Set Up OAuth Routes
Install the box-node-sdk package — Box's official Node.js SDK that wraps all API calls with proper authentication handling. The SDK handles token management, request retry on 429 rate limit errors, and response parsing. Install it with npm (or prompt Bolt) — it is a pure JavaScript package with no native dependencies. The Box OAuth 2.0 flow is standard: your initiation route builds an authorization URL with your client_id, redirect_uri, and state parameter, then redirects the user to Box's login page. After authorization, Box redirects to your callback URL with an authorization code. Your callback route exchanges this code for an access_token (valid 1 hour) and refresh_token (valid 60 days). Using the box-node-sdk for token exchange: BoxSDK.getAuthorizeURL() builds the auth URL, and the SDK's TokenManager.getTokensAuthorizationCodeGrant() exchanges the code for tokens. Alternatively, you can use direct fetch() calls to Box's token endpoint — both approaches work. Store the Box access token and refresh token in httpOnly cookies. The SDK's BoxClient can be initialized with a stored token: BoxSDK.getBasicClient(accessToken) for simple token-based access, or configure the SDK with token auto-refresh using the refresh token for a seamless experience that doesn't require re-authorization every hour.
Install box-node-sdk. Create lib/box.ts that exports: (1) getBoxAuthUrl(state: string): string — builds Box OAuth authorization URL using BOX_CLIENT_ID and BOX_REDIRECT_URI, (2) exchangeCodeForTokens(code: string): Promise<{accessToken, refreshToken}> — exchanges authorization code for tokens via POST to https://api.box.com/oauth2/token, (3) getBoxClient(accessToken: string) — returns a configured BoxClient instance. Create OAuth routes: GET /api/auth/box (generates random state, stores in cookie, redirects to Box auth URL), GET /api/auth/box/callback (validates state, exchanges code for tokens, stores access and refresh tokens in httpOnly cookies, redirects to /dashboard).
Paste this in Bolt.new chat
1// lib/box.ts2import BoxSDK from 'box-node-sdk';34const sdk = new BoxSDK({5 clientID: process.env.BOX_CLIENT_ID!,6 clientSecret: process.env.BOX_CLIENT_SECRET!,7});89export function getBoxAuthUrl(state: string): string {10 return sdk.getAuthorizeURL({11 response_type: 'code',12 redirect_uri: process.env.BOX_REDIRECT_URI,13 state,14 });15}1617export async function exchangeCodeForTokens(18 code: string19): Promise<{ accessToken: string; refreshToken: string }> {20 const res = await fetch('https://api.box.com/oauth2/token', {21 method: 'POST',22 headers: { 'Content-Type': 'application/x-www-form-urlencoded' },23 body: new URLSearchParams({24 grant_type: 'authorization_code',25 code,26 client_id: process.env.BOX_CLIENT_ID!,27 client_secret: process.env.BOX_CLIENT_SECRET!,28 redirect_uri: process.env.BOX_REDIRECT_URI!,29 }),30 });31 const tokens = await res.json();32 if (tokens.error) throw new Error(tokens.error_description);33 return {34 accessToken: tokens.access_token,35 refreshToken: tokens.refresh_token,36 };37}3839export function getBoxClient(accessToken: string) {40 return sdk.getBasicClient(accessToken);41}Pro tip: Box access tokens expire after 1 hour. Implement auto-refresh: before each API call, check if the stored token is within 5 minutes of expiry and use the refresh token to get a new access token. The box-node-sdk can handle this automatically if you configure it with a PersistentTokenStore.
Expected result: box-node-sdk is installed. lib/box.ts exports auth URL generation, token exchange, and client factory. OAuth routes redirect users to Box login and store tokens on return.
Implement Box File Operations
Implement Box File Operations
With the Box SDK initialized, implement the file operations your app needs. The box-node-sdk exposes file and folder operations through a consistent API — most operations return Promises that resolve with Box item objects. Key SDK method groups: - client.folders.getItems(folderId, options) — list folder contents (pass '0' for root) - client.files.get(fileId, options) — get file metadata - client.files.download(fileId) — returns a readable stream of file content - client.files.previewLink(fileId) — generates a Box-hosted preview URL - client.files.getDownloadURL(fileId) — returns a temporary direct download URL - client.files.createSharedLink(fileId, options) — creates a shared link with access level - client.files.uploadFile(parentFolderId, filename, content) — uploads a new file - client.files.uploadNewFileVersion(fileId, content) — uploads a new version of an existing file - client.folders.create(parentFolderId, folderName) — creates a new folder Box folder/file items have a consistent structure: id, name, type ('file' or 'folder'), created_at, modified_at, size, created_by, modified_by. Files also have extension, content_version, and sha1. For file listings, items are returned in a PagingIterator — iterate with hasNextPage() and nextPage() for large folders. The Content Preview URL (from previewLink) is an HTTPS URL to Box's hosted document viewer. Embed it in an iframe for in-app document viewing without downloading the file. The preview URL requires the user to be authenticated with Box — it uses the access token implicitly for users who are already logged in to Box.
Create Box API routes. GET /api/box/folders?folderId={id} — uses client.folders.getItems, returns { items: BoxItem[] } where BoxItem has {id, name, type, size, modified_at}. GET /api/box/files/[id]/preview-url — uses client.files.previewLink, returns { previewUrl: string }. POST /api/box/upload — accepts { filename, contentBase64, parentFolderId }, converts base64 to Buffer, calls client.files.uploadFile, returns { fileId, name, viewUrl }. POST /api/box/share — accepts { fileId, accessLevel: 'open'|'company'|'collaborators' }, calls client.files.createSharedLink with the specified access, returns { shareUrl }. All routes read box_at cookie for auth.
Paste this in Bolt.new chat
1// app/api/box/folders/route.ts2import { NextRequest, NextResponse } from 'next/server';3import { getBoxClient } from '@/lib/box';45export async function GET(request: NextRequest) {6 const accessToken = request.cookies.get('box_at')?.value;7 if (!accessToken) return NextResponse.json({ error: 'Not authenticated' }, { status: 401 });89 const { searchParams } = new URL(request.url);10 const folderId = searchParams.get('folderId') || '0'; // '0' = Box root folder1112 const client = getBoxClient(accessToken);1314 try {15 const items = await client.folders.getItems(folderId, {16 fields: 'id,name,type,size,modified_at,extension',17 limit: 100,18 });1920 const formattedItems = items.entries.map(21 (item: {22 id: string;23 name: string;24 type: string;25 size?: number;26 modified_at: string;27 extension?: string;28 }) => ({29 id: item.id,30 name: item.name,31 type: item.type,32 size: item.size,33 modified_at: item.modified_at,34 extension: item.extension,35 })36 );3738 return NextResponse.json({ items: formattedItems, total: items.total_count });39 } catch (error: unknown) {40 const e = error as { statusCode?: number; message: string };41 if (e.statusCode === 401) return NextResponse.json({ error: 'Token expired' }, { status: 401 });42 return NextResponse.json({ error: e.message }, { status: 500 });43 }44}Pro tip: Box's root folder ID is always '0' (the string zero, not a UUID). All other folder IDs are numeric strings that you find in the Box web app URL or from the API response's id field.
Expected result: Box file operation routes return folder items, generate preview URLs, handle file uploads, and create shared links using the Box SDK with the stored access token.
Build the File Browser with Content Preview
Build the File Browser with Content Preview
Build a React file browser component that uses your Box API routes to navigate folders and preview documents in-app. Box's Content Preview is the standout feature that differentiates it from simpler storage APIs — you can embed a full-fidelity document viewer for 120+ file formats in your Bolt app without any additional libraries. The Content Preview URL returned by client.files.previewLink() opens Box's hosted viewer. Embed it in an iframe: the viewer renders PDFs, Word documents, Excel spreadsheets, PowerPoint presentations, images, videos, and code files with formatting intact. The iframe requires width and height styling — 100% width and a fixed height (e.g., 700px) works well. Box's viewer automatically adjusts to the iframe dimensions. For the file browser layout, a two-panel design works well: a left sidebar for folder navigation with a folder tree, and a right panel showing the current folder's contents as a table or grid. Clicking a folder navigates into it (fetch new folder items). Clicking a file opens the preview in a modal or in the right panel. Include breadcrumb navigation showing the current path. File type icons help users quickly identify content. Box's type system distinguishes 'file' (with extension) from 'folder'. Map common extensions to icon types: pdf, docx, xlsx, pptx, txt, jpg, png, mp4. Use Lucide React icons (which Bolt includes by default) for file type representation.
Build a BoxFileBrowser React component. State: currentFolderId ('0' for root), folderHistory [{id, name}] for breadcrumbs, items (BoxItem[]), loading, previewFile (BoxItem | null). Fetch /api/box/folders?folderId={currentFolderId} on mount and folderId change. Layout: breadcrumb trail at top (Home > Folder1 > Folder2, clickable). Items table: icon (📁 folder or file emoji based on extension), name (click → folder navigates in, file sets previewFile), last modified (formatted), size (KB/MB, blank for folders). Preview panel: when previewFile is set, GET /api/box/files/{previewFile.id}/preview-url, then render an iframe with the returned URL at full height. Include a 'Close preview' button and a 'Download' button using the download URL.
Paste this in Bolt.new chat
1// Utility: generate Box file type icon from extension2function getBoxFileIcon(item: { type: string; extension?: string }): string {3 if (item.type === 'folder') return '📁';4 const ext = (item.extension || '').toLowerCase();5 const iconMap: Record<string, string> = {6 pdf: '📄',7 docx: '📝', doc: '📝',8 xlsx: '📊', xls: '📊',9 pptx: '📑', ppt: '📑',10 jpg: '🖼️', jpeg: '🖼️', png: '🖼️', gif: '🖼️', webp: '🖼️',11 mp4: '🎬', mov: '🎬', avi: '🎬',12 mp3: '🎵', wav: '🎵',13 zip: '📦', tar: '📦', gz: '📦',14 txt: '📋', csv: '📋', md: '📋',15 };16 return iconMap[ext] || '📎';17}1819// Usage in the file browser:20// <span>{getBoxFileIcon(item)}</span>21// <span>{item.name}</span>Pro tip: Box's Content Preview iframe works best with explicit dimensions. Set the iframe to 100% width and at least 600px height for comfortable document reading. Add overflow: hidden to the iframe container to prevent scrollbars from appearing around the viewer.
Expected result: The BoxFileBrowser component renders a navigable file browser with breadcrumb navigation. Clicking files opens Box's Content Preview in an iframe within the app. Folder navigation and file preview both function correctly.
Common use cases
Enterprise Document Management Portal
Build an internal web portal that lets employees browse, view, and manage Box documents without leaving your app. Users authenticate with Box OAuth, browse their assigned folders, preview documents in-app using Box's Content Preview, and upload new versions of files. Useful for legal teams, HR portals, and compliance document management.
Build a Box document portal. Create API routes: GET /api/box/folders?folderId={id} (lists folder contents using box-node-sdk, defaults to root folder '0'), GET /api/box/files/[id]/preview-url (returns the Box content preview URL for the file), POST /api/box/upload (accepts filename and base64 content, uploads to specified Box folder). Create a BoxDocumentPortal React component: left panel shows folder tree navigation, right panel shows file list with file type icon, name, modified date, and 'Preview' button. Clicking Preview opens an in-app modal with an iframe showing the Box content preview URL. Read the Box access token from the session cookie.
Copy this prompt to try it in Bolt.new
Automated Document Generation and Saving to Box
Generate documents programmatically in your Bolt app (PDF reports, contracts, invoices) and save them to a specific Box folder as new files. Box's upload API supports creating new files and uploading new versions of existing files. After upload, generate a shared link with specific access level for sharing with external parties.
Build a contract generation feature that saves to Box. After generating a PDF contract, POST to /api/box/upload-contract: accepts {filename, pdfBase64, clientEmail}. Upload to Box folder ID from BOX_CONTRACTS_FOLDER_ID env var using box-node-sdk filesUpload. Then use createSharedLink with access: 'collaborator' and allow_download: false to generate a view-only link. Store {boxFileId, shareUrl, filename} in Supabase contracts table. Send the shareUrl to clientEmail via SendGrid. Return the shareUrl in the API response.
Copy this prompt to try it in Bolt.new
File Upload Widget with Box Destination
Add a file upload feature to your app that deposits files directly into a Box folder with proper metadata tagging. Users select files from their computer, your app uploads them to the correct Box folder based on business rules (department folder, project folder, date-based archive), and the files appear immediately in Box for other team members.
Create a file upload component that saves to Box. Upload form accepts multiple files (max 50MB each). For each file: POST to /api/box/upload with {filename, contentBase64, contentType, folderId}. The API route uses box-node-sdk to upload to the specified folder. Add metadata to the uploaded file: document_type (from a dropdown: invoice, contract, report), uploaded_by (from the authenticated user's email), upload_date (ISO string). Return {fileId, filename, viewUrl} for each uploaded file. Show a list of recently uploaded files with filename, upload time, and a 'View in Box' link using the viewUrl.
Copy this prompt to try it in Bolt.new
Troubleshooting
Box OAuth callback returns 'invalid_client' or 'client authentication failed'
Cause: BOX_CLIENT_ID or BOX_CLIENT_SECRET is incorrect, or the redirect_uri in the token exchange doesn't match the registered redirect URI in the Box Developer Console.
Solution: Copy the Client ID and Client Secret exactly from the Box Developer Console (developer.box.com/console → your app → Configuration tab). Verify the BOX_REDIRECT_URI in your environment variables matches a URI registered in the Box app settings, including protocol (https), path, and no trailing slash.
client.folders.getItems returns an empty list even though the Box account has files
Cause: The folderId '0' accesses the authenticated user's root folder. If the user's files are in a different location, or if the app is authorized to a service account with no files, the root may appear empty.
Solution: Verify the authenticated user has files in their Box root. Log the items response fully to check for a total_count. For enterprise apps using Service Account authentication, files may be in specific collaboration folders — use client.search.query('*', {limit: 10}) to find items regardless of folder location.
1// Debug: log full folder response2const items = await client.folders.getItems('0', { limit: 10 });3console.log('Box root:', JSON.stringify({ total: items.total_count, entries: items.entries.map((e: {id: string; name: string; type: string}) => ({id: e.id, name: e.name, type: e.type})) }));Box Content Preview iframe shows a blank page or access denied error
Cause: The preview URL requires the user to be currently authenticated with Box in their browser session. If the preview is opened in an iframe for a user who is not logged into Box, the viewer shows a login prompt or error.
Solution: Box's embedded content preview works when the user is logged into Box in the same browser. For apps where users may not be Box-logged-in, use the direct download URL or generate a publicly accessible shared link instead of relying on the preview URL's implicit authentication.
1// Alternative: use shared link for preview instead of authenticated preview URL2const shareResult = await client.files.createSharedLink(fileId, {3 access: 'open', // 'open' = anyone with link4 permissions: { can_download: false, can_preview: true }5});6const shareUrl = shareResult.shared_link.url;7// Embed shareUrl in iframe instead of previewLink URLbox-node-sdk throws 'TypeError: BoxSDK is not a constructor'
Cause: The box-node-sdk package uses CommonJS module.exports, which requires a specific import pattern in TypeScript/ESM projects.
Solution: Use the default import with the require-style pattern. In TypeScript files, use: import BoxSDK from 'box-node-sdk'. If this fails with the ESM interop, try: const BoxSDK = require('box-node-sdk') — and add @types/box-node-sdk for TypeScript types.
1// If ESM interop fails, use CommonJS-compatible import:2// eslint-disable-next-line @typescript-eslint/no-require-imports3const BoxSDK = require('box-node-sdk');45// Or in tsconfig.json, ensure:6// "esModuleInterop": true,7// "allowSyntheticDefaultImports": trueBest practices
- Store Box access tokens and refresh tokens in httpOnly cookies, never in localStorage — Box tokens grant access to potentially sensitive corporate documents
- Implement token auto-refresh using the refresh token before it expires after 60 days — users should not need to re-authorize frequently
- Use Box's minimum necessary permissions: request read-only scopes if your app only displays files, write scope only if users create or modify files
- Embed Box Content Preview for document viewing rather than downloading files client-side — the Box viewer supports 120+ file formats and maintains formatting fidelity without additional libraries
- Handle Box's rate limiting (429 responses) gracefully — Box enforces per-user and per-app rate limits; implement exponential backoff for retry logic
- Test the OAuth flow on your deployed Netlify app first — the Bolt WebContainer URL cannot be registered as a Box redirect URI
- For enterprise deployments, consider Box JWT server authentication (app-to-app, no user OAuth) for service accounts that manage files on behalf of your app rather than individual users
Alternatives
Dropbox is more consumer/SMB-focused with a simpler developer experience; Box has stronger enterprise compliance (HIPAA, FedRAMP) and admin controls — choose based on your organization's compliance requirements.
OneDrive integrates natively with Microsoft 365 (Word, Teams, SharePoint); Box is platform-agnostic and used across multiple enterprise ecosystems — choose OneDrive for Microsoft-heavy organizations.
AWS S3 is raw cloud storage you fully control; Box is a managed content management platform with user-facing features — use S3 for programmatic app storage, Box for accessing and managing users' existing enterprise documents.
Google Drive integrates with Google Workspace documents and uses OAuth similar to Box; Box is preferred in regulated industries with HIPAA/FedRAMP compliance requirements where Google's data handling doesn't meet security policies.
Frequently asked questions
Does Box integration work in Bolt's WebContainer preview?
File operations via the Box SDK (listing, uploading, downloading) work in the Bolt preview because they are outbound HTTPS requests. The Box OAuth authorization flow requires a stable redirect URI registered in the Box Developer Console — the Bolt WebContainer URL is not stable and cannot be registered. Deploy to Netlify first to test the full OAuth flow. Once you have a valid access token, individual file operations can be tested in the preview using a test token.
What is the difference between Box OAuth 2.0 and Box JWT authentication?
OAuth 2.0 is user authentication — the user logs in with their Box credentials and your app acts on their behalf with their files. JWT authentication is app-to-app (service account) authentication — your app has its own Box identity that manages its own set of files or has admin-granted access to enterprise content. Use OAuth for apps where each user accesses their own Box files. Use JWT for backend automation, content management systems that manage files on behalf of the organization, or apps with Box admin access.
Can I use Box's Content Preview in a Bolt app without Box authentication?
Box's standard preview URL (from previewLink) requires the user to be authenticated with Box in their browser. For publicly viewable documents, create a shared link with access 'open' (anyone with the link) and preview permission enabled — embed the shared link in an iframe instead. This works for externally shareable content but should not be used for confidential documents.
Is Box free to use for development and small applications?
Box offers a free personal account (10GB storage) that works for development. Box's developer sandbox is available at app.box.com/developers and provides a separate test environment. For production apps, Box Business starts at $15/user/month. The free tier is sufficient for development and testing. Note: Box's HIPAA and FedRAMP compliance features require enterprise plans.
How do I handle Box files shared with me (not in my own Box account)?
Files shared with you appear in the Box web app under 'All Files' but not in your personal root folder via the API. Use client.folders.get('0', {fields: 'item_collection'}) to see your root, or client.collaborations.getAll() to see shared items. For files shared to you, the API response includes a 'shared_link' property. You can also use client.search.query() to find files regardless of sharing status.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation