File Storage with JavaScript SDK

Comprehensive guide to uploading, managing, and organizing audio files using the VerbalisAI JavaScript SDK.

File Upload

Node.js File Upload

import { VerbalisAI } from '@verbalisai/sdk';
import fs from 'fs';

const client = new VerbalisAI();

async function uploadLocalFile() {
  try {
    // Upload a single file
    const fileStream = fs.createReadStream('audio.mp3');
    
    const fileInfo = await client.files.upload({
      file: fileStream,
      filename: 'my-audio.mp3'
    });
    
    console.log('File uploaded successfully!');
    console.log(`URL: ${fileInfo.url}`);
    console.log(`File ID: ${fileInfo.id}`);
    console.log(`Size: ${fileInfo.sizeBytes} bytes`);
    console.log(`Upload date: ${fileInfo.createdAt}`);
  } catch (error) {
    console.error('Upload error:', error.message);
  }
}

uploadLocalFile();

Browser File Upload

// HTML: <input type="file" id="audioFile" accept="audio/*">

async function uploadFromBrowser() {
  const fileInput = document.getElementById('audioFile');
  const file = fileInput.files[0];
  
  if (!file) {
    console.log('No file selected');
    return;
  }
  
  try {
    const fileInfo = await client.files.upload({
      file: file,
      filename: file.name
    });
    
    console.log('File uploaded successfully!');
    console.log(`URL: ${fileInfo.url}`);
    console.log(`File ID: ${fileInfo.id}`);
    console.log(`Size: ${fileInfo.sizeBytes} bytes`);
  } catch (error) {
    console.error('Upload error:', error.message);
  }
}

// Attach to file input change event
document.getElementById('audioFile').addEventListener('change', uploadFromBrowser);

Upload with Metadata

async function uploadWithMetadata() {
  try {
    const fileInput = document.getElementById('audioFile');
    const file = fileInput.files[0];
    
    const fileInfo = await client.files.upload({
      file: file,
      filename: 'meeting-recording.mp3',
      
      // Optional metadata
      tags: ['meeting', 'quarterly', '2025'],
      description: 'Q2 2025 team meeting recording',
      folder: 'meetings/2025/q2',
      
      // File settings
      public: false,  // Keep file private
      autoDeleteDays: 30  // Delete after 30 days
    });
    
    console.log(`File uploaded to: ${fileInfo.folder}`);
    console.log(`Tags: ${fileInfo.tags.join(', ')}`);
    console.log(`Auto-delete date: ${fileInfo.autoDeleteDate}`);
  } catch (error) {
    console.error('Upload error:', error.message);
  }
}

uploadWithMetadata();

Batch File Upload

async function batchUpload() {
  const fileInput = document.getElementById('multipleFiles');
  const files = Array.from(fileInput.files);
  
  if (files.length === 0) {
    console.log('No files selected');
    return;
  }
  
  console.log(`Uploading ${files.length} files...`);
  
  try {
    // Upload all files concurrently
    const uploadPromises = files.map(file => 
      client.files.upload({
        file: file,
        filename: file.name,
        folder: 'batch_upload'
      }).catch(error => ({ error: error.message, filename: file.name }))
    );
    
    const results = await Promise.all(uploadPromises);
    
    let successfulUploads = 0;
    let failedUploads = 0;
    
    results.forEach(result => {
      if (result.error) {
        console.error(`Failed to upload ${result.filename}: ${result.error}`);
        failedUploads++;
      } else {
        console.log(`Uploaded ${result.filename}: ${result.url}`);
        successfulUploads++;
      }
    });
    
    console.log(`\nBatch upload complete:`);
    console.log(`  Successful: ${successfulUploads}`);
    console.log(`  Failed: ${failedUploads}`);
  } catch (error) {
    console.error('Batch upload error:', error);
  }
}

batchUpload();

Upload Progress Tracking

class UploadProgressTracker {
  constructor(client) {
    this.client = client;
  }
  
  async uploadWithProgress(file, options = {}) {
    const { onProgress, ...uploadOptions } = options;
    
    // Create upload session for progress tracking
    const uploadSession = await this.client.files.createUploadSession({
      filename: file.name,
      fileSize: file.size,
      ...uploadOptions
    });
    
    const chunkSize = 5 * 1024 * 1024; // 5MB chunks
    const totalChunks = Math.ceil(file.size / chunkSize);
    let uploadedChunks = 0;
    
    try {
      for (let start = 0; start < file.size; start += chunkSize) {
        const end = Math.min(start + chunkSize, file.size);
        const chunk = file.slice(start, end);
        
        await uploadSession.uploadChunk(chunk, uploadedChunks);
        uploadedChunks++;
        
        // Report progress
        const progress = (uploadedChunks / totalChunks) * 100;
        if (onProgress) {
          onProgress({
            loaded: end,
            total: file.size,
            percentage: progress,
            chunk: uploadedChunks,
            totalChunks
          });
        }
        
        console.log(`Progress: ${progress.toFixed(1)}%`);
      }
      
      // Complete the upload
      const fileInfo = await uploadSession.complete();
      console.log('Upload completed successfully!');
      return fileInfo;
      
    } catch (error) {
      await uploadSession.abort();
      throw error;
    }
  }
}

// Usage
async function uploadWithProgressTracking() {
  const fileInput = document.getElementById('audioFile');
  const file = fileInput.files[0];
  
  if (!file) return;
  
  const tracker = new UploadProgressTracker(client);
  
  try {
    const fileInfo = await tracker.uploadWithProgress(file, {
      folder: 'uploads',
      onProgress: (progress) => {
        // Update progress bar in UI
        updateProgressBar(progress.percentage);
        console.log(`Uploading: ${progress.percentage.toFixed(1)}% (${progress.chunk}/${progress.totalChunks} chunks)`);
      }
    });
    
    console.log('File uploaded:', fileInfo.url);
  } catch (error) {
    console.error('Upload failed:', error);
  }
}

function updateProgressBar(percentage) {
  const progressBar = document.getElementById('progressBar');
  if (progressBar) {
    progressBar.style.width = `${percentage}%`;
    progressBar.textContent = `${percentage.toFixed(1)}%`;
  }
}

File Management

List Files

async function listFiles() {
  try {
    // List all files
    const files = await client.files.list();
    console.log(`Total files: ${files.length}`);
    
    files.forEach(file => {
      console.log(`  ${file.filename} (${file.sizeBytes} bytes) - ${file.createdAt}`);
    });
    
    // List files with filtering
    const meetingFiles = await client.files.list({
      folder: 'meetings',
      tags: ['quarterly'],
      createdAfter: '2025-01-01',
      limit: 50
    });
    
    console.log(`\nMeeting files: ${meetingFiles.length}`);
  } catch (error) {
    console.error('Error listing files:', error);
  }
}

listFiles();

Search Files

async function searchFiles() {
  try {
    // Search by filename
    const results = await client.files.search({
      query: 'meeting',
      searchIn: ['filename', 'description', 'tags']
    });
    
    console.log(`Found ${results.length} files matching 'meeting':`);
    results.forEach(file => {
      console.log(`  ${file.filename}: ${file.description}`);
    });
    
    // Advanced search
    const advancedResults = await client.files.search({
      query: 'quarterly team',
      folder: 'meetings',
      fileType: 'audio/mpeg',
      sizeMin: 1000000,  // At least 1MB
      createdAfter: '2025-01-01'
    });
    
    console.log(`Advanced search results: ${advancedResults.length}`);
  } catch (error) {
    console.error('Search error:', error);
  }
}

searchFiles();

Get File Information

async function getFileInfo(fileId) {
  try {
    const fileInfo = await client.files.get(fileId);
    
    console.log(`Filename: ${fileInfo.filename}`);
    console.log(`Size: ${fileInfo.sizeBytes} bytes (${fileInfo.sizeHuman})`);
    console.log(`Type: ${fileInfo.mimeType}`);
    console.log(`Duration: ${fileInfo.durationSeconds} seconds`);
    console.log(`Sample rate: ${fileInfo.sampleRate} Hz`);
    console.log(`Channels: ${fileInfo.channels}`);
    console.log(`Folder: ${fileInfo.folder}`);
    console.log(`Tags: ${fileInfo.tags.join(', ')}`);
    console.log(`Public: ${fileInfo.public}`);
    console.log(`Downloads: ${fileInfo.downloadCount}`);
  } catch (error) {
    console.error('Error getting file info:', error);
  }
}

getFileInfo('your-file-id');

File Organization

Folder Management

async function manageFolders() {
  try {
    // Create folder structure
    await client.files.createFolder('projects');
    await client.files.createFolder('projects/client-a');
    await client.files.createFolder('projects/client-a/meetings');
    await client.files.createFolder('projects/client-a/interviews');
    
    // List folders
    const folders = await client.files.listFolders();
    console.log('Folder structure:');
    folders.forEach(folder => {
      console.log(`  ${folder.path} (${folder.fileCount} files)`);
    });
    
    // Move files to folders
    const fileId = 'your-file-id';
    await client.files.move(fileId, 'projects/client-a/meetings');
    
    console.log('File moved to new folder');
  } catch (error) {
    console.error('Folder management error:', error);
  }
}

manageFolders();

Tagging System

async function manageTags() {
  try {
    const fileId = 'your-file-id';
    
    // Add tags to file
    await client.files.addTags(fileId, ['important', 'Q2-2025', 'client-meeting']);
    
    // Remove specific tags
    await client.files.removeTags(fileId, ['Q2-2025']);
    
    // Replace all tags
    await client.files.setTags(fileId, ['archived', 'processed']);
    
    // Get all available tags
    const allTags = await client.files.listTags();
    console.log('Available tags:');
    allTags.forEach(tag => {
      console.log(`  ${tag.name} (${tag.fileCount} files)`);
    });
  } catch (error) {
    console.error('Tag management error:', error);
  }
}

manageTags();

File Operations

Copy and Move Files

async function copyMoveFiles() {
  try {
    const fileId = 'your-file-id';
    
    // Copy file to another folder
    const copiedFile = await client.files.copy(fileId, {
      newFolder: 'backup',
      newFilename: 'backup-copy.mp3'
    });
    console.log(`File copied: ${copiedFile.id}`);
    
    // Move file to different folder
    await client.files.move(fileId, 'archive/2025');
    console.log('File moved to archive');
    
    // Rename file
    await client.files.rename(fileId, 'new-filename.mp3');
    console.log('File renamed');
  } catch (error) {
    console.error('File operation error:', error);
  }
}

copyMoveFiles();

File Sharing

async function shareFiles() {
  try {
    const fileId = 'your-file-id';
    
    // Make file public
    const publicUrl = await client.files.makePublic(fileId);
    console.log(`Public URL: ${publicUrl}`);
    
    // Create temporary sharing link
    const tempLink = await client.files.createShareLink(fileId, {
      expiresInHours: 24,
      password: 'optional-password',
      downloadLimit: 10
    });
    
    console.log(`Temporary link: ${tempLink.url}`);
    console.log(`Expires: ${tempLink.expiresAt}`);
    
    // Make file private again
    await client.files.makePrivate(fileId);
    console.log('File is now private');
  } catch (error) {
    console.error('File sharing error:', error);
  }
}

shareFiles();

Storage Analytics

Storage Usage

async function storageAnalytics() {
  try {
    // Get storage overview
    const storage = await client.files.getStorageInfo();
    
    console.log(`Storage used: ${storage.usedBytes} bytes (${storage.usedHuman})`);
    console.log(`Storage limit: ${storage.limitBytes} bytes (${storage.limitHuman})`);
    console.log(`Usage percentage: ${storage.usagePercentage.toFixed(1)}%`);
    console.log(`Files count: ${storage.fileCount}`);
    console.log(`Folders count: ${storage.folderCount}`);
    
    // Get usage by file type
    const usageByType = await client.files.getUsageByType();
    console.log('\nUsage by file type:');
    Object.entries(usageByType).forEach(([fileType, info]) => {
      console.log(`  ${fileType}: ${info.count} files, ${info.sizeHuman}`);
    });
    
    // Get usage by folder
    const usageByFolder = await client.files.getUsageByFolder();
    console.log('\nUsage by folder:');
    Object.entries(usageByFolder).forEach(([folder, info]) => {
      console.log(`  ${folder}: ${info.count} files, ${info.sizeHuman}`);
    });
  } catch (error) {
    console.error('Storage analytics error:', error);
  }
}

storageAnalytics();

Usage History

async function usageHistory() {
  try {
    // Get daily usage for the last 30 days
    const dailyUsage = await client.files.getDailyUsage({ days: 30 });
    
    console.log('Daily storage usage (last 30 days):');
    dailyUsage.forEach(day => {
      console.log(`  ${day.date}: ${day.uploads} uploads, ${day.sizeHuman} added`);
    });
    
    // Get monthly summary
    const monthlyUsage = await client.files.getMonthlyUsage({ year: 2025 });
    
    console.log('\nMonthly usage summary for 2025:');
    monthlyUsage.forEach(month => {
      console.log(`  ${month.month}: ${month.uploads} uploads, ${month.totalSizeHuman}`);
    });
  } catch (error) {
    console.error('Usage history error:', error);
  }
}

usageHistory();

File Lifecycle Management

Auto-Delete Policies

async function lifecycleManagement() {
  try {
    // Set auto-delete for old files
    await client.files.setAutoDeletePolicy({
      folder: 'temp',
      deleteAfterDays: 7
    });
    
    // Set archival policy for large files
    await client.files.setArchivePolicy({
      folder: 'archive',
      archiveAfterDays: 90,
      deleteAfterDays: 365
    });
    
    // Get files scheduled for deletion
    const scheduledDeletions = await client.files.listScheduledDeletions();
    
    console.log('Files scheduled for deletion:');
    scheduledDeletions.forEach(file => {
      console.log(`  ${file.filename}: ${file.deleteDate}`);
    });
    
    // Cancel deletion for specific file
    const fileId = 'file-to-keep';
    await client.files.cancelDeletion(fileId);
    console.log('Deletion cancelled');
  } catch (error) {
    console.error('Lifecycle management error:', error);
  }
}

lifecycleManagement();

Backup and Restore

async function backupRestore() {
  try {
    // Create backup of specific folder
    const backupId = await client.files.createBackup({
      folder: 'important-files',
      backupName: 'monthly-backup-june-2025'
    });
    
    console.log(`Backup created: ${backupId}`);
    
    // List available backups
    const backups = await client.files.listBackups();
    
    backups.forEach(backup => {
      console.log(`Backup: ${backup.name} (${backup.createdAt}) - ${backup.fileCount} files`);
    });
    
    // Restore from backup
    const restoredFiles = await client.files.restoreBackup(backupId, {
      restoreToFolder: 'restored-files'
    });
    
    console.log(`Restored ${restoredFiles.length} files`);
  } catch (error) {
    console.error('Backup/restore error:', error);
  }
}

backupRestore();

Advanced File Operations

File Processing

async function processFiles() {
  try {
    const fileId = 'your-audio-file-id';
    
    // Get audio analysis
    const analysis = await client.files.analyzeAudio(fileId);
    
    console.log(`Audio quality score: ${analysis.qualityScore}/10`);
    console.log(`Noise level: ${analysis.noiseLevel}%`);
    console.log(`Volume level: ${analysis.volumeLevel} dB`);
    console.log(`Speech percentage: ${analysis.speechPercentage}%`);
    
    // Optimize audio for transcription
    const optimizedFile = await client.files.optimizeForTranscription(fileId, {
      reduceNoise: true,
      normalizeVolume: true,
      removeSilence: true
    });
    
    console.log(`Optimized file: ${optimizedFile.id}`);
    console.log(`Size reduction: ${analysis.sizeBytes - optimizedFile.sizeBytes} bytes`);
  } catch (error) {
    console.error('File processing error:', error);
  }
}

processFiles();

File Conversion

async function convertFiles() {
  try {
    const fileId = 'your-file-id';
    
    // Convert to different formats
    const conversions = {
      mp3: { bitrate: '128k', quality: 'standard' },
      wav: { sampleRate: 16000, channels: 1 },  // Mono, 16kHz
      flac: { compressionLevel: 5 }
    };
    
    for (const [formatType, options] of Object.entries(conversions)) {
      const convertedFile = await client.files.convert(fileId, {
        targetFormat: formatType,
        options: options
      });
      
      console.log(`Converted to ${formatType}: ${convertedFile.filename}`);
      console.log(`Size: ${convertedFile.sizeBytes} bytes`);
    }
  } catch (error) {
    console.error('File conversion error:', error);
  }
}

convertFiles();

React Integration

File Upload Component

import React, { useState, useCallback } from 'react';
import { VerbalisAI } from '@verbalisai/sdk';

const FileUploadComponent = ({ onUploadComplete }) => {
  const [uploading, setUploading] = useState(false);
  const [progress, setProgress] = useState(0);
  const [uploadedFiles, setUploadedFiles] = useState([]);
  
  const client = new VerbalisAI();
  
  const handleFileUpload = useCallback(async (files) => {
    setUploading(true);
    setProgress(0);
    
    try {
      const uploadPromises = Array.from(files).map(async (file, index) => {
        const fileInfo = await client.files.upload({
          file: file,
          filename: file.name,
          folder: 'react-uploads',
          onProgress: (progressInfo) => {
            setProgress((prevProgress) => {
              // Update progress for this specific file
              const fileProgress = (progressInfo.percentage / files.length);
              const totalProgress = (index / files.length) * 100 + fileProgress;
              return Math.min(totalProgress, 100);
            });
          }
        });
        
        return {
          ...fileInfo,
          originalFile: file
        };
      });
      
      const results = await Promise.all(uploadPromises);
      setUploadedFiles(prev => [...prev, ...results]);
      
      if (onUploadComplete) {
        onUploadComplete(results);
      }
      
      setProgress(100);
    } catch (error) {
      console.error('Upload failed:', error);
      alert(`Upload failed: ${error.message}`);
    } finally {
      setUploading(false);
      setTimeout(() => setProgress(0), 2000); // Reset progress after 2 seconds
    }
  }, [client, onUploadComplete]);
  
  const handleDrop = useCallback((e) => {
    e.preventDefault();
    const files = e.dataTransfer.files;
    if (files.length > 0) {
      handleFileUpload(files);
    }
  }, [handleFileUpload]);
  
  const handleFileSelect = useCallback((e) => {
    const files = e.target.files;
    if (files.length > 0) {
      handleFileUpload(files);
    }
  }, [handleFileUpload]);
  
  return (
    <div className="file-upload-component">
      <div 
        className="upload-area"
        onDrop={handleDrop}
        onDragOver={(e) => e.preventDefault()}
        style={{
          border: '2px dashed #ccc',
          borderRadius: '8px',
          padding: '40px',
          textAlign: 'center',
          cursor: uploading ? 'not-allowed' : 'pointer'
        }}
      >
        <input
          type="file"
          multiple
          accept="audio/*"
          onChange={handleFileSelect}
          disabled={uploading}
          style={{ display: 'none' }}
          id="file-input"
        />
        
        <label htmlFor="file-input" style={{ cursor: 'inherit' }}>
          {uploading ? (
            <div>
              <p>Uploading files...</p>
              <div className="progress-bar" style={{
                width: '100%',
                height: '20px',
                backgroundColor: '#f0f0f0',
                borderRadius: '10px',
                overflow: 'hidden'
              }}>
                <div 
                  className="progress-fill"
                  style={{
                    width: `${progress}%`,
                    height: '100%',
                    backgroundColor: '#007bff',
                    transition: 'width 0.3s ease'
                  }}
                />
              </div>
              <p>{progress.toFixed(1)}%</p>
            </div>
          ) : (
            <div>
              <p>Drag & drop audio files here or click to select</p>
              <p>Supported formats: MP3, WAV, FLAC, M4A, OGG</p>
            </div>
          )}
        </label>
      </div>
      
      {uploadedFiles.length > 0 && (
        <div className="uploaded-files" style={{ marginTop: '20px' }}>
          <h3>Uploaded Files</h3>
          <ul>
            {uploadedFiles.map((file, index) => (
              <li key={index} style={{ marginBottom: '10px' }}>
                <strong>{file.filename}</strong>
                <br />
                <small>
                  Size: {(file.sizeBytes / 1024 / 1024).toFixed(2)} MB | 
                  Uploaded: {new Date(file.createdAt).toLocaleString()}
                </small>
                <br />
                <a href={file.url} target="_blank" rel="noopener noreferrer">
                  View File
                </a>
              </li>
            ))}
          </ul>
        </div>
      )}
    </div>
  );
};

export default FileUploadComponent;

File Manager Component

import React, { useState, useEffect } from 'react';
import { VerbalisAI } from '@verbalisai/sdk';

const FileManagerComponent = () => {
  const [files, setFiles] = useState([]);
  const [loading, setLoading] = useState(true);
  const [searchQuery, setSearchQuery] = useState('');
  const [selectedFolder, setSelectedFolder] = useState('');
  const [folders, setFolders] = useState([]);
  
  const client = new VerbalisAI();
  
  useEffect(() => {
    loadFiles();
    loadFolders();
  }, [selectedFolder, searchQuery]);
  
  const loadFiles = async () => {
    setLoading(true);
    try {
      let fileList;
      
      if (searchQuery) {
        fileList = await client.files.search({
          query: searchQuery,
          folder: selectedFolder || undefined
        });
      } else {
        fileList = await client.files.list({
          folder: selectedFolder || undefined,
          limit: 50
        });
      }
      
      setFiles(fileList);
    } catch (error) {
      console.error('Failed to load files:', error);
    } finally {
      setLoading(false);
    }
  };
  
  const loadFolders = async () => {
    try {
      const folderList = await client.files.listFolders();
      setFolders(folderList);
    } catch (error) {
      console.error('Failed to load folders:', error);
    }
  };
  
  const deleteFile = async (fileId, filename) => {
    if (!window.confirm(`Are you sure you want to delete "${filename}"?`)) {
      return;
    }
    
    try {
      await client.files.delete(fileId);
      setFiles(files.filter(file => file.id !== fileId));
      alert('File deleted successfully');
    } catch (error) {
      console.error('Failed to delete file:', error);
      alert(`Failed to delete file: ${error.message}`);
    }
  };
  
  const transcribeFile = async (fileId, filename) => {
    try {
      const file = files.find(f => f.id === fileId);
      
      const transcription = await client.transcriptions.create({
        audioUrl: file.url,
        model: 'mini',
        topics: true
      });
      
      alert(`Transcription started for "${filename}". ID: ${transcription.id}`);
    } catch (error) {
      console.error('Failed to start transcription:', error);
      alert(`Failed to transcribe file: ${error.message}`);
    }
  };
  
  return (
    <div className="file-manager">
      <div className="controls" style={{ marginBottom: '20px' }}>
        <input
          type="text"
          placeholder="Search files..."
          value={searchQuery}
          onChange={(e) => setSearchQuery(e.target.value)}
          style={{ 
            padding: '8px 12px', 
            marginRight: '10px',
            border: '1px solid #ccc',
            borderRadius: '4px'
          }}
        />
        
        <select
          value={selectedFolder}
          onChange={(e) => setSelectedFolder(e.target.value)}
          style={{ 
            padding: '8px 12px',
            border: '1px solid #ccc',
            borderRadius: '4px'
          }}
        >
          <option value="">All Folders</option>
          {folders.map(folder => (
            <option key={folder.path} value={folder.path}>
              {folder.path} ({folder.fileCount} files)
            </option>
          ))}
        </select>
      </div>
      
      {loading ? (
        <div>Loading files...</div>
      ) : (
        <div className="file-list">
          {files.length === 0 ? (
            <p>No files found</p>
          ) : (
            <table style={{ width: '100%', borderCollapse: 'collapse' }}>
              <thead>
                <tr style={{ borderBottom: '1px solid #ccc' }}>
                  <th style={{ padding: '12px', textAlign: 'left' }}>Name</th>
                  <th style={{ padding: '12px', textAlign: 'left' }}>Size</th>
                  <th style={{ padding: '12px', textAlign: 'left' }}>Created</th>
                  <th style={{ padding: '12px', textAlign: 'left' }}>Actions</th>
                </tr>
              </thead>
              <tbody>
                {files.map(file => (
                  <tr key={file.id} style={{ borderBottom: '1px solid #eee' }}>
                    <td style={{ padding: '12px' }}>
                      <strong>{file.filename}</strong>
                      {file.tags && file.tags.length > 0 && (
                        <div style={{ fontSize: '12px', color: '#666' }}>
                          Tags: {file.tags.join(', ')}
                        </div>
                      )}
                    </td>
                    <td style={{ padding: '12px' }}>
                      {(file.sizeBytes / 1024 / 1024).toFixed(2)} MB
                    </td>
                    <td style={{ padding: '12px' }}>
                      {new Date(file.createdAt).toLocaleDateString()}
                    </td>
                    <td style={{ padding: '12px' }}>
                      <button
                        onClick={() => transcribeFile(file.id, file.filename)}
                        style={{
                          padding: '4px 8px',
                          margin: '2px',
                          backgroundColor: '#007bff',
                          color: 'white',
                          border: 'none',
                          borderRadius: '4px',
                          cursor: 'pointer'
                        }}
                      >
                        Transcribe
                      </button>
                      <button
                        onClick={() => window.open(file.url, '_blank')}
                        style={{
                          padding: '4px 8px',
                          margin: '2px',
                          backgroundColor: '#28a745',
                          color: 'white',
                          border: 'none',
                          borderRadius: '4px',
                          cursor: 'pointer'
                        }}
                      >
                        Download
                      </button>
                      <button
                        onClick={() => deleteFile(file.id, file.filename)}
                        style={{
                          padding: '4px 8px',
                          margin: '2px',
                          backgroundColor: '#dc3545',
                          color: 'white',
                          border: 'none',
                          borderRadius: '4px',
                          cursor: 'pointer'
                        }}
                      >
                        Delete
                      </button>
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          )}
        </div>
      )}
    </div>
  );
};

export default FileManagerComponent;

Error Handling for File Operations

Robust File Upload

import { VerbalisAIError } from '@verbalisai/sdk';

async function robustFileUpload(file) {
  const maxRetries = 3;
  const retryDelay = 2000; // 2 seconds
  
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      const fileInfo = await client.files.upload({
        file: file,
        filename: file.name
      });
      
      console.log(`Upload successful on attempt ${attempt + 1}`);
      console.log(`File URL: ${fileInfo.url}`);
      return fileInfo;
      
    } catch (error) {
      console.log(`Upload attempt ${attempt + 1} failed: ${error.message}`);
      
      if (error instanceof VerbalisAIError) {
        if (error.statusCode === 413) { // File too large
          console.log('File is too large, consider compressing');
          break;
        } else if (error.statusCode === 507) { // Storage full
          console.log('Storage quota exceeded');
          break;
        } else if ([500, 502, 503].includes(error.statusCode)) { // Server errors
          if (attempt < maxRetries - 1) {
            const waitTime = retryDelay * Math.pow(2, attempt);
            console.log(`Retrying in ${waitTime}ms...`);
            await new Promise(resolve => setTimeout(resolve, waitTime));
            continue;
          }
        } else {
          console.log('Non-retryable error');
          break;
        }
      } else {
        console.log(`Unexpected error: ${error.message}`);
        break;
      }
    }
  }
  
  throw new Error('Upload failed after all retry attempts');
}

// Usage
async function handleFileUpload() {
  const fileInput = document.getElementById('audioFile');
  const file = fileInput.files[0];
  
  if (!file) return;
  
  try {
    const fileInfo = await robustFileUpload(file);
    console.log('Upload completed:', fileInfo.url);
  } catch (error) {
    console.error('Final upload error:', error.message);
  }
}

Integration with Transcription

Upload and Transcribe Workflow

async function uploadAndTranscribe(file) {
  try {
    console.log('Starting upload and transcription workflow...');
    
    // Step 1: Upload file
    console.log('Uploading file...');
    const fileInfo = await client.files.upload({
      file: file,
      filename: file.name,
      folder: 'meetings/june-2025',
      tags: ['meeting', 'team', 'planning']
    });
    
    console.log(`File uploaded: ${fileInfo.url}`);
    
    // Step 2: Transcribe uploaded file
    console.log('Starting transcription...');
    const transcription = await client.transcriptions.create({
      audioUrl: fileInfo.url,
      model: 'pro',
      diarize: true,
      topics: true,
      summarization: true,
      summaryType: 'bullets'
    });
    
    console.log(`Transcription completed: ${transcription.id}`);
    
    // Step 3: Update file with transcription metadata
    await client.files.updateMetadata(fileInfo.id, {
      transcriptionId: transcription.id,
      transcriptionStatus: 'completed',
      topics: transcription.topics
    });
    
    console.log('File metadata updated with transcription info');
    
    return {
      fileInfo,
      transcription
    };
  } catch (error) {
    console.error('Upload and transcribe workflow failed:', error);
    throw error;
  }
}

// Usage with file input
async function handleUploadAndTranscribe() {
  const fileInput = document.getElementById('audioFile');
  const file = fileInput.files[0];
  
  if (!file) {
    alert('Please select a file');
    return;
  }
  
  try {
    const result = await uploadAndTranscribe(file);
    
    console.log('Workflow completed successfully!');
    console.log('File:', result.fileInfo.url);
    console.log('Transcription:', result.transcription.text);
    console.log('Topics:', result.transcription.topics);
    console.log('Summary:', result.transcription.summary?.text);
  } catch (error) {
    alert(`Workflow failed: ${error.message}`);
  }
}

Ready to learn about SDK configuration? Check out the Configuration guide to learn about advanced client settings and customization options.