Skip to main content
RapidDev - Software Development Agency
bolt-ai-integrationsBolt Chat + API Route

How to Integrate Bolt.new with Dropbox

Dropbox integrates with Bolt.new via Dropbox's HTTP API v2 — an RPC-style REST API that works over HTTPS in Bolt's WebContainer. Create a Dropbox app in the Developer Portal to get OAuth credentials, implement the PKCE authorization flow in Next.js API routes (requires deployment for the redirect URI), then use the Dropbox SDK or direct fetch calls to upload, download, list, and share files. RPC-style endpoints differ from standard REST — read the API format carefully.

What you'll learn

  • How to register a Dropbox app and configure OAuth 2.0 PKCE permissions for file access
  • How to implement the Dropbox PKCE authorization flow in Next.js API routes
  • How to use Dropbox API v2's RPC-style endpoints for file upload, download, list, and sharing
  • How to build a file picker and upload component that integrates with Dropbox
  • Why Dropbox OAuth callback requires a deployed URL and how to test the full flow on Netlify
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Intermediate16 min read40 minutesStorageApril 2026RapidDev Engineering Team
TL;DR

Dropbox integrates with Bolt.new via Dropbox's HTTP API v2 — an RPC-style REST API that works over HTTPS in Bolt's WebContainer. Create a Dropbox app in the Developer Portal to get OAuth credentials, implement the PKCE authorization flow in Next.js API routes (requires deployment for the redirect URI), then use the Dropbox SDK or direct fetch calls to upload, download, list, and share files. RPC-style endpoints differ from standard REST — read the API format carefully.

Dropbox in Bolt.new: File Sync and Storage via HTTP API v2

Dropbox is one of the most widely used cloud storage platforms, with over 700 million registered users. For Bolt.new apps that need to interact with users' existing files — reading documents, saving exports, synchronizing data — Dropbox provides a clean HTTP-based API that works in Bolt's WebContainer. Unlike database drivers that require TCP connections, all Dropbox API calls use HTTPS, making them fully compatible during development.

Dropbox API v2 uses an unusual RPC-style architecture that catches many developers by surprise. Instead of standard REST (GET /files/list, POST /files/upload), Dropbox uses JSON-body POST requests to action-named endpoints: POST /files/list_folder, POST /files/upload. Even GET-semantics operations (listing files) use POST requests with JSON bodies. The endpoint paths are descriptive action names rather than resource paths. Once you understand this pattern, the API is very consistent — but it is worth knowing before you start prompting Bolt.

The Dropbox JavaScript SDK (dropbox package) abstracts the RPC-style calls into normal function invocations. For most Bolt integrations, using the SDK is simpler than raw fetch calls. The SDK handles the Content-Type headers, API versioning, and error format parsing. Install it as a pure JavaScript package — no native binaries, works in WebContainers. The main integration steps are: register a Dropbox app, implement PKCE OAuth, store tokens, and call SDK methods from your API routes.

Integration method

Bolt Chat + API Route

Dropbox uses OAuth 2.0 PKCE for user authorization and an HTTP-based API v2 for file operations — both compatible with Bolt's WebContainer over HTTPS. You register a Dropbox app to get an app key, implement the OAuth PKCE flow in Next.js API routes, store the access token securely in an httpOnly cookie, and call Dropbox API endpoints through server-side API routes to keep tokens away from client code. The OAuth redirect callback requires a deployed URL — test on Netlify after initial development.

Prerequisites

  • A Dropbox account (personal free or Dropbox Business) for testing
  • A Dropbox app registered at dropbox.com/developers/apps (requires a Dropbox account)
  • A Bolt.new Next.js project for the OAuth callback routes and server-side API handling
  • A deployed Netlify or Bolt Cloud URL for the OAuth redirect URI — Dropbox OAuth callbacks cannot use Bolt's WebContainer preview URLs
  • Familiarity with OAuth 2.0 PKCE flow — especially that PKCE requires generating a code_verifier before the authorization request

Step-by-step guide

1

Create a Dropbox App and Get OAuth Credentials

Register a Dropbox application at dropbox.com/developers/apps. Click 'Create app', then make these choices: API — Dropbox API (not Scoped App, which is for Dropbox Business). App folder access vs Full Dropbox — choose 'App folder' for apps that only need one dedicated folder (simpler permission, Dropbox creates /Apps/YourAppName in the user's Dropbox), or 'Full Dropbox' for apps that need to browse the user's entire Dropbox. Give the app a unique name. On the app settings page, you will find the App key (this is your OAuth client ID — Dropbox calls it 'App key', not 'Client ID'). Under OAuth 2.0, set the Redirect URI to your deployed callback URL: https://your-app.netlify.app/api/auth/dropbox/callback. Note: add localhost:3000 as a second redirect URI for local development testing. For permissions, go to the Permissions tab and enable: files.content.read (download files), files.content.write (upload and modify files), files.metadata.read (list folders), sharing.write (create shared links). Save changes. Dropbox permissions must be set before generating tokens — changing permissions requires users to re-authorize. Dropbox now uses short-lived access tokens (4 hours) with refresh tokens by default. The older long-lived tokens are being deprecated. During development, you can generate a test access token on the app settings page under OAuth 2 → Generated access token — this gives you a long-lived token for rapid development iteration without implementing the full OAuth flow first.

Bolt.new Prompt

Create a .env file with Dropbox OAuth environment variables: DROPBOX_APP_KEY=your_app_key_here, DROPBOX_APP_SECRET=your_app_secret_here, DROPBOX_REDIRECT_URI=https://your-app.netlify.app/api/auth/dropbox/callback. Note: Dropbox calls it 'App key' not 'Client ID', but it serves the same purpose. For development, also add DROPBOX_TEST_TOKEN=your_generated_test_token (generated on Dropbox app settings page for dev testing only).

Paste this in Bolt.new chat

.env
1# .env
2DROPBOX_APP_KEY=your_dropbox_app_key
3DROPBOX_APP_SECRET=your_dropbox_app_secret
4DROPBOX_REDIRECT_URI=https://your-app.netlify.app/api/auth/dropbox/callback
5
6# For development testing only (generated on Dropbox app settings page):
7# DROPBOX_TEST_TOKEN=sl.xxxxxxxxxxxxxxxxxxxxxxxxxxxx
8# Remove before production deployment!

Pro tip: Use 'App folder' access instead of 'Full Dropbox' whenever possible — it requires fewer permissions, reassures users during the OAuth consent screen (they see 'access one folder' instead of 'access your entire Dropbox'), and reduces the blast radius if credentials are compromised.

Expected result: Dropbox app is registered with App key and App secret. Permissions include files.content.read, files.content.write, files.metadata.read, and sharing.write. Redirect URI points to your Netlify callback URL.

2

Install Dropbox SDK and Configure Client

Install the official Dropbox JavaScript SDK using the package name 'dropbox'. This SDK wraps Dropbox API v2's RPC-style endpoints into typed methods, handling the request format (JSON body POSTs), authentication headers, and response parsing. The package is pure JavaScript with no native binaries — it installs and works in Bolt's WebContainer. The Dropbox SDK is initialized with your App key for OAuth flows, or with an access token for API calls. Create two utility files: one for OAuth URL generation and token exchange (uses App key + App secret), and one that creates an authenticated Dropbox client instance from a stored access token. Dropbox API v2's RPC format note for Bolt prompting: when prompting Bolt to call Dropbox methods, reference the SDK method names (filesListFolder, filesUpload, sharingCreateSharedLinkWithSettings) rather than the raw API endpoints. Bolt generates cleaner SDK-based code when you reference method names. The SDK method names match the Dropbox API documentation endpoints with camelCase: /files/list_folder → filesListFolder, /files/upload → filesUpload, /sharing/create_shared_link_with_settings → sharingCreateSharedLinkWithSettings.

Bolt.new Prompt

Install the dropbox npm package. Create lib/dropbox-client.ts that exports a function getDropboxClient(accessToken: string) that returns a configured Dropbox instance. Create lib/dropbox-auth.ts that exports: (1) generateAuthUrl(codeVerifier: string) — builds the Dropbox OAuth PKCE authorization URL using DROPBOX_APP_KEY and DROPBOX_REDIRECT_URI, using crypto.subtle to generate the code_challenge as SHA-256 hash of the verifier encoded as base64url, (2) exchangeCodeForToken(code: string, codeVerifier: string) — exchanges the authorization code for access and refresh tokens using DROPBOX_APP_KEY and DROPBOX_APP_SECRET.

Paste this in Bolt.new chat

lib/dropbox-client.ts
1// lib/dropbox-client.ts
2import { Dropbox } from 'dropbox';
3
4export function getDropboxClient(accessToken: string): Dropbox {
5 return new Dropbox({ accessToken });
6}
7
8// lib/dropbox-auth.ts
9function base64urlEncode(buffer: ArrayBuffer): string {
10 return Buffer.from(buffer)
11 .toString('base64')
12 .replace(/\+/g, '-')
13 .replace(/\//g, '_')
14 .replace(/=/g, '');
15}
16
17export async function generateCodeChallenge(verifier: string): Promise<string> {
18 const encoded = new TextEncoder().encode(verifier);
19 const hash = await crypto.subtle.digest('SHA-256', encoded);
20 return base64urlEncode(hash);
21}
22
23export function generateCodeVerifier(): string {
24 const array = new Uint8Array(32);
25 crypto.getRandomValues(array);
26 return base64urlEncode(array.buffer);
27}
28
29export async function buildAuthUrl(codeVerifier: string): Promise<string> {
30 const challenge = await generateCodeChallenge(codeVerifier);
31 const params = new URLSearchParams({
32 client_id: process.env.DROPBOX_APP_KEY!,
33 response_type: 'code',
34 redirect_uri: process.env.DROPBOX_REDIRECT_URI!,
35 code_challenge: challenge,
36 code_challenge_method: 'S256',
37 token_access_type: 'offline', // Enables refresh tokens
38 });
39 return `https://www.dropbox.com/oauth2/authorize?${params}`;
40}

Pro tip: Dropbox uses short-lived access tokens (4 hours) with offline access refresh tokens when you include token_access_type: 'offline' in the authorization URL. Always include this parameter — without it you only get a short-lived token and users must re-authorize every 4 hours.

Expected result: The 'dropbox' package is installed. lib/dropbox-client.ts exports a configured Dropbox instance factory. lib/dropbox-auth.ts exports PKCE code verifier generation and auth URL building utilities.

3

Implement OAuth PKCE Authorization Routes

Dropbox recommends PKCE (Proof Key for Code Exchange) for OAuth 2.0. PKCE enhances security for public clients by generating a cryptographic verifier before the authorization request and proving possession of that verifier during token exchange — preventing authorization code interception attacks. The PKCE flow requires two API routes. The initiation route generates a code_verifier (a random 32-byte string, base64url encoded), hashes it with SHA-256 to create the code_challenge, stores the verifier in an httpOnly cookie (needed for the callback), and redirects the user to Dropbox's authorization page with the code_challenge. The callback route receives the authorization code from Dropbox, reads the code_verifier from the cookie, exchanges both for access and refresh tokens, and stores the tokens securely. This OAuth flow only completes on a deployed app where the redirect URI matches exactly. During development in Bolt, you have two options: (1) deploy to Netlify first and test OAuth there, or (2) use a development access token from the Dropbox app settings page (App Settings → Generated access token) to test file operations independently without implementing OAuth. The generated development token works for testing filesListFolder, filesUpload, etc., without going through the OAuth flow — useful for building and testing the file operation UI before the OAuth plumbing is complete.

Bolt.new Prompt

Create Dropbox OAuth API routes. Route 1: GET /api/auth/dropbox — generates PKCE code_verifier (32 random bytes, base64url), stores it in httpOnly cookie 'dropbox_cv' for 10 minutes, builds auth URL with code_challenge (SHA-256 of verifier, base64url), redirects user to Dropbox. Route 2: GET /api/auth/dropbox/callback — reads code from query params and code_verifier from cookie, exchanges them for tokens via POST to https://api.dropboxapi.com/oauth2/token with grant_type: authorization_code and code_verifier, stores access_token and refresh_token in httpOnly cookies (dropbox_at expires in 4h, dropbox_rt expires in 30d), redirects to /dashboard. Use DROPBOX_APP_KEY and DROPBOX_APP_SECRET env vars. Add GET /api/auth/dropbox/logout that clears both token cookies.

Paste this in Bolt.new chat

app/api/auth/dropbox/route.ts
1// app/api/auth/dropbox/route.ts
2import { NextResponse } from 'next/server';
3import { buildAuthUrl, generateCodeVerifier } from '@/lib/dropbox-auth';
4
5export async function GET() {
6 const codeVerifier = generateCodeVerifier();
7 const authUrl = await buildAuthUrl(codeVerifier);
8 const response = NextResponse.redirect(authUrl);
9 response.cookies.set('dropbox_cv', codeVerifier, {
10 httpOnly: true,
11 secure: true,
12 maxAge: 600,
13 sameSite: 'lax',
14 });
15 return response;
16}
17
18// app/api/auth/dropbox/callback/route.ts
19import { NextRequest, NextResponse } from 'next/server';
20
21export async function GET(request: NextRequest) {
22 const { searchParams } = new URL(request.url);
23 const code = searchParams.get('code');
24 const codeVerifier = request.cookies.get('dropbox_cv')?.value;
25
26 if (!code || !codeVerifier) {
27 return NextResponse.redirect('/login?error=missing_params');
28 }
29
30 const tokenRes = await fetch('https://api.dropboxapi.com/oauth2/token', {
31 method: 'POST',
32 headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
33 body: new URLSearchParams({
34 code,
35 grant_type: 'authorization_code',
36 client_id: process.env.DROPBOX_APP_KEY!,
37 client_secret: process.env.DROPBOX_APP_SECRET!,
38 redirect_uri: process.env.DROPBOX_REDIRECT_URI!,
39 code_verifier: codeVerifier,
40 }),
41 });
42
43 const tokens = await tokenRes.json();
44 if (tokens.error) {
45 return NextResponse.redirect(`/login?error=${tokens.error}`);
46 }
47
48 const response = NextResponse.redirect('/dashboard');
49 response.cookies.set('dropbox_at', tokens.access_token, { httpOnly: true, secure: true, maxAge: 14400 });
50 if (tokens.refresh_token) {
51 response.cookies.set('dropbox_rt', tokens.refresh_token, { httpOnly: true, secure: true, maxAge: 86400 * 30 });
52 }
53 response.cookies.delete('dropbox_cv');
54 return response;
55}

Pro tip: Dropbox only returns a refresh_token when the app is configured with offline access (token_access_type: 'offline' in the auth URL) and the user has not previously granted offline access to your app. If refresh_token is absent in the callback, the user needs to revoke your app's access in Dropbox settings and re-authorize.

Expected result: OAuth routes are in place. On deployed Netlify, visiting /api/auth/dropbox initiates the PKCE flow, and /api/auth/dropbox/callback stores tokens and redirects to /dashboard.

4

Implement File Operations with the Dropbox SDK

With authentication in place, implement the file operations your app needs using the Dropbox SDK. The SDK's method signatures follow Dropbox API v2's RPC naming — remember that listing and reading files uses POST requests under the hood, but the SDK presents them as straightforward method calls. Key SDK methods for common operations: - List folder: dropbox.filesListFolder({ path: '' }) for root (empty string, not '/'), returns result.entries array of FileMetadata and FolderMetadata objects - List with pagination: check result.has_more, then call dropbox.filesListFolderContinue({ cursor: result.cursor }) until has_more is false - Download file: dropbox.filesDownload({ path: '/path/to/file.pdf' }) — in Node.js, the response contains a fileBlob property with the binary content - Upload file: dropbox.filesUpload({ path: '/target/path/file.pdf', contents: Buffer.from(fileContent), mode: { '.tag': 'add' }, autorename: true }) - Create folder: dropbox.filesCreateFolderV2({ path: '/NewFolder', autorename: false }) - Create sharing link: dropbox.sharingCreateSharedLinkWithSettings({ path: '/file.pdf', settings: { requested_visibility: { '.tag': 'public' } } }) Error handling: Dropbox SDK methods throw errors with an error.error property containing the Dropbox error object, which has a '.tag' field identifying the error type. Common tags: 'path' for path errors, 'too_many_requests' for rate limiting, 'expired_access_token' for auth errors.

Bolt.new Prompt

Create Dropbox file operation API routes. GET /api/dropbox/files?path={path} — calls filesListFolder with the given path (default ''), returns { files: Array<{name, path_lower, isFolder, size, modified}> }. POST /api/dropbox/upload — accepts {filename: string, content: string (base64), folder: string}, calls filesUpload to folder/filename, returns {path: string, success: true}. POST /api/dropbox/share — accepts {path: string}, calls sharingCreateSharedLinkWithSettings with public visibility, returns {shareUrl: string}. All routes read dropbox_at cookie for auth token, return 401 if missing. Handle 'shared_link_already_exists' error in the share route by fetching the existing link instead.

Paste this in Bolt.new chat

app/api/dropbox/files/route.ts
1// app/api/dropbox/files/route.ts
2import { NextRequest, NextResponse } from 'next/server';
3import { getDropboxClient } from '@/lib/dropbox-client';
4
5export async function GET(request: NextRequest) {
6 const accessToken = request.cookies.get('dropbox_at')?.value;
7 if (!accessToken) return NextResponse.json({ error: 'Not authenticated' }, { status: 401 });
8
9 const { searchParams } = new URL(request.url);
10 const path = searchParams.get('path') || '';
11
12 const dbx = getDropboxClient(accessToken);
13
14 try {
15 const result = await dbx.filesListFolder({ path });
16 const files = result.result.entries.map((entry) => ({
17 name: entry.name,
18 path_lower: entry.path_lower,
19 isFolder: entry['.tag'] === 'folder',
20 size: entry['.tag'] === 'file' ? entry.size : undefined,
21 modified: entry['.tag'] === 'file' ? entry.server_modified : undefined,
22 }));
23 return NextResponse.json({ files, cursor: result.result.cursor, hasMore: result.result.has_more });
24 } catch (error: unknown) {
25 const e = error as { status?: number; error?: { error_summary?: string } };
26 if (e.status === 401) return NextResponse.json({ error: 'Token expired' }, { status: 401 });
27 return NextResponse.json({ error: e.error?.error_summary || 'Dropbox error' }, { status: 500 });
28 }
29}

Pro tip: Dropbox's path for the root folder is an empty string '', NOT '/'. Passing '/' as the path throws an error. Always use '' for root and '/FolderName' for specific folders.

Expected result: Dropbox file operation routes work correctly. GET /api/dropbox/files returns file and folder entries. Upload and share routes function after deployment with a valid access token.

Common use cases

Import Files from User's Dropbox

Allow users to browse their Dropbox and select files to import into your app. After OAuth authentication, list the user's Dropbox folders, let them navigate and select a file, then download the file content to process in your app. Useful for importing CSV data, images, or documents that users already have in Dropbox.

Bolt.new Prompt

Build a Dropbox file importer. Create two API routes: GET /api/dropbox/list?path={path} (lists folder contents at the given path, defaults to root '') using the Dropbox SDK filesListFolder method, returning entries with .tag ('file' or 'folder'), name, path_lower, size, and server_modified. POST /api/dropbox/download with body {path: string} using filesDownload, returning the file content as base64 for text files under 5MB. Create a DropboxFilePicker React component that calls the list route on mount, shows a navigable file tree with folder navigation and breadcrumbs, and calls onFileImport(path, name, content) prop callback when a file is selected. Read the Dropbox access token from a server-side session.

Copy this prompt to try it in Bolt.new

Export and Save Documents to Dropbox

Enable users to save documents, reports, or exports from your app directly to their Dropbox. After the user clicks a save button, your app uploads the file to a dedicated folder in their Dropbox and optionally returns a shareable link. This is useful for invoice generators, report builders, or any tool that creates files users want to store.

Bolt.new Prompt

Add 'Save to Dropbox' functionality to my document generator. Create a POST /api/dropbox/upload route that accepts {filename: string, content: string, folder: '/AppExports'} in the request body. Use Dropbox SDK filesUpload with mode 'add' and autorename: true to upload the file to the specified folder. If the folder doesn't exist, use filesCreateFolderV2 to create it first, then upload. After upload, use sharingCreateSharedLinkWithSettings to create a view-only shared link. Return {shareUrl: string, dropboxPath: string}. Add a SaveToDropbox button component that calls this route and shows the share URL with a copy-to-clipboard button.

Copy this prompt to try it in Bolt.new

Continuous Sync — Watch a Dropbox Folder

Poll a specific Dropbox folder for new files using the Dropbox list_folder/get_latest_cursor and list_folder/longpoll endpoints. When new files appear, process them in your app. Useful for automation workflows where users drop files into a watched Dropbox folder to trigger processing. Note: longpoll requires a deployed environment, not the Bolt WebContainer.

Bolt.new Prompt

Build a Dropbox folder watcher that checks for new files every 30 seconds (polling, not longpoll — works in preview). Create a GET /api/dropbox/new-files?cursor={cursor} route that uses filesListFolderContinue if cursor is provided, or filesListFolder with cursor: true for the initial call. Return {entries: DropboxEntry[], cursor: string, hasMore: boolean}. Store the cursor in Supabase per user after each check. Create a useDropboxSync hook that polls /api/dropbox/new-files every 30 seconds and calls onNewFile(entry) for each new file found since the last poll. Show a 'Watching /Imports folder' status badge that turns green when active.

Copy this prompt to try it in Bolt.new

Troubleshooting

OAuth callback returns 'invalid_grant' or 'The provided authorization grant is invalid'

Cause: The authorization code has expired (codes are valid for ~1 minute), or the code_verifier does not match the code_challenge used in the authorization URL (PKCE mismatch), or the redirect_uri in the token exchange doesn't exactly match the one used in the authorization URL.

Solution: Verify the code_verifier is being stored in the cookie before the redirect and retrieved correctly in the callback. Ensure the DROPBOX_REDIRECT_URI environment variable is identical in both the auth URL and the token exchange request. Authorization codes expire quickly — any delay between authorization and callback causes this error.

filesListFolder throws an error: 'path/not_found/' or 'path/malformed_path'

Cause: The path parameter uses '/' for root instead of '' (empty string), or contains characters that Dropbox doesn't allow in paths, or the path starts without a leading slash for non-root folders.

Solution: Use empty string '' for the Dropbox root folder. All non-root paths must start with '/': '/Documents', '/Apps/MyApp/exports'. Never pass '/' as a path — Dropbox API v2 does not accept it.

typescript
1// Correct Dropbox path format:
2const rootPath = ''; // Root folder: empty string, NOT '/'
3const subfolder = '/Documents'; // Non-root: leading slash required
4const appFolder = '/Apps/MyApp'; // App folder path
5
6// Wrong:
7// const rootPath = '/' ← throws path/malformed_path error

Dropbox access token expires after 4 hours and users are logged out

Cause: Short-lived access tokens expire after 4 hours. Without a refresh token (requires token_access_type: 'offline' in the auth URL and offline_access permission on the app), there is no way to get a new token without re-authorization.

Solution: Verify token_access_type: 'offline' is included in the buildAuthUrl function. Check that the Dropbox app settings include the correct permission scope. Implement a token refresh endpoint that uses the refresh_token to get a new access_token when the current one expires.

typescript
1// Token refresh endpoint:
2export async function POST(request: NextRequest) {
3 const refreshToken = request.cookies.get('dropbox_rt')?.value;
4 if (!refreshToken) return NextResponse.json({ error: 'No refresh token' }, { status: 401 });
5
6 const res = await fetch('https://api.dropboxapi.com/oauth2/token', {
7 method: 'POST',
8 headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
9 body: new URLSearchParams({
10 grant_type: 'refresh_token',
11 refresh_token: refreshToken,
12 client_id: process.env.DROPBOX_APP_KEY!,
13 client_secret: process.env.DROPBOX_APP_SECRET!,
14 }),
15 });
16 const tokens = await res.json();
17 const response = NextResponse.json({ ok: true });
18 response.cookies.set('dropbox_at', tokens.access_token, { httpOnly: true, secure: true, maxAge: 14400 });
19 return response;
20}

sharingCreateSharedLinkWithSettings fails with 'shared_link_already_exists'

Cause: A shared link already exists for this file. Dropbox only allows one shared link per file per visibility setting.

Solution: Catch the 'shared_link_already_exists' error and call sharingListSharedLinks with path to retrieve the existing link instead of trying to create a new one.

typescript
1try {
2 const result = await dbx.sharingCreateSharedLinkWithSettings({ path });
3 return result.result.url;
4} catch (err: unknown) {
5 const e = err as { error?: { error_summary?: string } };
6 if (e.error?.error_summary?.includes('shared_link_already_exists')) {
7 // Retrieve existing shared link
8 const existing = await dbx.sharingListSharedLinks({ path, direct_only: true });
9 return existing.result.links[0]?.url;
10 }
11 throw err;
12}

Best practices

  • Always include token_access_type: 'offline' in the Dropbox authorization URL to get a refresh token — without it, users must re-authorize every 4 hours
  • Store Dropbox OAuth tokens in httpOnly cookies, never in localStorage or React state — access tokens grant full Dropbox access as configured in your app's permission scopes
  • Use empty string '' for Dropbox root path, not '/' — this is one of the most common Dropbox API v2 mistakes that causes path/malformed_path errors
  • Handle the 'shared_link_already_exists' error in share link creation by retrieving the existing link — creating a second share link always fails since Dropbox permits one per visibility level
  • Test OAuth flow on your deployed Netlify URL before implementing it fully — the redirect URI must be pre-registered and the WebContainer preview URL cannot be used
  • Request minimal Dropbox permissions: files.content.read only if you need read access, files.content.write only if you need to upload or modify files — narrower permissions improve user trust
  • Implement pagination for Dropbox folder listings using has_more and cursor — users' Dropbox folders may contain hundreds or thousands of files that won't all return in a single API call

Alternatives

Frequently asked questions

Does Dropbox integration work in Bolt's WebContainer preview?

File operations (list, upload, download) work in the Bolt preview because they use outbound HTTPS requests through the Dropbox SDK. The OAuth authorization flow requires a stable redirect URI that must be registered with Dropbox — the Bolt WebContainer URL is not stable and cannot be registered. Deploy to Netlify to test the OAuth flow. For faster development, use a generated test access token from the Dropbox app settings page to test file operations without OAuth.

What is the difference between Dropbox App folder and Full Dropbox access?

App folder access creates a dedicated /Apps/YourAppName folder in the user's Dropbox — your app can only read and write files within that folder. Full Dropbox access allows reading and writing anywhere in the user's Dropbox. App folder access is preferred for most apps: it requires less user trust (the OAuth consent screen shows 'one folder' not 'your entire Dropbox'), and limits accidental data access. Use Full Dropbox only if your app genuinely needs to access files outside a dedicated folder.

Why does Dropbox API v2 use POST requests for listing files?

Dropbox API v2 uses an RPC (Remote Procedure Call) style rather than standard REST. All API calls are POST requests to action-named endpoints with JSON bodies — even read operations like listing folders. This differs from REST conventions where GET retrieves data. The Dropbox JavaScript SDK abstracts this into method calls like filesListFolder(), so you rarely need to deal with the raw HTTP format unless you are using fetch() directly.

How long does the Dropbox refresh token last?

Dropbox offline refresh tokens don't have a fixed expiration — they remain valid until the user revokes your app's access in their Dropbox account settings, your app explicitly calls the revoke endpoint, or the token hasn't been used in 90 days. Practically, store the refresh token securely (httpOnly cookie or database) and implement automatic token refresh when the 4-hour access token expires.

Can I connect to a Dropbox Business (team) account?

Yes. Dropbox Business accounts use the same API and OAuth flow as personal accounts. For team-specific features (listing team folders, accessing team members' files with admin consent), use the Dropbox Business API endpoints under /team/ — these require additional Dropbox Business API permission scopes. Standard file operations (reading/writing to the authenticated user's Dropbox) work identically for both personal and business accounts.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.