Take Your Search Game to the Next Level with Dropbox Dash 🚀✨ Curious how it works? Ask us here!
dropbox business
47 Topicsapi file request set naming convention
HI, There is currently no way to set the naming convention when creating a file request through the API. Therefore the uploader name is added to the file automatically and we have no say about it. The idea to implement the option to set the naming convention through the api https://api.dropboxapi.com/2/file_requests/create or setting a default naming convention for file request could also work. Related threads : - File Request API | The Dropbox Community - Rest API: naming conventions for new file request | The Dropbox CommunityUnable to Retrieve Dropbox "path_display" for Folders in Google Sheets Script
I'm developing a Google Sheets database that feeds an interactive map on My Maps. The script uses the Dropbox API to update folder names (in column A) and folder paths (in column F) based on metadata retrieved from Dropbox shared links. Although every folder is mounted on my account and I have full administrative rights on my Dropbox team, I'm not seeing the expected "path_display" value for my Dropbox folders. The script calls several API endpoints (such as sharing/get_shared_link_metadata, sharing/list_folders, sharing/list_mountable_folders, and sharing/get_folder_metadata) to try to obtain the complete folder path, but the path_display property remains empty in my sheet. I need to retrieve path_display because it lets me move folders in Dropbox while still keeping the most recent path in my map. The script is set to run weekly so that any folder moves are captured and my map stays up to date. Below is the complete script (with sensitive credentials, paths, and other details replaced): I tried this script in Google Apps Script: ``` // ===================================================== // CONFIGURATION & CONSTANTS // ===================================================== // Google Maps API Key (for geocoding) const API_KEY = "YOUR_GOOGLE_MAPS_API_KEY"; // OAuth2 Dropbox: Replace with your Dropbox credentials const DROPBOX_CLIENT_ID = 'YOUR_DROPBOX_CLIENT_ID'; const DROPBOX_CLIENT_SECRET = 'YOUR_DROPBOX_CLIENT_SECRET'; const DROPBOX_SCOPES = 'sharing.read files.metadata.read files.team_metadata.read team_data.member'; // Replace with your Dropbox team member ID (the member on which you want to operate) // Example: "dbmid:example_member_id" const DROPBOX_TEAM_MEMBER_ID = 'YOUR_DROPBOX_TEAM_MEMBER_ID'; const BATCH_SIZE = 100; const DELAY_BETWEEN_REQUESTS = 1000; // ===================================================== // OAUTH2 FOR DROPBOX (using the OAuth2 library) // ===================================================== function getDropboxService() { return OAuth2.createService('Dropbox') .setAuthorizationBaseUrl('https://www.dropbox.com/oauth2/authorize') .setTokenUrl('https://api.dropboxapi.com/oauth2/token') .setClientId(DROPBOX_CLIENT_ID) .setClientSecret(DROPBOX_CLIENT_SECRET) .setCallbackFunction('authCallback') .setPropertyStore(PropertiesService.getUserProperties()) .setScope(DROPBOX_SCOPES) // Request a refresh token .setParam('token_access_type', 'offline'); } function authCallback(request) { const service = getDropboxService(); const authorized = service.handleCallback(request); return HtmlService.createHtmlOutput(authorized ? 'Success! You can close this tab.' : 'Access denied.'); } function authorizeDropbox() { const service = getDropboxService(); if (!service.hasAccess()) { const authorizationUrl = service.getAuthorizationUrl(); Logger.log('Open the following URL and authorize the app, then re-run the script: %s', authorizationUrl); return authorizationUrl; } else { Logger.log('Already authorized with Dropbox.'); } } // ===================================================== // FUNCTIONS FOR UPDATING COORDINATES // ===================================================== function updateCoordinates() { const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); const startRow = 4; const addresses = sheet.getRange(`B${startRow}:B${sheet.getLastRow()}`).getValues().flat(); const gpsData = sheet.getRange(`D${startRow}:D${sheet.getLastRow()}`).getValues().flat(); addresses.forEach((address, index) => { const gps = gpsData[index]; if (address && !gps) { const coordinates = getCoordinates(address); if (coordinates) { sheet.getRange(index + startRow, 4).setValue(coordinates); } } }); SpreadsheetApp.flush(); } function getCoordinates(address) { const url = `https://maps.googleapis.com/maps/api/geocode/json?address=${encodeURIComponent(address)}&key=${API_KEY}`; try { const response = UrlFetchApp.fetch(url); const json = JSON.parse(response.getContentText()); if (json.status === "OK") { const latitude = json.results[0].geometry.location.lat; const longitude = json.results[0].geometry.location.lng; return `${latitude}, ${longitude}`; } else { console.error(`API error for address: ${address} - Status: ${json.status}`); return "API error"; } } catch (error) { console.error(`Error fetching coordinates: ${error.message}`); return "API error"; } } // ===================================================== // FUNCTIONS FOR UPDATING STATUS (column E) FROM PATHS (column F) // ===================================================== function updateStatusFromPaths() { const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); const startRow = 4; const lastRow = sheet.getLastRow(); const paths = sheet.getRange(`F${startRow}:F${lastRow}`).getValues().flat(); const statuses = []; paths.forEach(path => { if (path) { if (path.includes("ActiveDeals/Active") || path.includes("C:\\Path\\To\\ActiveDeals\\Active")) { statuses.push(["Active"]); } else if (path.includes("ActiveDeals/ToWatch") || path.includes("C:\\Path\\To\\ActiveDeals\\ToWatch")) { statuses.push(["To watch"]); } else if (path.includes("Properties/Owned") || path.includes("C:\\Path\\To\\Properties\\Owned")) { statuses.push(["Owned"]); } else if (path.includes("Properties/Sold") || path.includes("C:\\Path\\To\\Properties\\Sold")) { statuses.push(["Sold"]); } else if (path.includes("DeadDeals") || path.includes("C:\\Path\\To\\DeadDeals")) { statuses.push(["Dead"]); } else { statuses.push(["Undefined"]); } } else { statuses.push([""]); } }); sheet.getRange(startRow, 5, statuses.length, 1).setValues(statuses); } // ===================================================== // FUNCTIONS FOR UPDATING DROPBOX INFORMATION // ===================================================== /** * This script updates both the folder name (column A) * and the folder path (column F) by comparing the path_display returned * by Dropbox. Any changes are logged in column H. */ function updateFolderNamesInBatches() { const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); const startRow = 4; const lastRow = sheet.getLastRow(); const scriptProperties = PropertiesService.getScriptProperties(); let batchIndex = parseInt(scriptProperties.getProperty('batchIndexDropbox') || '0'); const totalBatches = Math.ceil((lastRow - startRow + 1) / BATCH_SIZE); // If all batches have been processed, reset and stop if (batchIndex >= totalBatches) { scriptProperties.deleteProperty('batchIndexDropbox'); Logger.log("All batches processed. Function stopped."); return; } const batchStart = startRow + (batchIndex * BATCH_SIZE); const batchEnd = Math.min(batchStart + BATCH_SIZE - 1, lastRow); // Check if the batch contains any sharing links (Column C) const linksRange = sheet.getRange(`C${batchStart}:C${batchEnd}`).getValues(); let hasLink = false; for (let i = 0; i < linksRange.length; i++) { if (linksRange[i][0].toString().trim() !== "") { hasLink = true; break; } } // If no links are found in the batch, stop processing if (!hasLink) { scriptProperties.deleteProperty('batchIndexDropbox'); Logger.log("No sharing links found in batch. Function stopped."); return; } // Clear previous statuses for the current batch (Column H) sheet.getRange(`H${batchStart}:H${batchEnd}`).clearContent(); // Process the current batch updateBatch(batchStart, batchEnd); // Update the batch index batchIndex++; scriptProperties.setProperty('batchIndexDropbox', batchIndex.toString()); // Schedule the next batch if there are more rows to process if (batchIndex < totalBatches) { ScriptApp.newTrigger('updateFolderNamesInBatches') .timeBased() .after(1000) .create(); } } /** * Processes the rows in the batch, * compares existing names/paths with those returned by Dropbox, and updates if necessary. */ function updateBatch(startRow, endRow) { const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); // Read columns A (folderNames), C (sharingLinks) and F (folderPaths) const folderNames = sheet.getRange(`A${startRow}:A${endRow}`).getValues().flat(); const sharingLinks = sheet.getRange(`C${startRow}:C${endRow}`).getValues().flat(); const folderPaths = sheet.getRange(`F${startRow}:F${endRow}`).getValues().flat(); for (let index = 0; index < sharingLinks.length; index++) { const link = sharingLinks[index]; const currentRow = startRow + index; // Skip if the link is empty if (!link || link.trim() === "") { Logger.log(`Stopping at row ${currentRow}: No sharing link found.`); return; } try { const metadata = getDropboxMetadata(link); let statusMessages = []; if (metadata && metadata.name) { // Compare folder name if (folderNames[index] !== metadata.name) { sheet.getRange(currentRow, 1).setValue(metadata.name); statusMessages.push("Folder name updated"); } // Compare folder path if (metadata.path && folderPaths[index] !== metadata.path) { sheet.getRange(currentRow, 6).setValue(metadata.path); statusMessages.push("Path updated"); } if (statusMessages.length === 0) { statusMessages.push("No changes needed"); } sheet.getRange(currentRow, 8).setValue(statusMessages.join(" | ")); } else { sheet.getRange(currentRow, 8).setValue("Failed: No metadata/name"); } } catch (err) { sheet.getRange(currentRow, 8).setValue("Failed: " + err.message); } // Delay to respect rate limits Utilities.sleep(DELAY_BETWEEN_REQUESTS); } SpreadsheetApp.flush(); } /** * getDropboxMetadata retrieves the name and path_display * from the Dropbox sharing link. * * It uses multiple methods to try to obtain the full path, * handling various limitations of the Dropbox API. */ function getDropboxMetadata(sharingLink) { const service = getDropboxService(); if (!service.hasAccess()) { throw new Error("Authorization required. Run authorizeDropbox() first."); } const accessToken = service.getAccessToken(); // First call to sharing/get_shared_link_metadata let apiUrl = "https://api.dropboxapi.com/2/sharing/get_shared_link_metadata"; let payload = { url: sharingLink }; let options = { method: "post", contentType: "application/json", headers: { Authorization: "Bearer " + accessToken, "Dropbox-API-Select-User": DROPBOX_TEAM_MEMBER_ID }, payload: JSON.stringify(payload), muteHttpExceptions: true }; let response = UrlFetchApp.fetch(apiUrl, options); let responseText = response.getContentText(); Logger.log("API Response for " + sharingLink + ": " + responseText); let json; try { json = JSON.parse(responseText); } catch (e) { throw new Error("Invalid JSON response: " + responseText); } if (json.error_summary) { throw new Error("Dropbox API error: " + json.error_summary); } // For shared folders, try a different approach to get the path if (!json.path_display && json['.tag'] === 'folder' && json.id) { // Try with sharing/list_folders endpoint if it's a shared folder apiUrl = "https://api.dropboxapi.com/2/sharing/list_folders"; payload = { limit: 100 }; options.payload = JSON.stringify(payload); try { response = UrlFetchApp.fetch(apiUrl, options); responseText = response.getContentText(); Logger.log("List Folders API Response: " + responseText); const listFolders = JSON.parse(responseText); if (listFolders.entries && listFolders.entries.length > 0) { // Look for matching entry by shared_folder_id const matchingFolder = listFolders.entries.find(folder => folder.shared_folder_id === json.id.replace('id:', '') ); if (matchingFolder && matchingFolder.path_lower) { json.path_display = matchingFolder.path_lower; } } } catch (e) { Logger.log("Fallback list_folders method failed: " + e.message); } // If still no path_display, try with list_mountable_folders if (!json.path_display) { apiUrl = "https://api.dropboxapi.com/2/sharing/list_mountable_folders"; payload = { limit: 100 }; options.payload = JSON.stringify(payload); try { response = UrlFetchApp.fetch(apiUrl, options); responseText = response.getContentText(); Logger.log("List Mountable Folders API Response: " + responseText); const listFolders = JSON.parse(responseText); if (listFolders.entries && listFolders.entries.length > 0) { // Look for matching entry by shared_folder_id const matchingFolder = listFolders.entries.find(folder => folder.shared_folder_id === json.id.replace('id:', '') ); if (matchingFolder && matchingFolder.path_lower) { json.path_display = matchingFolder.path_lower; } } } catch (e) { Logger.log("Fallback list_mountable_folders method failed: " + e.message); } } // Try one more approach with sharing/get_folder_metadata if (!json.path_display) { apiUrl = "https://api.dropboxapi.com/2/sharing/get_folder_metadata"; payload = { shared_folder_id: json.id.replace('id:', '') }; options.payload = JSON.stringify(payload); try { response = UrlFetchApp.fetch(apiUrl, options); responseText = response.getContentText(); Logger.log("Get Folder Metadata API Response: " + responseText); const folderMetadata = JSON.parse(responseText); if (folderMetadata.path_lower) { json.path_display = folderMetadata.path_lower; } } catch (e) { Logger.log("Fallback get_folder_metadata method failed: " + e.message); } } } return { name: json.name || "", path: json.path_display || "" }; } function startFolderNameUpdate() { PropertiesService.getScriptProperties().setProperty("batchIndexDropbox", "0"); updateFolderNamesInBatches(); } // ===================================================== // SETUP TRIGGERS // ===================================================== function setupTriggers() { // Delete all existing triggers. ScriptApp.getProjectTriggers().forEach(function(trigger) { ScriptApp.deleteTrigger(trigger); }); // Trigger on change to update coordinates. ScriptApp.newTrigger("updateCoordinates") .forSpreadsheet(SpreadsheetApp.getActiveSpreadsheet()) .onChange() .create(); // Trigger on change to update statuses from paths. ScriptApp.newTrigger("updateStatusFromPaths") .forSpreadsheet(SpreadsheetApp.getActiveSpreadsheet()) .onChange() .create(); // Time-based trigger to update Dropbox folder names & paths in batches (every Monday at 15:00). ScriptApp.newTrigger("updateFolderNamesInBatches") .timeBased() .onWeekDay(ScriptApp.WeekDay.MONDAY) .atHour(15) .create(); Logger.log("Triggers set: onChange for updateCoordinates and updateStatusFromPaths; weekly for updateFolderNamesInBatches."); } // Function to manually reset the batch index. function resetBatchIndex() { PropertiesService.getScriptProperties().deleteProperty('batchIndexDropbox'); Logger.log("Batch index reset to start from the beginning (row 4)"); } // Function to reset old Dropbox credentials. function resetDropboxAuth() { PropertiesService.getUserProperties().deleteAllProperties(); Logger.log("Dropbox authorization reset. Re-run authorizeDropbox()."); } ``` Typical Log Output: Here are examples of the log messages I typically see when the script runs: API Response Log: `3 March 2025, 15:10:42 Info API Response for https://www.dropbox.com/scl/fo/REPLACE_URL?dl=0: {"tag": "folder", "url": "https://www.dropbox.com/scl/fo/REPLACE_URL?dl=0", "id": "id:REPLACE_ID", "name": "REPLACE_NAME", "link_permissions": { ... }, "team_member_info": { ... }}` Fallback Log: `3 March 2025, 15:10:42 Info Fallback API Response for https://www.dropbox.com/scl/fo/REPLACE_URL?dl=0: Error in call to API function "files/get_metadata": request body: unknown field 'shared_link'` In these logs, all sensitive details (such as URLs, IDs, names, and team names) have been replaced with placeholders. My question is: Why isn't the path_display property being returned by the Dropbox API, even though my account has the necessary permissions? Retrieving this property is crucial because it allows me to move folders in Dropbox and still maintain the most recent folder path in my interactive map. This is why I run weekly updates—to ensure that the map reflects any changes in folder structure. Any help or suggestions would be greatly appreciated!Solved202Views0likes1CommentTricks for exporting file names to an Excel spreadsheet as index.
I have tried Zappier and other automations for exporting folders, subfolders, and even the files names to an excel spreadsheet to create an index or guide, even with the link for an easier access. Can anyone share a way to do such export or copy paste hack?731Views0likes4CommentsHow do admins of orgs using Dropbox for Business support end users with syncing issues?
This is a general question for admins in organizations using Dropbox for Business. How do you support users who are having Dropbox syncing issues on Windows endpoints? I have been creating a screen sharing session where I can investigate syncing issues on the endpoint. It seems to me that Dropbox for Business is missing some kind of telemetry from endpoints that gives status on sync health back to the admin console. Something that reported back every 15 mins would be better than flying blind. I would even take a log file saved into the AppData folder that logged sync status when it wasn't "finished". It seems like a reasonable feature.1.5KViews0likes6CommentsRetrieve your content more quickly with our new advanced search operators!
Hi Dropbox community! I'm a product manager at Dropbox working on the search experience on dropbox.com. Paid users already have access to advanced search features like full-text search, OCR (searching for text within images), full-text search, and image search (searching for objects within images). However, this can often return a lot of results leading to a poor experience having to wade through and find exactly what you're looking for. So, we're happy to announce that we're adding a few new operators to help you retrieve your files/folders more quickly: title:(new lead) => See results with only the specific words in title of the file title:"new lead" => See results with exact phrase match in title of the file. Note that quotes only work with title searches and can't be used to match on content type:image => Filter results by a certain types like image, video, document, spreadsheet, etc. type:jpg => Filter results by a certain types like file extension like jpg, png, docx, etc. before:2022-01-01 => Allows you to see all content before a certain date. Uses YYYY-MM-DD format. after:2022-01-01 => Allows you to see all content after a certain date. Uses YYYY-MM-DD format. lead AND new => AND operators will show results that contain both words. lead OR new => OR operators will show results that contain either words. To use these operators, login to Dropbox.com, click on the searchbox at the top, and start typing your query. You can learn more about our operators on our help center article here: https://help.dropbox.com/view-edit/search Note that there are some limitations: - This feature is Web only (for now) - Searches may return inaccurate results for contents of a file, certain images, and Paper docs if you're using the old release of Dropbox Paper. - Quotes will only work on file titles, not matches on content (for now) Try it out and let us know what you think! Thanks for your patience as we ship new features to improve your overall Dropbox experience! Rhut4.2KViews7likes2CommentsHow we use Dropbox to edit PDFs: Lauren
You might not know this but us Dropboxers get just as excited about new Dropbox features as anyone. In fact, Lauren, an unstoppable member of our social team, shared how the new PDF editing update has factored in to her life. How we use Dropbox to edit PDFs: Lauren One of my new favorite Dropbox features is PDF editing. It's been so helpful for consolidating receipts and organizing documents - whatever about how helpful it is at work, it has helped me to keep my life on track. For example, my auto mechanic prints out a receipt every time I need to get my car serviced. Instead of stuffing all the paper receipts in my car, and losing them to the blackhole of my glovebox, I use Dropbox Scanner app to scan receipts on the go, then consolidate my digital receipts into specific categories. If I have to get a new set of tires, I add that receipt to an existing PDF called “Ongoing Maintenance.” If I get an oil change, I add that new receipt to an existing PDF called “Oil Changes.” This enables me to easily access and keep track of all the work I’ve had done on my car. These documents are also saved in my Family Room folder that’s part of my Dropbox Family account, which enables my husband to easily access these documents whenever needed. It also means I can look back on the documents regularly and know what’s up to date on the car and what needs attention. The plan now is to expand this to more than just my car, so any home updates are tracked, and general life admin are all managed with just a few simple clicks. I know I say this every time we share how the Dropbox team use Dropbox, but I really will have to start doing this myself. I don’t need to wait for the dash to light up like a Christmas tree - and Lauren certainly makes it sound easy. Don’t forget, we have more tips on PDFs available here too. Do you use Dropbox to keep your personal life organized? Tell us how in the comments below!1.7KViews0likes0CommentsWeb Videos now supports auto-generated Video Transcriptions + Closed Captioning
Hey folks! My name is Derrick and I work on a team that improves the file preview and viewing experience at Dropbox. We are excited to announce two features on Dropbox.com to enhance your video viewing experience: video transcriptions and closed captioning. Here’s how to use: Simply upload your video to Dropbox and voila! Your videos will have auto-generated transcripts and closed captioning at your disposal with a click of a button. Even more so - watch videos shared from your colleagues - and copy transcribed segments to instantly quote them in a presentation. Tell me about your experience with our new features! We are all ears. Help Center Article URL: https://help.dropbox.com/view-edit/transcript-closed-captions12KViews9likes9Comments