Skip to main content

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

OperationDescription
file.infoRetrieve file information and generate access URLs
file.updateUpdate file permissions and metadata
file.deleteDelete files from storage
file.presign_uploadGenerate presigned URLs for secure file uploads
file.postsign_uploadComplete file upload process and finalize storage
file.upload_errorReport 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

  1. Call file.presign_upload to get upload credentials
  2. Use the presigned data to upload directly to storage
  3. 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

VariantMax WidthMax HeightQuality
thumbnail150px150px80%
small300px300px85%
medium600px600px90%
large1200px1200px95%
xlarge2400px2400px95%

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 exist
  • ACCESS_DENIED: Insufficient permissions for file operation
  • FILE_TOO_LARGE: File exceeds size limits
  • INVALID_FILE_TYPE: File type not supported
  • UPLOAD_EXPIRED: Presigned URL has expired
  • METADATA_TOO_LARGE: Metadata object exceeds size limit
  • QUOTA_EXCEEDED: Storage quota limit reached
  • PROCESSING_FAILED: Image processing failed
  • NETWORK_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 TypeMaximum SizeRecommended Size
Images50 MB< 10 MB
Documents100 MB< 25 MB
Videos500 MB< 100 MB
Audio100 MB< 25 MB
Archives200 MB< 50 MB