Filestore
The Filestore API provides comprehensive file management capabilities including secure file uploads, metadata management, permission control, and automated image processing. This RESTful API handles the complete file lifecycle from upload to deletion with built-in security and optimization features.
Operations Overview
Operation | Description |
---|---|
file.info | Retrieve file information and generate access URLs |
file.update | Update file permissions and metadata |
file.delete | Delete files from storage |
file.presign_upload | Generate presigned URLs for secure file uploads |
file.postsign_upload | Complete file upload process and finalize storage |
file.upload_error | Report upload errors and handle failed uploads |
1. Get File Information
file.info
Retrieve detailed file information including download URLs, metadata, and access permissions.
Request Body
{
"op": "file.info",
"_key": "file_abc123xyz789",
"signed_ttl": 3600
}
Parameters
- op (string, required): Must be
"file.info"
- _key (string, required): Unique file identifier
- signed_ttl (integer, optional): Temporary access duration in seconds for private files (max: 604800 = 7 days)
Response
{
"data": {
"_key": "file_abc123xyz789",
"url": "https://storage.example.com/files/document.pdf?signature=xyz",
"filename": "quarterly-report.pdf",
"filesize": "2048576",
"fileclass": "document",
"object_key": "uploads/2024/01/quarterly-report.pdf",
"info": {
"uploaded_by": "user_123",
"upload_date": "2024-01-15T10:30:00Z",
"last_modified": "2024-01-15T10:30:00Z"
},
"acl": "private",
"content_type": "application/pdf",
"image_variants": {}
}
}
Response Fields
- _key: Unique file identifier
- url: Direct access URL (signed for private files)
- filename: Original filename
- filesize: File size in bytes
- fileclass: File category (image, document, video, etc.)
- object_key: Storage path identifier
- info: Additional metadata object
- acl: Access control level (
"public"
or"private"
) - content_type: MIME type
- image_variants: Available image sizes/formats (for images only)
Example Use Cases
Get public file info:
{
"op": "file.info",
"_key": "file_public123"
}
Get private file with temporary access:
{
"op": "file.info",
"_key": "file_private456",
"signed_ttl": 1800
}
Get image with variants:
{
"op": "file.info",
"_key": "image_789"
}
Response for image with variants:
{
"data": {
"_key": "image_789",
"url": "https://storage.example.com/images/photo.jpg",
"filename": "profile-photo.jpg",
"fileclass": "image",
"content_type": "image/jpeg",
"image_variants": {
"thumbnail": "https://storage.example.com/images/photo_thumb.jpg",
"medium": "https://storage.example.com/images/photo_medium.jpg",
"large": "https://storage.example.com/images/photo_large.jpg"
}
}
}
2. Update File
file.update
Update file permissions, metadata, and access control settings.
Request Body
{
"op": "file.update",
"_key": "file_abc123xyz789",
"public_read": true,
"metadata": {
"description": "Updated quarterly financial report",
"category": "finance",
"tags": ["Q1", "2024", "revenue"],
"department": "Finance",
"confidentiality": "internal"
}
}
Parameters
- op (string, required): Must be
"file.update"
- _key (string, required): File identifier to update
- public_read (boolean, optional): Set file visibility (
true
= public,false
= private) - metadata (object, optional): Custom metadata to associate with the file
Response
{
"data": {
"_key": "file_abc123xyz789",
"change": "updated"
}
}
Example Use Cases
Make file public:
{
"op": "file.update",
"_key": "file_abc123",
"public_read": true
}
Add metadata only:
{
"op": "file.update",
"_key": "file_xyz789",
"metadata": {
"project": "Website Redesign",
"version": "2.1",
"approved_by": "design_team"
}
}
Update privacy and metadata:
{
"op": "file.update",
"_key": "file_confidential456",
"public_read": false,
"metadata": {
"classification": "confidential",
"retention_policy": "7_years",
"access_level": "management_only"
}
}
3. Delete File
file.delete
Permanently delete files from storage.
Request Body
{
"op": "file.delete",
"_key": "file_abc123xyz789"
}
Parameters
- op (string, required): Must be
"file.delete"
- _key (string, required): File identifier to delete
Response
{
"data": {
"_key": "file_abc123xyz789",
"change": "deleted"
}
}
Example Use Cases
Delete temporary file:
{
"op": "file.delete",
"_key": "temp_file_123"
}
Bulk deletion workflow:
const filesToDelete = ["file_1", "file_2", "file_3"];
for (const fileKey of filesToDelete) {
await fetch('file.delete', {
method: 'POST',
headers: {
'X-API-KEY': 'your-api-key',
'Authorization': 'Bearer your-token'
},
body: JSON.stringify({
op: 'file.delete',
_key: fileKey
})
});
}
4. Presign Upload
file.presign_upload
Generate secure presigned URLs and validate file uploads before they occur.
Request Body
{
"op": "file.presign_upload",
"filename": "presentation.pptx",
"content_type": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
"metadata": {
"project": "Q1 Review",
"created_by": "user_123",
"department": "Marketing"
},
"public_read": false,
"new_name": "q1-marketing-presentation.pptx",
"options": {
"profilephoto": false,
"variants": []
}
}
Request Body for Image Upload
{
"op": "file.presign_upload",
"filename": "profile.jpg",
"content_type": "image/jpeg",
"metadata": {
"user_id": "user_456",
"upload_context": "profile_update"
},
"public_read": true,
"options": {
"profilephoto": true,
"variants": ["thumbnail", "medium", "large"]
}
}
Parameters
- op (string, required): Must be
"file.presign_upload"
- filename (string, required): Original filename with extension
- content_type (string, required): MIME type of the file
- metadata (object, optional): Custom metadata to store with file
- public_read (boolean, optional): File visibility setting
- new_name (string, optional): Custom filename for storage
- options (object, optional): Upload options
- profilephoto (boolean): Mark as profile photo
- variants (array): Image size variants to generate
Response
{
"data": {
"info": {
"_key": "file_new123abc",
"url": null,
"filename": "q1-marketing-presentation.pptx",
"filesize": null,
"fileclass": "document",
"object_key": "uploads/2024/01/q1-marketing-presentation.pptx",
"info": {
"project": "Q1 Review",
"created_by": "user_123",
"department": "Marketing"
},
"acl": "private",
"content_type": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
"image_variants": {}
},
"presigned_data": {
"url": "https://storage.amazonaws.com/bucket",
"fields": {
"key": "uploads/2024/01/q1-marketing-presentation.pptx",
"AWSAccessKeyId": "AKIAIOSFODNN7EXAMPLE",
"policy": "eyJleHBpcmF0aW9uIjoi...",
"signature": "signature-hash",
"x-amz-security-token": "token"
}
}
}
}
Upload Process
- Call
file.presign_upload
to get upload credentials - Use the presigned data to upload directly to storage
- Call
file.postsign_upload
to finalize the upload
Example Upload Implementation
// Step 1: Get presigned upload data
const presignResponse = await fetch('file.presign_upload', {
method: 'POST',
headers: {
'X-API-KEY': 'your-api-key',
'Authorization': 'Bearer your-token',
'Content-Type': 'application/json'
},
body: JSON.stringify({
op: 'file.presign_upload',
filename: 'document.pdf',
content_type: 'application/pdf',
public_read: true
})
});
const { info, presigned_data } = presignResponse.data;
// Step 2: Upload file using presigned data
const formData = new FormData();
Object.entries(presigned_data.fields).forEach(([key, value]) => {
formData.append(key, value);
});
formData.append('file', fileBlob);
await fetch(presigned_data.url, {
method: 'POST',
body: formData
});
// Step 3: Finalize upload
await fetch('file.postsign_upload', {
method: 'POST',
headers: {
'X-API-KEY': 'your-api-key',
'Authorization': 'Bearer your-token',
'Content-Type': 'application/json'
},
body: JSON.stringify({
op: 'file.postsign_upload',
_key: info._key,
presigned_data: presigned_data
})
});
5. Postsign Upload
file.postsign_upload
Complete the file upload process and finalize file storage.
Request Body
{
"op": "file.postsign_upload",
"_key": "file_new123abc",
"presigned_data": {
"url": "https://storage.amazonaws.com/bucket",
"fields": {
"key": "uploads/2024/01/q1-marketing-presentation.pptx",
"AWSAccessKeyId": "AKIAIOSFODNN7EXAMPLE",
"policy": "eyJleHBpcmF0aW9uIjoi...",
"signature": "signature-hash"
}
}
}
Parameters
- op (string, required): Must be
"file.postsign_upload"
- _key (string, required): File key from presign response
- presigned_data (object, required): Presigned data from presign response
Response
{
"data": {
"_key": "file_new123abc",
"url": "https://storage.example.com/uploads/2024/01/q1-marketing-presentation.pptx",
"filename": "q1-marketing-presentation.pptx",
"filesize": "5242880",
"fileclass": "document",
"object_key": "uploads/2024/01/q1-marketing-presentation.pptx",
"info": {
"project": "Q1 Review",
"created_by": "user_123",
"department": "Marketing",
"upload_completed": "2024-01-15T10:35:00Z"
},
"acl": "private",
"content_type": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
"image_variants": {}
}
}
After successful postsign, the file is fully processed and available for use.
6. Upload Error
file.upload_error
Report upload errors and handle failed upload attempts.
Request Body
{
"op": "file.upload_error",
"_key": "file_failed123",
"presigned_data": {
"url": "https://storage.amazonaws.com/bucket",
"fields": {
"key": "uploads/2024/01/failed-upload.pdf"
}
},
"errors": {
"error_code": "NETWORK_TIMEOUT",
"message": "Upload failed due to network timeout",
"retry_count": 3,
"last_attempt": "2024-01-15T10:40:00Z"
}
}
Parameters
- op (string, required): Must be
"file.upload_error"
- _key (string, required): File key from failed upload
- presigned_data (object, required): Original presigned data
- errors (object/string, required): Error details
Response
{
"data": {
"_key": "file_failed123",
"change": "error"
}
}
Error Types
{
"errors": {
"error_code": "FILE_TOO_LARGE",
"message": "File exceeds maximum size limit of 100MB",
"file_size": 104857600,
"max_size": 104857600
}
}
{
"errors": {
"error_code": "INVALID_FORMAT",
"message": "File format not supported",
"detected_type": "application/octet-stream",
"expected_types": ["image/jpeg", "image/png", "image/gif"]
}
}
File Upload Workflow
Complete Upload Process
async function uploadFile(file, options = {}) {
try {
// Step 1: Presign upload
const presignResponse = await fetch('file.presign_upload', {
method: 'POST',
headers: {
'X-API-KEY': 'your-api-key',
'Authorization': 'Bearer your-token',
'Content-Type': 'application/json'
},
body: JSON.stringify({
op: 'file.presign_upload',
filename: file.name,
content_type: file.type,
public_read: options.public || false,
metadata: options.metadata || {},
options: options.uploadOptions || {}
})
});
if (!presignResponse.ok) {
throw new Error('Presign failed');
}
const { info, presigned_data } = presignResponse.data;
// Step 2: Upload to storage
const formData = new FormData();
Object.entries(presigned_data.fields).forEach(([key, value]) => {
formData.append(key, value);
});
formData.append('file', file);
const uploadResponse = await fetch(presigned_data.url, {
method: 'POST',
body: formData
});
if (!uploadResponse.ok) {
// Report upload error
await fetch('file.upload_error', {
method: 'POST',
headers: {
'X-API-KEY': 'your-api-key',
'Authorization': 'Bearer your-token',
'Content-Type': 'application/json'
},
body: JSON.stringify({
op: 'file.upload_error',
_key: info._key,
presigned_data: presigned_data,
errors: {
error_code: 'UPLOAD_FAILED',
message: `Upload failed with status ${uploadResponse.status}`,
http_status: uploadResponse.status
}
})
});
throw new Error('Upload failed');
}
// Step 3: Finalize upload
const finalizeResponse = await fetch('file.postsign_upload', {
method: 'POST',
headers: {
'X-API-KEY': 'your-api-key',
'Authorization': 'Bearer your-token',
'Content-Type': 'application/json'
},
body: JSON.stringify({
op: 'file.postsign_upload',
_key: info._key,
presigned_data: presigned_data
})
});
if (!finalizeResponse.ok) {
throw new Error('Finalization failed');
}
return finalizeResponse.data;
} catch (error) {
console.error('Upload failed:', error);
throw error;
}
}
// Usage
const fileInput = document.getElementById('file-input');
const file = fileInput.files[0];
uploadFile(file, {
public: true,
metadata: {
category: 'user-content',
uploaded_by: 'user_123'
},
uploadOptions: {
variants: ['thumbnail', 'medium']
}
}).then(result => {
console.log('Upload successful:', result);
}).catch(error => {
console.error('Upload failed:', error);
});
Image Processing
Automatic Variants
When uploading images, you can request automatic generation of different sizes:
{
"op": "file.presign_upload",
"filename": "hero-image.jpg",
"content_type": "image/jpeg",
"public_read": true,
"options": {
"variants": ["thumbnail", "small", "medium", "large", "xlarge"]
}
}
Variant Specifications
Variant | Max Width | Max Height | Quality |
---|---|---|---|
thumbnail | 150px | 150px | 80% |
small | 300px | 300px | 85% |
medium | 600px | 600px | 90% |
large | 1200px | 1200px | 95% |
xlarge | 2400px | 2400px | 95% |
Profile Photo Optimization
{
"op": "file.presign_upload",
"filename": "avatar.jpg",
"content_type": "image/jpeg",
"public_read": true,
"options": {
"profilephoto": true,
"variants": ["thumbnail", "medium"]
}
}
Profile photos receive additional processing:
- Square cropping from center
- Face detection and centering (if available)
- Optimized compression for web display
File Management Patterns
Organized Upload Structure
// Organize files by date and category
const uploadOptions = {
metadata: {
category: 'documents',
subcategory: 'contracts',
date: new Date().toISOString().split('T')[0],
user_id: currentUser.id,
department: currentUser.department
},
public_read: false
};
Batch Operations
// Process multiple files
async function batchUpload(files, commonMetadata = {}) {
const results = [];
for (const file of files) {
try {
const result = await uploadFile(file, {
metadata: {
...commonMetadata,
original_name: file.name,
file_index: results.length
}
});
results.push(result);
} catch (error) {
console.error(`Failed to upload ${file.name}:`, error);
results.push({ error: error.message, filename: file.name });
}
}
return results;
}
File Cleanup
// Clean up temporary files older than 24 hours
async function cleanupTempFiles(tempFileKeys) {
const oneDayAgo = Date.now() - (24 * 60 * 60 * 1000);
for (const fileKey of tempFileKeys) {
try {
const info = await getFileInfo(fileKey);
const uploadTime = new Date(info.data.info.upload_date).getTime();
if (uploadTime < oneDayAgo) {
await deleteFile(fileKey);
console.log(`Cleaned up temp file: ${fileKey}`);
}
} catch (error) {
console.error(`Failed to cleanup ${fileKey}:`, error);
}
}
}
Error Responses
All endpoints may return errors with this structure:
{
"error": {
"code": "FILE_NOT_FOUND",
"message": "The specified file does not exist",
"details": {
"_key": "file_nonexistent123",
"operation": "file.info"
}
}
}
Common Error Codes
FILE_NOT_FOUND
: Specified file key doesn't existACCESS_DENIED
: Insufficient permissions for file operationFILE_TOO_LARGE
: File exceeds size limitsINVALID_FILE_TYPE
: File type not supportedUPLOAD_EXPIRED
: Presigned URL has expiredMETADATA_TOO_LARGE
: Metadata object exceeds size limitQUOTA_EXCEEDED
: Storage quota limit reachedPROCESSING_FAILED
: Image processing failedNETWORK_ERROR
: Upload network failure
Security and Best Practices
1. Access Control
- Use private files for sensitive content
- Implement signed URLs with appropriate TTL for temporary access
- Regularly audit file permissions
- Use metadata to track file ownership and access requirements
2. Upload Security
- Validate file types on the client and server
- Implement file size limits appropriate to your use case
- Use virus scanning for user-uploaded content
- Monitor upload patterns for abuse detection
3. Storage Optimization
- Use image variants to optimize delivery
- Implement automatic cleanup for temporary files
- Compress large files before upload when possible
- Use appropriate metadata for content organization
4. Performance
- Upload large files in chunks when possible
- Use CDN for public file delivery
- Implement client-side retry logic for failed uploads
- Cache file information for frequently accessed files
File Size Limits
File Type | Maximum Size | Recommended Size |
---|---|---|
Images | 50 MB | < 10 MB |
Documents | 100 MB | < 25 MB |
Videos | 500 MB | < 100 MB |
Audio | 100 MB | < 25 MB |
Archives | 200 MB | < 50 MB |