OpenAI Files API: Complete Guide to Upload, Manage & Delete Files
The OpenAI Files API allows you to upload, manage, and delete files for use with Assistants, fine-tuning, and vector stores. While powerful, the API lacks built-in bulk operations and visual management tools, making file management challenging for developers working with large datasets.
This comprehensive guide covers everything you need to know about the OpenAI Files API, including practical code examples, best practices, common issues, and solutions for efficient file management.
Table of Contents
- OpenAI Files API Overview
- File Upload Methods
- File Management Operations
- Vector Store Integration
- File Purposes and Limitations
- Bulk Operations Challenge
- Best Practices
- Common Issues and Solutions
- API Reference Examples
- File Management Tools
OpenAI Files API Overview
The OpenAI Files API provides endpoints for managing files used across OpenAI's platform. Files can serve different purposes including Assistants API integration, fine-tuning datasets, and vector store content.
Supported File Types and Limits
File Size Limits:
- Individual files: Up to 512 MB per file
- Organization total: 100 GB across all files
- Vector stores: 10,000 files per vector store maximum
Supported File Formats:
- Documents: PDF, TXT, DOCX, MD, HTML
- Code: JS, PY, JSON, CSV, XML
- Data: JSONL (for fine-tuning)
- Images: PNG, JPEG, GIF, WEBP (for vision models)
File Purposes
Files are categorized by purpose, which determines how they can be used:
assistants
: Files for use with the Assistants APIvision
: Images for vision model processingbatch
: Files for batch processingfine-tune
: Training data for model fine-tuninguser_data
: General user data files
File Upload Methods
Basic File Upload
import OpenAI from 'openai';
import fs from 'fs';
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY
});
// Upload a single file
async function uploadFile(filePath, purpose = 'assistants') {
try {
const file = await openai.files.create({
file: fs.createReadStream(filePath),
purpose: purpose
});
console.log('File uploaded:', file.id);
return file;
} catch (error) {
console.error('Upload failed:', error.message);
}
}
// Usage
const uploadedFile = await uploadFile('./document.pdf', 'assistants');
Upload with Error Handling
async function uploadFileWithRetry(filePath, purpose = 'assistants', maxRetries = 3) {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
const file = await openai.files.create({
file: fs.createReadStream(filePath),
purpose: purpose
});
return {
success: true,
file: file,
filename: filePath.split('/').pop()
};
} catch (error) {
console.error(`Upload attempt ${attempt} failed:`, error.message);
if (attempt === maxRetries) {
return {
success: false,
error: error.message,
filename: filePath.split('/').pop()
};
}
// Wait before retry
await new Promise(resolve => setTimeout(resolve, 1000 * attempt));
}
}
}
Batch Upload Multiple Files
async function uploadMultipleFiles(filePaths, purpose = 'assistants') {
const results = [];
const concurrency = 3; // Limit concurrent uploads
for (let i = 0; i < filePaths.length; i += concurrency) {
const batch = filePaths.slice(i, i + concurrency);
const batchPromises = batch.map(filePath =>
uploadFileWithRetry(filePath, purpose)
);
const batchResults = await Promise.all(batchPromises);
results.push(...batchResults);
// Progress logging
console.log(`Uploaded ${Math.min(i + concurrency, filePaths.length)} of ${filePaths.length} files`);
}
return results;
}
// Usage
const filePaths = ['./doc1.pdf', './doc2.txt', './doc3.docx'];
const uploadResults = await uploadMultipleFiles(filePaths);
// Check results
const successful = uploadResults.filter(r => r.success);
const failed = uploadResults.filter(r => !r.success);
console.log(`Successfully uploaded: ${successful.length}`);
console.log(`Failed uploads: ${failed.length}`);
File Management Operations
List Files
// List all files
async function listAllFiles() {
try {
const files = await openai.files.list();
return files.data;
} catch (error) {
console.error('Failed to list files:', error.message);
return [];
}
}
// List files by purpose
async function listFilesByPurpose(purpose) {
const allFiles = await listAllFiles();
return allFiles.filter(file => file.purpose === purpose);
}
// List files with details
async function listFilesWithDetails() {
const files = await listAllFiles();
return files.map(file => ({
id: file.id,
filename: file.filename,
purpose: file.purpose,
size: `${(file.bytes / 1024 / 1024).toFixed(2)} MB`,
created: new Date(file.created_at * 1000).toISOString(),
status: file.status
}));
}
Retrieve File Information
// Get file metadata
async function getFileInfo(fileId) {
try {
const file = await openai.files.retrieve(fileId);
return {
id: file.id,
filename: file.filename,
purpose: file.purpose,
size: file.bytes,
created: new Date(file.created_at * 1000),
status: file.status
};
} catch (error) {
console.error(`Failed to retrieve file ${fileId}:`, error.message);
return null;
}
}
// Check file processing status
async function checkFileStatus(fileId) {
const fileInfo = await getFileInfo(fileId);
if (!fileInfo) {
return 'not_found';
}
return fileInfo.status; // 'uploaded', 'processed', 'error'
}
Delete Files
// Delete a single file
async function deleteFile(fileId) {
try {
const result = await openai.files.del(fileId);
console.log(`File ${fileId} deleted:`, result.deleted);
return result.deleted;
} catch (error) {
console.error(`Failed to delete file ${fileId}:`, error.message);
return false;
}
}
// Delete multiple files (sequential to avoid rate limits)
async function deleteMultipleFiles(fileIds) {
const results = [];
for (const fileId of fileIds) {
const deleted = await deleteFile(fileId);
results.push({ fileId, deleted });
// Brief pause to respect rate limits
await new Promise(resolve => setTimeout(resolve, 100));
}
return results;
}
// Delete files by criteria
async function deleteFilesByPurpose(purpose, olderThanDays = null) {
const files = await listFilesByPurpose(purpose);
let filesToDelete = files;
if (olderThanDays) {
const cutoffDate = new Date();
cutoffDate.setDate(cutoffDate.getDate() - olderThanDays);
filesToDelete = files.filter(file => {
const fileDate = new Date(file.created_at * 1000);
return fileDate < cutoffDate;
});
}
console.log(`Deleting ${filesToDelete.length} files with purpose: ${purpose}`);
const fileIds = filesToDelete.map(file => file.id);
return await deleteMultipleFiles(fileIds);
}
Retrieve File Content
// Download file content
async function downloadFileContent(fileId, outputPath = null) {
try {
const response = await openai.files.content(fileId);
if (outputPath) {
// Save to file
const buffer = Buffer.from(await response.arrayBuffer());
fs.writeFileSync(outputPath, buffer);
console.log(`File content saved to: ${outputPath}`);
return outputPath;
} else {
// Return content as text (for text files)
return await response.text();
}
} catch (error) {
console.error(`Failed to retrieve content for file ${fileId}:`, error.message);
// Check if file purpose allows content retrieval
if (error.message.includes('Not allowed to download')) {
console.log('Tip: Some file purposes (like fine-tune) restrict content download');
}
return null;
}
}
// Check if file content can be retrieved
async function canDownloadFile(fileId) {
try {
await openai.files.content(fileId);
return true;
} catch (error) {
return false;
}
}
Vector Store Integration
Add Files to Vector Store
// Create vector store with files
async function createVectorStoreWithFiles(name, fileIds) {
try {
// Create the vector store
const vectorStore = await openai.beta.vectorStores.create({
name: name
});
// Add files to vector store
if (fileIds.length > 0) {
await openai.beta.vectorStores.fileBatches.create(vectorStore.id, {
file_ids: fileIds
});
}
return vectorStore;
} catch (error) {
console.error('Failed to create vector store:', error.message);
return null;
}
}
// Add files to existing vector store
async function addFilesToVectorStore(vectorStoreId, fileIds) {
try {
const batch = await openai.beta.vectorStores.fileBatches.create(vectorStoreId, {
file_ids: fileIds
});
console.log(`Added ${fileIds.length} files to vector store ${vectorStoreId}`);
return batch;
} catch (error) {
console.error('Failed to add files to vector store:', error.message);
return null;
}
}
// Remove files from vector store
async function removeFilesFromVectorStore(vectorStoreId, fileIds) {
const results = [];
for (const fileId of fileIds) {
try {
await openai.beta.vectorStores.files.del(vectorStoreId, fileId);
results.push({ fileId, removed: true });
} catch (error) {
console.error(`Failed to remove file ${fileId}:`, error.message);
results.push({ fileId, removed: false, error: error.message });
}
}
return results;
}
// List files in vector store
async function listVectorStoreFiles(vectorStoreId) {
try {
const files = await openai.beta.vectorStores.files.list(vectorStoreId);
return files.data;
} catch (error) {
console.error(`Failed to list vector store files:`, error.message);
return [];
}
}
Vector Store File Management
// Complete vector store management example
async function manageVectorStore(vectorStoreName, documentPaths) {
console.log(`Setting up vector store: ${vectorStoreName}`);
// 1. Upload all documents
console.log('Uploading documents...');
const uploadResults = await uploadMultipleFiles(documentPaths, 'assistants');
const successfulUploads = uploadResults.filter(r => r.success);
if (successfulUploads.length === 0) {
console.error('No files uploaded successfully');
return null;
}
// 2. Create vector store with uploaded files
const fileIds = successfulUploads.map(r => r.file.id);
const vectorStore = await createVectorStoreWithFiles(vectorStoreName, fileIds);
if (!vectorStore) {
console.error('Failed to create vector store');
return null;
}
// 3. Wait for processing to complete
console.log('Waiting for vector store processing...');
await waitForVectorStoreProcessing(vectorStore.id);
console.log(`Vector store ${vectorStoreName} ready with ${fileIds.length} files`);
return vectorStore;
}
// Wait for vector store processing
async function waitForVectorStoreProcessing(vectorStoreId, maxWaitMinutes = 10) {
const startTime = Date.now();
const maxWaitTime = maxWaitMinutes * 60 * 1000;
while (Date.now() - startTime < maxWaitTime) {
try {
const vectorStore = await openai.beta.vectorStores.retrieve(vectorStoreId);
if (vectorStore.status === 'completed') {
console.log('Vector store processing completed');
return true;
} else if (vectorStore.status === 'failed') {
console.error('Vector store processing failed');
return false;
}
console.log(`Vector store status: ${vectorStore.status}`);
await new Promise(resolve => setTimeout(resolve, 10000)); // Wait 10 seconds
} catch (error) {
console.error('Error checking vector store status:', error.message);
break;
}
}
console.error('Vector store processing timeout');
return false;
}
File Purposes and Limitations
Understanding File Purposes
Different file purposes have different restrictions and capabilities:
const FILE_PURPOSES = {
'assistants': {
description: 'Files for Assistants API and vector stores',
maxSize: '512MB',
contentDownload: 'Limited', // Some restrictions apply
formats: ['pdf', 'txt', 'docx', 'md', 'html', 'json', 'csv'],
usage: 'Knowledge base, document analysis, RAG applications'
},
'vision': {
description: 'Images for vision model processing',
maxSize: '20MB',
contentDownload: 'Yes',
formats: ['png', 'jpeg', 'gif', 'webp'],
usage: 'Image analysis, vision tasks'
},
'batch': {
description: 'Files for batch processing',
maxSize: '100MB',
contentDownload: 'Yes',
formats: ['jsonl'],
usage: 'Batch API requests'
},
'fine-tune': {
description: 'Training data for fine-tuning',
maxSize: '1GB',
contentDownload: 'No', // Restricted for security
formats: ['jsonl'],
usage: 'Model fine-tuning datasets'
}
};
// Check if file purpose allows content download
function canDownloadByPurpose(purpose) {
const purposeInfo = FILE_PURPOSES[purpose];
return purposeInfo && purposeInfo.contentDownload !== 'No';
}
// Validate file for purpose
function validateFileForPurpose(filename, purpose) {
const purposeInfo = FILE_PURPOSES[purpose];
if (!purposeInfo) {
return { valid: false, error: `Unknown purpose: ${purpose}` };
}
const extension = filename.split('.').pop().toLowerCase();
if (!purposeInfo.formats.includes(extension)) {
return {
valid: false,
error: `File type .${extension} not supported for purpose ${purpose}. Supported: ${purposeInfo.formats.join(', ')}`
};
}
return { valid: true };
}
File Processing Status
// Monitor file processing status
async function monitorFileProcessing(fileId, maxWaitMinutes = 5) {
const startTime = Date.now();
const maxWaitTime = maxWaitMinutes * 60 * 1000;
console.log(`Monitoring file ${fileId} processing...`);
while (Date.now() - startTime < maxWaitTime) {
const status = await checkFileStatus(fileId);
switch (status) {
case 'processed':
console.log(`File ${fileId} processed successfully`);
return true;
case 'error':
console.error(`File ${fileId} processing failed`);
return false;
case 'not_found':
console.error(`File ${fileId} not found`);
return false;
case 'uploaded':
console.log(`File ${fileId} still processing...`);
break;
}
await new Promise(resolve => setTimeout(resolve, 5000)); // Wait 5 seconds
}
console.warn(`File ${fileId} processing timeout`);
return false;
}
Bulk Operations Challenge
One of the biggest limitations of the OpenAI Files API is the lack of built-in bulk operations. This creates several challenges for developers:
The Problem
// ❌ This doesn't exist in OpenAI API
// await openai.files.bulkDelete(fileIds);
// Instead, you must do this:
// ✅ Manual iteration required
async function bulkDeleteFiles(fileIds) {
for (const fileId of fileIds) {
try {
await openai.files.del(fileId);
console.log(`Deleted: ${fileId}`);
} catch (error) {
console.error(`Failed to delete ${fileId}:`, error.message);
}
// Rate limiting delay
await new Promise(resolve => setTimeout(resolve, 100));
}
}
Common Bulk Operations
Here are utility functions for common bulk operations:
// Bulk operations utility class
class OpenAIFileManager {
constructor(apiKey) {
this.openai = new OpenAI({ apiKey });
}
// Delete all files older than specified days
async cleanupOldFiles(olderThanDays = 30) {
const files = await this.openai.files.list();
const cutoffDate = new Date();
cutoffDate.setDate(cutoffDate.getDate() - olderThanDays);
const oldFiles = files.data.filter(file => {
const fileDate = new Date(file.created_at * 1000);
return fileDate < cutoffDate;
});
console.log(`Found ${oldFiles.length} files older than ${olderThanDays} days`);
const results = [];
for (const file of oldFiles) {
try {
await this.openai.files.del(file.id);
results.push({ id: file.id, filename: file.filename, deleted: true });
} catch (error) {
results.push({ id: file.id, filename: file.filename, deleted: false, error: error.message });
}
await new Promise(resolve => setTimeout(resolve, 100));
}
return results;
}
// Upload directory of files
async uploadDirectory(directoryPath, purpose = 'assistants') {
const files = fs.readdirSync(directoryPath);
const filePaths = files.map(file => path.join(directoryPath, file));
return await uploadMultipleFiles(filePaths, purpose);
}
// Get storage usage summary
async getStorageUsage() {
const files = await this.openai.files.list();
const summary = {
totalFiles: files.data.length,
totalBytes: files.data.reduce((sum, file) => sum + file.bytes, 0),
byPurpose: {}
};
// Group by purpose
files.data.forEach(file => {
if (!summary.byPurpose[file.purpose]) {
summary.byPurpose[file.purpose] = { count: 0, bytes: 0 };
}
summary.byPurpose[file.purpose].count++;
summary.byPurpose[file.purpose].bytes += file.bytes;
});
// Convert bytes to readable format
summary.totalSize = `${(summary.totalBytes / 1024 / 1024 / 1024).toFixed(2)} GB`;
Object.keys(summary.byPurpose).forEach(purpose => {
const purposeData = summary.byPurpose[purpose];
purposeData.size = `${(purposeData.bytes / 1024 / 1024).toFixed(2)} MB`;
});
return summary;
}
}
// Usage example
const fileManager = new OpenAIFileManager(process.env.OPENAI_API_KEY);
// Clean up old files
await fileManager.cleanupOldFiles(30);
// Get storage usage
const usage = await fileManager.getStorageUsage();
console.log('Storage Usage:', usage);
Best Practices
File Organization
// Use consistent naming conventions
const generateFileName = (type, date, description) => {
const timestamp = date.toISOString().split('T')[0];
return `${type}_${timestamp}_${description}`.replace(/[^a-zA-Z0-9_-]/g, '_');
};
// Example: "knowledge_base_2025-08-05_company_policies.pdf"
const filename = generateFileName('knowledge_base', new Date(), 'company policies');
Error Handling and Retry Logic
// Robust file operation with exponential backoff
async function robustFileOperation(operation, maxRetries = 3) {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await operation();
} catch (error) {
const isRetryable = error.message.includes('rate_limit') ||
error.message.includes('timeout') ||
error.status >= 500;
if (!isRetryable || attempt === maxRetries) {
throw error;
}
const delay = Math.pow(2, attempt) * 1000; // Exponential backoff
console.log(`Attempt ${attempt} failed, retrying in ${delay}ms`);
await new Promise(resolve => setTimeout(resolve, delay));
}
}
}
// Usage
const file = await robustFileOperation(() =>
openai.files.create({
file: fs.createReadStream('large-file.pdf'),
purpose: 'assistants'
})
);
Rate Limiting
// Rate limiter utility
class RateLimiter {
constructor(requestsPerSecond = 3) {
this.requestsPerSecond = requestsPerSecond;
this.lastRequestTime = 0;
}
async wait() {
const now = Date.now();
const timeSinceLastRequest = now - this.lastRequestTime;
const minimumInterval = 1000 / this.requestsPerSecond;
if (timeSinceLastRequest < minimumInterval) {
const waitTime = minimumInterval - timeSinceLastRequest;
await new Promise(resolve => setTimeout(resolve, waitTime));
}
this.lastRequestTime = Date.now();
}
}
// Use with bulk operations
const rateLimiter = new RateLimiter(3); // 3 requests per second
async function rateLimitedBulkDelete(fileIds) {
const results = [];
for (const fileId of fileIds) {
await rateLimiter.wait();
try {
const result = await openai.files.del(fileId);
results.push({ fileId, deleted: result.deleted });
} catch (error) {
results.push({ fileId, deleted: false, error: error.message });
}
}
return results;
}
Storage Management
// Monitor and manage storage limits
async function checkStorageLimits() {
const files = await openai.files.list();
const totalBytes = files.data.reduce((sum, file) => sum + file.bytes, 0);
const totalGB = totalBytes / (1024 * 1024 * 1024);
const warnings = [];
if (totalGB > 80) { // 80% of 100GB limit
warnings.push(`Storage usage: ${totalGB.toFixed(2)}GB / 100GB (${(totalGB).toFixed(1)}%)`);
}
// Check for unusually large files
const largeFiles = files.data.filter(file => file.bytes > 100 * 1024 * 1024); // > 100MB
if (largeFiles.length > 0) {
warnings.push(`${largeFiles.length} files larger than 100MB detected`);
}
// Check for old unused files
const oldFiles = files.data.filter(file => {
const fileAge = Date.now() - (file.created_at * 1000);
return fileAge > 90 * 24 * 60 * 60 * 1000; // > 90 days
});
if (oldFiles.length > 0) {
warnings.push(`${oldFiles.length} files older than 90 days could be cleaned up`);
}
return {
totalFiles: files.data.length,
totalGB: totalGB.toFixed(2),
percentUsed: ((totalGB / 100) * 100).toFixed(1),
warnings
};
}
Common Issues and Solutions
File Upload Failures
// Diagnose upload failures
async function diagnoseUploadFailure(filePath, purpose) {
const checks = [];
// Check file exists
if (!fs.existsSync(filePath)) {
checks.push({ check: 'File exists', status: 'FAIL', message: 'File not found' });
return checks;
}
checks.push({ check: 'File exists', status: 'PASS' });
// Check file size
const stats = fs.statSync(filePath);
const sizeMB = stats.size / (1024 * 1024);
if (sizeMB > 512) {
checks.push({ check: 'File size', status: 'FAIL', message: `${sizeMB.toFixed(2)}MB exceeds 512MB limit` });
} else {
checks.push({ check: 'File size', status: 'PASS', message: `${sizeMB.toFixed(2)}MB` });
}
// Check file type
const filename = path.basename(filePath);
const validation = validateFileForPurpose(filename, purpose);
if (!validation.valid) {
checks.push({ check: 'File type', status: 'FAIL', message: validation.error });
} else {
checks.push({ check: 'File type', status: 'PASS' });
}
// Check organization storage
const usage = await checkStorageLimits();
if (parseFloat(usage.totalGB) + sizeMB/1024 > 100) {
checks.push({ check: 'Storage capacity', status: 'FAIL', message: 'Would exceed 100GB limit' });
} else {
checks.push({ check: 'Storage capacity', status: 'PASS' });
}
return checks;
}
File Processing Issues
// Debug file processing problems
async function debugFileProcessing(fileId) {
try {
const file = await openai.files.retrieve(fileId);
const debug = {
fileId: file.id,
filename: file.filename,
purpose: file.purpose,
status: file.status,
size: `${(file.bytes / 1024 / 1024).toFixed(2)} MB`,
age: `${Math.floor((Date.now() - file.created_at * 1000) / (1000 * 60))} minutes`,
recommendations: []
};
// Status-specific recommendations
switch (file.status) {
case 'error':
debug.recommendations.push('File processing failed - check file format and content');
debug.recommendations.push('Try re-uploading the file');
break;
case 'uploaded':
const ageMinutes = Math.floor((Date.now() - file.created_at * 1000) / (1000 * 60));
if (ageMinutes > 10) {
debug.recommendations.push('File has been processing for over 10 minutes - may have failed');
} else {
debug.recommendations.push('File is still processing - wait a few more minutes');
}
break;
case 'processed':
debug.recommendations.push('File processed successfully and ready for use');
break;
}
// Size-based recommendations
if (file.bytes > 50 * 1024 * 1024) { // > 50MB
debug.recommendations.push('Large file may take longer to process');
}
return debug;
} catch (error) {
return { error: error.message };
}
}
Vector Store Issues
// Troubleshoot vector store problems
async function troubleshootVectorStore(vectorStoreId) {
try {
const vectorStore = await openai.beta.vectorStores.retrieve(vectorStoreId);
const files = await openai.beta.vectorStores.files.list(vectorStoreId);
const troubleshoot = {
vectorStoreId: vectorStore.id,
name: vectorStore.name,
status: vectorStore.status,
fileCount: vectorStore.file_counts.total,
issues: []
};
// Check vector store status
if (vectorStore.status === 'failed') {
troubleshoot.issues.push('Vector store processing failed');
}
// Check file processing status
const fileStatuses = {};
files.data.forEach(file => {
fileStatuses[file.status] = (fileStatuses[file.status] || 0) + 1;
});
if (fileStatuses.failed > 0) {
troubleshoot.issues.push(`${fileStatuses.failed} files failed to process`);
}
if (fileStatuses.in_progress > 0) {
troubleshoot.issues.push(`${fileStatuses.in_progress} files still processing`);
}
// Check for empty vector store
if (vectorStore.file_counts.total === 0) {
troubleshoot.issues.push('Vector store contains no files');
}
troubleshoot.fileStatuses = fileStatuses;
return troubleshoot;
} catch (error) {
return { error: error.message };
}
}
API Reference Examples
Complete File Management Script
#!/usr/bin/env node
import OpenAI from 'openai';
import fs from 'fs';
import path from 'path';
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
// Command line file management utility
class OpenAIFileCLI {
async list(purpose = null) {
const files = await openai.files.list();
let filteredFiles = files.data;
if (purpose) {
filteredFiles = files.data.filter(f => f.purpose === purpose);
}
console.table(filteredFiles.map(file => ({
ID: file.id,
Filename: file.filename,
Purpose: file.purpose,
Size: `${(file.bytes / 1024 / 1024).toFixed(2)} MB`,
Status: file.status,
Created: new Date(file.created_at * 1000).toLocaleDateString()
})));
console.log(`\nTotal: ${filteredFiles.length} files`);
}
async upload(filePath, purpose = 'assistants') {
console.log(`Uploading ${filePath} with purpose: ${purpose}`);
const file = await openai.files.create({
file: fs.createReadStream(filePath),
purpose: purpose
});
console.log(`✅ Uploaded: ${file.id} - ${file.filename}`);
return file;
}
async delete(fileId) {
const result = await openai.files.del(fileId);
console.log(`✅ Deleted: ${fileId}`);
return result;
}
async info(fileId) {
const file = await openai.files.retrieve(fileId);
console.log('File Information:');
console.log(` ID: ${file.id}`);
console.log(` Filename: ${file.filename}`);
console.log(` Purpose: ${file.purpose}`);
console.log(` Size: ${(file.bytes / 1024 / 1024).toFixed(2)} MB`);
console.log(` Status: ${file.status}`);
console.log(` Created: ${new Date(file.created_at * 1000)}`);
}
async cleanup(olderThanDays = 30) {
console.log(`Cleaning up files older than ${olderThanDays} days...`);
const files = await openai.files.list();
const cutoffDate = new Date();
cutoffDate.setDate(cutoffDate.getDate() - olderThanDays);
const oldFiles = files.data.filter(file => {
const fileDate = new Date(file.created_at * 1000);
return fileDate < cutoffDate;
});
console.log(`Found ${oldFiles.length} files to delete`);
for (const file of oldFiles) {
try {
await this.delete(file.id);
} catch (error) {
console.error(`Failed to delete ${file.id}: ${error.message}`);
}
}
}
}
// CLI usage
const cli = new OpenAIFileCLI();
const command = process.argv[2];
switch (command) {
case 'list':
await cli.list(process.argv[3]);
break;
case 'upload':
await cli.upload(process.argv[3], process.argv[4]);
break;
case 'delete':
await cli.delete(process.argv[3]);
break;
case 'info':
await cli.info(process.argv[3]);
break;
case 'cleanup':
await cli.cleanup(parseInt(process.argv[3]) || 30);
break;
default:
console.log('Usage: node file-manager.js <command> [args]');
console.log('Commands:');
console.log(' list [purpose] - List files');
console.log(' upload <file> [purpose] - Upload file');
console.log(' delete <fileId> - Delete file');
console.log(' info <fileId> - Show file info');
console.log(' cleanup [days] - Delete files older than N days');
}
File Management Tools
While the OpenAI Files API is powerful, managing files through code can be tedious, especially for bulk operations. The API lacks:
- Visual file browser for easy navigation
- Bulk selection and deletion capabilities
- File usage tracking across assistants and vector stores
- Secure API key management for quick operations
The Solution: AI Files App
For developers who need a visual interface for OpenAI file management, we've built AI Files - a free macOS application that provides:
- Bulk file operations - Upload, delete, and manage multiple files at once
- Vector Store management - Visual interface for vector store file operations
- Secure API key storage - Keys stored safely in macOS Keychain
- File usage insights - See which assistants and vector stores use your files
- Drag-and-drop uploads - Simple file management interface
The app solves the bulk operations problem highlighted throughout this guide, providing the visual file management interface that the OpenAI platform currently lacks.
When to Use the API vs. Visual Tools
Use the OpenAI Files API directly when:
- Integrating file operations into your application
- Automating file uploads as part of a workflow
- Building custom file management logic
- Processing files programmatically
Use visual tools like AI Files when:
- Managing files during development and testing
- Performing bulk cleanup operations
- Exploring and organizing your file collection
- Quick ad-hoc file management tasks
Conclusion
The OpenAI Files API is a powerful tool for managing files across OpenAI's platform, but it requires careful planning and implementation to use effectively. Key takeaways:
- Understand file purposes - Different purposes have different limitations and capabilities
- Implement proper error handling - File operations can fail for various reasons
- Use bulk operations carefully - Rate limiting and sequential processing are important
- Monitor storage usage - Stay within the 100GB organization limit
- Consider visual tools - For bulk operations and file exploration, GUI tools can save significant time
Whether you're building automated workflows with the API or managing files visually, understanding these concepts will help you work more effectively with OpenAI's file system.
For complex file management needs, combining programmatic API usage with visual tools like AI Files provides the best of both worlds - automation where needed and visual control for bulk operations.
Need help with OpenAI Files API integration? Contact our team for guidance on implementing robust file management in your applications.