Introducción
Dropbox API ofrece a los desarrolladores la capacidad de integrar las funcionalidades de almacenamiento en la nube directamente en sus aplicaciones. Esta guía te llevará paso a paso por el proceso completo de creación de una aplicación que utiliza la API de Dropbox, desde la configuración inicial hasta la implementación de funcionalidades avanzadas.
La API de Dropbox permite realizar acciones como crear, leer, editar, mover y eliminar archivos y carpetas, además de gestionar permisos de compartir y recibir notificaciones de cambios mediante webhooks. Con más de 50 mil millones de llamadas API por mes, la plataforma de Dropbox es robusta y confiable para aplicaciones de cualquier escala.
Configuración Inicial
Creación de Cuenta de Desarrollador
Para comenzar a desarrollar con Dropbox, necesitas tener una cuenta de Dropbox activa. Si no tienes una, puedes crear una cuenta gratuita en dropbox.com. Una vez que tengas tu cuenta, podrás acceder al Developer Console en developers.dropbox.com.

Creación de Aplicación en App Console
El primer paso técnico es crear una nueva aplicación en el App Console de Dropbox. Este proceso es fundamental y determina las capacidades de tu aplicación:
Paso 1: Acceder al App Console
- Dirígete a dropbox.com/developers
- In
- Haz clic en "App Console"
Paso 2: Crear Nueva Aplicación
- Selecciona "Create app" (Crear aplicación)
- Elige "Scoped access" como tipo de API
- Selecciona el nivel de acceso:
- App folder: Acceso limitado a una carpeta específica de la aplicación
- Full Dropbox: Acceso completo a la cuenta de Dropbox del usuario

Paso 3: Configurar Detalles de la Aplicación
- Proporciona un nombre único para tu aplicación
- Completa la descripción de la aplicación
- Haz clic en "Create app"
Configuración de Permisos y Scopes
Una vez creada la aplicación, es crucial configurar los permisos correctos. Dropbox utiliza un sistema de scopes que determina qué acciones puede realizar tu aplicación:
Principales categorías de scopes:
- Account Info: Información de la cuenta del usuario
- Files and Folders: Operaciones con archivos y carpetas
- Collaboration (sharing): Funcionalidades de compartir
Configuración de permisos:
- Ve a la pestaña "Permissions" en tu aplicación
- Selecciona únicamente los scopes que necesites
- Haz clic en "Submit" para guardar los cambios

Implementación de OAuth 2.0
Flujo de Autorización con Código
Dropbox utiliza OAuth 2.0 como protocolo de autorización estándar. El flujo de código de autorización es el método recomendado para la mayoría de aplicaciones.
Componentes clave del flujo OAuth:
- Client ID: Identificador único de tu aplicación
- Client Secret: Clave secreta de tu aplicación (debe mantenerse segura)
- Authorization Code: Código temporal recibido después de la autorización del usuario
- Access Token: Token que permite realizar llamadas a la API
Implementación de PKCE
Para aplicaciones que no pueden mantener seguro el client secret (como aplicaciones de una sola página o aplicaciones móviles), Dropbox recomienda usar PKCE (Proof Key for Code Exchange).
Ventajas de PKCE:
- Mayor seguridad para aplicaciones públicas
- Eliminación de la necesidad de almacenar client secrets
- Protección contra ataques de intercepción de código
Implementación de PKCE:
// Generar code_verifier y code_challenge
function generateCodeVerifier() {
const array = new Uint32Array(56/2);
crypto.getRandomValues(array);
return Array.from(array, dec => ('0' + dec.toString(16)).substr(-2)).join('');
}
function generateCodeChallenge(verifier) {
const encoder = new TextEncoder();
const data = encoder.encode(verifier);
return crypto.subtle.digest('SHA-256', data).then(digest => {
return btoa(String.fromCharCode(...new Uint8Array(digest)))
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=/g, '');
});
}
Tokens de Acceso y Refresh Tokens
Dropbox ahora utiliza tokens de acceso de corta duración (generalmente 4 horas) junto con refresh tokens de larga duración para acceso offline.
Configuración para tokens offline:
- Agrega
token_access_type=offline
a tu URL de autorización - Guarda de forma segura el refresh token recibido
- Utiliza el refresh token para obtener nuevos access tokens

Desarrollo de la Aplicación
Configuración del SDK
Instalación del SDK de JavaScript:
npm install --save dropbox
npm install --save isomorphic-fetch
Configuración básica:
require('isomorphic-fetch');
const { Dropbox } = require('dropbox');
const dbx = new Dropbox({
accessToken: 'tu_access_token_aqui',
fetch: fetch
});
Para aplicaciones con refresh tokens:
const dbx = new Dropbox({
clientId: 'tu_client_id',
clientSecret: 'tu_client_secret',
refreshToken: 'tu_refresh_token'
});
Operaciones Básicas con Archivos
Listar archivos en una carpeta:
async function listarArchivos(ruta = '') {
try {
const response = await dbx.filesListFolder({path: ruta});
console.log('Archivos encontrados:', response.result.entries);
return response.result.entries;
} catch (error) {
console.error('Error al listar archivos:', error);
}
}
Subir un archivo:
async function subirArchivo(contenido, rutaDestino) {
try {
const response = await dbx.filesUpload({
path: rutaDestino,
contents: contenido,
mode: 'add',
autorename: true
});
console.log('Archivo subido exitosamente:', response.result);
return response.result;
} catch (error) {
console.error('Error al subir archivo:', error);
}
}
Descargar un archivo:
async function descargarArchivo(rutaArchivo) {
try {
const response = await dbx.filesDownload({path: rutaArchivo});
const contenido = response.result.fileBinary.toString();
console.log('Archivo descargado:', contenido);
return contenido;
} catch (error) {
console.error('Error al descargar archivo:', error);
}
}
Crear una carpeta:
async function crearCarpeta(rutaCarpeta) {
try {
const response = await dbx.filesCreateFolderV2({path: rutaCarpeta});
console.log('Carpeta creada:', response.result);
return response.result;
} catch (error) {
console.error('Error al crear carpeta:', error);
}
}
Manejo de Errores
Es fundamental implementar un manejo robusto de errores en tu aplicación:
async function manejarOperacionConReintentos(operacion, maxReintentos = 3) {
for (let intento = 1; intento <= maxReintentos; intento++) {
try {
return await operacion();
} catch (error) {
if (error.status === 401) {
// Token expirado, renovar
await renovarAccessToken();
continue;
} else if (error.status === 429) {
// Rate limit, esperar antes de reintentar
const tiempoEspera = Math.pow(2, intento) * 1000;
await new Promise(resolve => setTimeout(resolve, tiempoEspera));
continue;
} else if (intento === maxReintentos) {
throw error;
}
}
}
}
Ejemplos Prácticos
Aplicación Completa de Gestión de Archivos
class GestorArchivosDropbox {
constructor(accessToken) {
this.dbx = new Dropbox({
accessToken: accessToken,
fetch: fetch
});
}
async inicializar() {
try {
const cuenta = await this.dbx.usersGetCurrentAccount();
console.log('Conectado como:', cuenta.result.name.display_name);
return true;
} catch (error) {
console.error('Error de inicialización:', error);
return false;
}
}
async organizarArchivosPorFecha() {
try {
const archivos = await this.dbx.filesListFolder({path: ''});
for (const archivo of archivos.result.entries) {
if (archivo['.tag'] === 'file') {
const fecha = new Date(archivo.client_modified);
const año = fecha.getFullYear();
const mes = fecha.getMonth() + 1;
const carpetaDestino = `/${año}/${mes.toString().padStart(2, '0')}`;
// Crear carpeta si no existe
await this.crearCarpetaSiNoExiste(carpetaDestino);
// Mover archivo
await this.dbx.filesMoveV2({
from_path: archivo.path_lower,
to_path: `${carpetaDestino}/${archivo.name}`
});
}
}
} catch (error) {
console.error('Error al organizar archivos:', error);
}
}
async crearCarpetaSiNoExiste(ruta) {
try {
await this.dbx.filesCreateFolderV2({path: ruta});
} catch (error) {
if (error.status !== 409) { // 409 = carpeta ya existe
throw error;
}
}
}
async sincronizarCarpetaLocal(rutaLocal, rutaDropbox) {
const fs = require('fs');
const path = require('path');
if (!fs.existsSync(rutaLocal)) {
return;
}
const archivosLocales = fs.readdirSync(rutaLocal);
for (const archivo of archivosLocales) {
const rutaCompleta = path.join(rutaLocal, archivo);
const stats = fs.statSync(rutaCompleta);
if (stats.isFile()) {
const contenido = fs.readFileSync(rutaCompleta);
await this.dbx.filesUpload({
path: `${rutaDropbox}/${archivo}`,
contents: contenido,
mode: 'overwrite'
});
console.log(`Subido: ${archivo}`);
}
}
}
}
Implementación de Webhooks
const express = require('express');
const crypto = require('crypto');
const app = express();
app.use(express.raw({ type: 'application/json' }));
// Verificación del webhook
app.get('/webhook', (req, res) => {
const challenge = req.query.challenge;
console.log('Verificación de webhook:', challenge);
res.send(challenge);
});
// Procesamiento de notificaciones
app.post('/webhook', (req, res) => {
const signature = req.get('X-Dropbox-Signature');
const body = req.body;
// Verificar la firma del webhook
const expectedSignature = crypto
.createHmac('sha256', process.env.WEBHOOK_SECRET)
.update(body)
.digest('hex');
if (signature === expectedSignature) {
const notification = JSON.parse(body.toString());
console.log('Notificación recibida:', notification);
// Procesar cambios en archivos
procesarCambiosArchivos(notification);
res.status(200).send('OK');
} else {
res.status(403).send('Firma inválida');
}
});
async function procesarCambiosArchivos(notification) {
for (const cuenta of notification.list_folder.accounts) {
console.log(`Cambios en cuenta: ${cuenta}`);
// Implementar lógica específica de tu aplicación
}
}
Consideraciones de Seguridad
Mejores Prácticas de Seguridad
Almacenamiento seguro de credenciales:
- Nunca hardcodees tokens de acceso en el código fuente
- Utiliza variables de entorno para credenciales sensibles
- Implementa rotación regular de tokens
Validación de permisos:
- Solicita únicamente los permisos mínimos necesarios
- Implementa validación del lado del servidor
- Verifica la autenticidad de las solicitudes
Manejo de tokens:
class ManejadorTokensSeguro {
constructor() {
this.tokenStorage = new Map();
}
async guardarTokens(userId, accessToken, refreshToken) {
// Encriptar tokens antes de guardar
const tokensEncriptados = {
accessToken: this.encriptar(accessToken),
refreshToken: this.encriptar(refreshToken),
timestamp: Date.now()
};
this.tokenStorage.set(userId, tokensEncriptados);
}
async obtenerAccessToken(userId) {
const tokens = this.tokenStorage.get(userId);
if (!tokens) return null;
// Verificar si el token ha expirado
if (Date.now() - tokens.timestamp > 14400000) { // 4 horas
return await this.renovarToken(userId);
}
return this.desencriptar(tokens.accessToken);
}
encriptar(data) {
// Implementar encriptación AES
const cipher = crypto.createCipher('aes-256-ctr', process.env.ENCRYPTION_KEY);
return cipher.update(data, 'utf8', 'hex') + cipher.final('hex');
}
desencriptar(data) {
const decipher = crypto.createDecipher('aes-256-ctr', process.env.ENCRYPTION_KEY);
return decipher.update(data, 'hex', 'utf8') + decipher.final('utf8');
}
}
Validación de webhooks:
function validarWebhook(req) {
const signature = req.get('X-Dropbox-Signature');
const body = req.body;
const expectedSignature = crypto
.createHmac('sha256', process.env.DROPBOX_WEBHOOK_SECRET)
.update(body)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature, 'hex'),
Buffer.from(expectedSignature, 'hex')
);
}
Cumplimiento y Regulaciones
Consideraciones importantes:
- Cumplimiento con GDPR para usuarios europeos
- Políticas de retención de datos
- Auditorías regulares de seguridad
- Documentación de procesos de manejo de datos
Conclusión
La implementación de una aplicación con Dropbox API requiere una comprensión sólida del flujo OAuth 2.0, el manejo adecuado de tokens, y la implementación de medidas de seguridad robustas. Los pasos fundamentales incluyen:
- Configuración correcta de la aplicación en el App Console con permisos mínimos necesarios
- Implementación segura del flujo de autenticación usando PKCE cuando sea apropiado
- Manejo robusto de errores y reintentos para garantizar la fiabilidad
- Seguridad de primera clase en el almacenamiento y manejo de tokens
- Monitoreo y mantenimiento continuo de la aplicación
Con esta base sólida, puedes desarrollar aplicaciones potentes que aprovechen las capacidades de almacenamiento y colaboración de Dropbox, proporcionando valor real a tus usuarios mientras mantienes los más altos estándares de seguridad y confiabilidad.
La API de Dropbox ofrece un ecosistema robusto para el desarrollo de aplicaciones modernas, y con las herramientas y conocimientos proporcionados en esta guía, estás preparado para crear soluciones innovadoras que integren perfectamente con la plataforma de Dropbox.
Referencias
Las siguientes fuentes fueron consultadas para la elaboración de esta guía:
- Documentación oficial de OAuth de Dropbox - developers.dropbox.com/oauth-guide
- Guía de inicio para desarrolladores de Dropbox - dropbox.com/developers/reference/getting-started
- Documentación del SDK de JavaScript - dropbox.github.io/dropbox-sdk-js/
- Guía de PKCE para OAuth 2.0 - dropbox.tech/developers/pkce--what-and-why-
- Implementación de tokens de acceso offline - dropbox.tech/developers/using-oauth-2-0-with-offline-access
- Mejores prácticas de seguridad para aplicaciones OAuth
- Documentación de la API HTTP de Dropbox v2
- Ejemplos de implementación en GitHub - github.com/dropbox/dropbox-sdk-js
- Foros de desarrolladores de Dropbox para resolución de problemas comunes
- Guías de migración de permisos y tokens de acceso
- https://developers.dropbox.com/oauth-guide
- https://www.dropbox.com/developers/reference/getting-started
- https://klamp.io/blog/guide-to-the-dropbox-developer-console
- https://help.tableau.com/current/server/es-es/config_oauth_dropbox.htm
- https://docs.gravityforms.com/creating-a-custom-dropbox-app/
- https://rollout.com/integration-guides/dropbox/sdk/step-by-step-guide-to-building-a-dropbox-api-integration-in-php
- https://www.dropbox.com/developers/reference/developer-guide
- https://www.dropbox.com/developers/reference
- https://help.scriptcase.net/portal/es/kb/articles/habilitacion-de-la-api-de-dropbox
- https://www.youtube.com/watch?v=LA8uSoOfPF4
- https://www.dropbox.com/developers
- https://dropbox.tech/developers/migrating-app-permissions-and-access-tokens
- https://www.dropbox.com/developers/documentation
- https://www.dropboxforum.com/discussions/101000014/where-to-start/575536
- https://help.dropbox.com/es-la/account-access/active-directory-connector
- https://www.dropbox.com/es/developers
- https://www.dropboxforum.com/discussions/101001016/dropbox-configuration-for-dummies/732392
- https://www.dropbox.com/es/developers/reference
- https://www.dropboxforum.com/discussions/101000014/create-app/799072
- https://www.dropbox.com/developers/documentation/http/documentation
- https://www.dropbox.com/developers/documentation/javascript
- https://www.youtube.com/watch?v=AzCQrjWQJs4
- https://www.youtube.com/watch?v=dUtDrmt9XZc
- https://www.npmjs.com/package/dropbox/v/4.0.9
- https://github.com/dropbox/dropbox-sdk-js
- https://developer.jitterbit.com/es/connector-sdk/tutorial/
- https://stackoverflow.com/questions/64300111/download-contents-of-dropbox-file-in-nodejs
- https://www.dropbox.com/developers/saver
- https://stackoverflow.com/questions/71207946/how-to-implement-dropboxoauth2flow-in-node-js
- https://dropbox.github.io/dropbox-sdk-js/Dropbox.html
- https://www.youtube.com/watch?v=9EqZepyuulo
- https://www.youtube.com/watch?v=gP7LwR5F5vE
- https://learn.dropbox.com/es/self-guided-learning/dropbox-fundamentals-course/how-to-use-dropbox
- https://dropbox.github.io/dropbox-sdk-js/
- https://help.dropbox.com/es-la/installs/homepage
- https://www.youtube.com/watch?v=jLRYQgOg2JY
- https://www.dropbox.com/developers/documentation/http/overview
- https://docs.workato.com/developing-connectors/sdk/guides/authentication/oauth/auth-code-pkce.html
- https://www.reddit.com/r/programming/comments/13kt2go/dropbox_api_auth_help/
- https://dropbox.tech/developers/pkce--what-and-why-
- https://help.dropbox.com/es-la/integrations/app-integrations
- https://stackoverflow.com/questions/70641660/how-do-you-get-and-use-a-refresh-token-for-the-dropbox-api-python-3-x
- https://dropbox.tech/developers/using-oauth-2-0-with-offline-access
- https://community.retool.com/t/dropbox-refresh-token-and-access/35868
- https://github.com/dropbox/dropbox-sdk-python/blob/main/example/oauth/commandline-oauth-pkce.py
- https://www.dropboxforum.com/discussions/101000014/how-to-get-an-access-token-and-refresh-token/683861
- https://help.dropbox.com/es-la/account-settings/account-settings
- https://www.codemzy.com/blog/dropbox-long-lived-access-refresh-token
- https://www.dropboxforum.com/discussions/101000014/is-there-a-pkce-example-for-a-a-client-side-web-application-pure-javascript/504550
- https://stackoverflow.com/questions/65065966/how-can-i-implement-dropbox-oauth2-pkce-flow-with-blazor-webassembly
- https://help.dropbox.com/es-la/account-settings/mobile-app-settings