File Storage
PUGUH provides S3-compatible file storage with organization-level isolation, automatic virus scanning, and CDN delivery.
Overview
The storage service handles:
- File uploads with size limits per plan
- Organization isolation — files are scoped to the uploading organization
- Image processing — automatic thumbnail and variant generation
- Presigned URLs for secure, time-limited downloads
- Visibility control — public or private per file
Uploading Files
Via API
bash
curl -X POST https://api-puguh.arsaka.io/storage/upload \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "X-Organization-ID: YOUR_ORG_ID" \
-F "file=@logo.png" \
-F "visibility=public" Response:
json
{
"id": "file_abc123",
"filename": "logo.png",
"content_type": "image/png",
"size_bytes": 45200,
"visibility": "public",
"url": "https://cdn.arsaka.io/org_xxx/logo.png",
"variants": {
"thumbnail": "https://cdn.arsaka.io/org_xxx/logo_thumb.png",
"medium": "https://cdn.arsaka.io/org_xxx/logo_medium.png"
},
"created_at": "2026-02-20T10:00:00Z"
} Via SDK (TypeScript)
typescript
import { PuguhClient } from '@arsaka/puguh-sdk';
const client = new PuguhClient({ apiKey: 'YOUR_KEY' });
// Upload a file
const file = await client.storage.upload(fileBlob, {
visibility: 'public',
organizationId: 'org_abc'
});
console.log(file.url); // Public CDN URL
console.log(file.variants); // { thumbnail, medium } Via SDK (Python)
python
from puguh_sdk import PuguhClient
client = PuguhClient(api_key="YOUR_KEY")
with open("logo.png", "rb") as f:
file = client.storage.upload(f, visibility="public")
print(file.url)
print(file.variants) File Visibility
| Visibility | Access | URL Type |
|---|---|---|
public | Anyone with the URL | Permanent CDN URL |
private | Authenticated users only | Presigned URL (expires) |
Changing Visibility
bash
curl -X PATCH https://api-puguh.arsaka.io/storage/file_abc123/visibility \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{"visibility": "private"}' Presigned URLs
Generate time-limited download URLs for private files:
bash
curl -X POST https://api-puguh.arsaka.io/storage/file_abc123/presign \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{"expires_in": 3600}' Response:
json
{
"url": "https://cdn.arsaka.io/org_xxx/file_abc123?token=xxx&expires=1708430400",
"expires_at": "2026-02-20T11:00:00Z"
} Image Variants
When you upload an image (PNG, JPG, WebP), PUGUH automatically generates variants:
| Variant | Max Size | Format |
|---|---|---|
thumbnail | 150x150 | WebP |
medium | 600x600 | WebP |
original | As uploaded | Original |
Listing Files
bash
curl https://api-puguh.arsaka.io/storage?page=1&page_size=20 \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "X-Organization-ID: YOUR_ORG_ID" Response:
json
{
"items": [
{
"id": "file_abc123",
"filename": "logo.png",
"content_type": "image/png",
"size_bytes": 45200,
"visibility": "public",
"created_at": "2026-02-20T10:00:00Z"
}
],
"total": 42,
"page": 1,
"page_size": 20,
"has_next": true,
"has_prev": false
} Deleting Files
bash
curl -X DELETE https://api-puguh.arsaka.io/storage/file_abc123 \
-H "Authorization: Bearer YOUR_TOKEN" Deleted files are soft-deleted and can be recovered within 30 days.
Storage Usage
bash
curl https://api-puguh.arsaka.io/storage/usage \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "X-Organization-ID: YOUR_ORG_ID" Response:
json
{
"used_bytes": 524288000,
"quota_bytes": 5368709120,
"file_count": 156,
"usage_percent": 9.8
} Limits by Plan
| Plan | Storage | Max File Size | Bandwidth |
|---|---|---|---|
| Free | 1 GB | 10 MB | 5 GB/month |
| Pro | 10 GB | 100 MB | 50 GB/month |
| Business | 100 GB | 500 MB | 500 GB/month |
| Enterprise | Custom | Custom | Custom |
Allowed File Types
By default, PUGUH allows common file types. Organization admins can customize allowed types via policies.
| Category | Extensions |
|---|---|
| Images | .png, .jpg, .jpeg, .gif, .webp, .svg |
| Documents | .pdf, .doc, .docx, .xls, .xlsx, .csv |
| Archives | .zip, .tar.gz |
| Other | .json, .xml, .txt |
Best Practices
- Use presigned URLs for private files instead of proxying through your server
- Set appropriate visibility at upload time (public for logos/assets, private for user documents)
- Use image variants instead of serving full-size originals for thumbnails
- Monitor storage usage to avoid hitting plan limits
- Clean up unused files periodically