Storage API
Upload and manage files.
Base URL
https://api.moontraze.comUpload File
POST /api/storage/:projectId/upload
Authorization: Bearer <token>
Content-Type: multipart/form-data
file: <binary>
folderId: <optional>
customPath: <optional>Fields
| Field | Type | Required | Description |
|---|---|---|---|
file | binary | Yes | File to upload |
folderId | string | No | Upload into this folder (folder-based) |
customPath | string | No | Upload to this exact path (path-based) |
Priority: customPath > folderId > root level
customPath example: users/{uid}/profile/avatar.jpg
Example — Folder-based
curl -X POST https://api.moontraze.com/api/storage/PROJECT_ID/upload \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "X-Project-Id: PROJECT_ID" \
-H "X-API-Key: YOUR_API_KEY" \
-F "file=@photo.jpg" \
-F "folderId=folder_abc"Result: projects/{projectId}/{folderName}/{uuid}.jpg
Example — Path-based (customPath)
curl -X POST https://api.moontraze.com/api/storage/PROJECT_ID/upload \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "X-Project-Id: PROJECT_ID" \
-H "X-API-Key: YOUR_API_KEY" \
-F "file=@avatar.jpg" \
-F "customPath=users/uid_123/profile/avatar.jpg"Result: projects/{projectId}/users/uid_123/profile/avatar.jpg
Response
{
"id": "file_abc123",
"name": "avatar.jpg",
"path": "/PROJECT_ID/users/uid_123/profile/avatar.jpg",
"url": "/PROJECT_ID/users/uid_123/profile/avatar.jpg",
"publicUrl": "https://api.moontraze.com/storage/PROJECT_ID/users/uid_123/profile/avatar.jpg",
"size": 45230,
"mimeType": "image/jpeg",
"folderId": null,
"customPath": "users/uid_123/profile/avatar.jpg",
"downloadUrl": "https://api.moontraze.com/storage/PROJECT_ID/users/uid_123/profile/avatar.jpg?download=true",
"previewUrl": "https://api.moontraze.com/storage/PROJECT_ID/users/uid_123/profile/avatar.jpg?preview=true",
"folderPath": "root",
"quota": {
"usedBytes": 45230,
"limitBytes": 5368709120,
"remainingBytes": 5368663890
}
}Safety
customPathis sanitized — path traversal (../), backslashes, and special characters are removed- Max length: 500 characters
- Leading/trailing slashes are stripped automatically
{projectId}is prepended automatically — do not include it incustomPath
List Files
GET /api/storage/:projectId/files
Authorization: Bearer <token>
X-Project-Id: YOUR_PROJECT_ID
X-API-Key: YOUR_API_KEYList Files in Folder
GET /api/storage/:projectId/files?folderId=FOLDER_ID
Authorization: Bearer <token>
X-Project-Id: YOUR_PROJECT_ID
X-API-Key: YOUR_API_KEYGet Presigned URL
GET /api/storage/:projectId/files/:fileId/presign?download=true
Authorization: Bearer <token>
X-Project-Id: YOUR_PROJECT_ID
X-API-Key: YOUR_API_KEYPresigned URLs work the same for folderId and customPath uploads — both are stored in the same table and served identically.
Delete File
DELETE /api/storage/:projectId/files/:fileId
Authorization: Bearer <token>
X-Project-Id: YOUR_PROJECT_ID
X-API-Key: YOUR_API_KEYCreate Folder
POST /api/storage/:projectId/folders
Authorization: Bearer <token>
Content-Type: application/json
X-Project-Id: YOUR_PROJECT_ID
X-API-Key: YOUR_API_KEY
{
"name": "My Folder",
"parentId": null
}List Folders
GET /api/storage/:projectId/folders
Authorization: Bearer <token>
X-Project-Id: YOUR_PROJECT_ID
X-API-Key: YOUR_API_KEYDelete Folder
DELETE /api/storage/:projectId/folders/:folderId
Authorization: Bearer <token>
X-Project-Id: YOUR_PROJECT_ID
X-API-Key: YOUR_API_KEYGet Storage Quota
GET /api/storage/:projectId/quota
Authorization: Bearer <token>
X-Project-Id: YOUR_PROJECT_ID
X-API-Key: YOUR_API_KEYPublic File URL
https://api.moontraze.com/storage/:projectId/path/to/file.webp
https://api.moontraze.com/storage/:projectId/path/to/file.webp?download=trueCustom paths work the same — the URL reflects the stored path:
https://api.moontraze.com/storage/PROJECT_ID/users/uid_123/profile/avatar.jpgSDK Example
const file = document.getElementById('file').files[0];
// Folder-based
const result = await moon.storage.upload(file, {
folderId: 'folder_abc',
});
console.log(result.publicUrl);
// Path-based (custom path)
const avatar = await moon.storage.upload(file, {
customPath: `users/${uid}/profile/avatar.jpg`,
});
console.log(avatar.publicUrl);
const files = await moon.storage.list();
const folders = await moon.storage.listFolders();
await moon.storage.createFolder('My Folder');
const url = await moon.storage.getDownloadUrl(fileId);
await moon.storage.delete(fileId);
await moon.storage.deleteFolder(folderId);
const quota = await moon.storage.getQuota();