API Documentation
Media Storage is a powerful tool to upload files, store them securely, or reference external URLs. You need API keys to use it.
Getting Started
Please ask your admin for API keys. They will generate them for you.
Note: Only admins can make keys. You will get two keys:
- Client Key (ck_...): Public ID
- API Key (sk_...): Secret Password (keep it safe!)
Authentication
You must send these two headers with every request:
| Header Name | x-client-key |
| Value Format | ck_[timestamp]_[random] |
| Example | ck_1234567890_abcd1234 |
| Header Name | x-api-key |
| Value Format | sk_[timestamp]_[random] |
| Example | sk_1234567890_xyz56789 |
Header Example
x-client-key: ck_1234567890_abcd1234
x-api-key: sk_1234567890_xyz56789
Upload Media
Upload media files directly or reference external URLs. Both methods use the same endpoint.
Endpoint Details
| Method | POST |
| URL | /api/v1/upload |
| Content-Type | multipart/form-data |
Request Headers
| Header | Required | Description |
|---|---|---|
| x-client-key | Yes | Your Client Key |
| x-api-key | Yes | Your Secret API Key |
Request Body (Form Data)
You can upload files in two ways: by uploading a file OR by providing an external URL.
Option 1: Upload File
| Field | Type | Required | Description |
|---|---|---|---|
| file | File | Yes | Select a media file (image, video, PDF, etc.) |
| folder | String | Optional | Subfolder name |
Option 2: External URL
Auto-Detection: If originalName or mimeType are not provided, they will be automatically detected from the URL.
| Field | Type | Required | Description |
|---|---|---|---|
| external-url | String | Yes | Full URL of the external media |
| originalName | String | Optional | Custom filename |
| mimeType | String | Optional | MIME type (e.g., image/jpeg) |
| notes | String | Optional | Additional notes |
Upload to Subfolder (Optional)
You can organize files into subfolders by adding a folder parameter:
| Via Query | ?folder=subfolder_name |
| Via Header | x-upload-folder: subfolder_name |
| Via Form Field | folder=subfolder_name |
💡 Folder Usage: If you give a folder name, the file saves in /uploads/resourceId/folder_name/. Otherwise, it saves in /uploads/resourceId/.
🌐 External URL: When using external URL, the media is not stored on our server. Instead, we save the URL reference in the database.
Code Examples
📁 File Upload Examples
cURL (Without Folder)
curl -X POST http://localhost:3000/api/v1/upload \
-H "x-client-key: ck_1234567890_abcd1234" \
-H "x-api-key: sk_1234567890_xyz56789" \
-F "file=@/path/to/image.jpg"
cURL (With Folder)
curl -X POST http://localhost:3000/api/v1/upload \
-H "x-client-key: ck_1234567890_abcd1234" \
-H "x-api-key: sk_1234567890_xyz56789" \
-F "file=@/path/to/image.jpg" \
-F "folder=products"
JavaScript (Fetch API)
const formData = new FormData();
formData.append('file', fileInput.files[0]);
formData.append('folder', 'products'); // optional
fetch('http://localhost:3000/api/v1/upload', {
method: 'POST',
headers: {
'x-client-key': 'ck_1234567890_abcd1234',
'x-api-key': 'sk_1234567890_xyz56789'
},
body: formData
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
🌐 External URL Examples
When using external URLs, originalName and mimeType are optional. If not provided, they will be auto-detected from the URL and file extension.
cURL (Basic - Auto-Detection)
The system will extract the filename and detect the MIME type automatically:
curl -X POST http://localhost:3000/api/v1/upload \
-H "x-client-key: ck_1234567890_abcd1234" \
-H "x-api-key: sk_1234567890_xyz56789" \
-F "external-url=https://example.com/image.jpg"
cURL (With Options)
curl -X POST http://localhost:3000/api/v1/upload \
-H "x-client-key: ck_1234567890_abcd1234" \
-H "x-api-key: sk_1234567890_xyz56789" \
-F "external-url=https://example.com/paris.jpg" \
-F "originalName=paris.jpg" \
-F "mimeType=image/jpeg" \
-F "notes=Restaurant banner image"
JavaScript (External URL)
const formData = new FormData();
formData.append('external-url', 'https://example.com/image.jpg');
formData.append('originalName', 'banner.jpg'); // optional
formData.append('mimeType', 'image/jpeg'); // optional
formData.append('notes', 'Homepage banner'); // optional
fetch('http://localhost:3000/api/v1/upload', {
method: 'POST',
headers: {
'x-client-key': 'ck_1234567890_abcd1234',
'x-api-key': 'sk_1234567890_xyz56789'
},
body: formData
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
Response Format
File Upload Response
Success response for file upload:
{
"success": true,
"message": "File uploaded successfully",
"data": {
"id": "65c9f4c8a1b23f0012345678",
"originalName": "profile.png",
"mimeType": "image/png",
"path": "uploads/resourceId/65c9f4c8a1b23f0012345678.png",
"url": "http://localhost:3000/uploads/resourceId/65c9f4c8a1b23f0012345678.png",
"size": 245678,
"provider": "FS",
"createdAt": "2026-02-19T08:12:00.000Z"
}
}
External URL Response
Success response for external URL:
{
"success": true,
"message": "External URL media created successfully",
"data": {
"id": "65c9f56ba1b23f0012349999",
"originalName": "paris.jpg",
"mimeType": "image/jpeg",
"url": "https://example.com/paris.jpg",
"provider": "EXTERNAL_URL",
"createdAt": "2026-02-19T09:00:00.000Z"
}
}
Error Codes
| Code | Message | Description |
|---|---|---|
| 400 | Bad Request | Bad request or no file sent |
| 401 | Unauthorized | Wrong or missing API keys |
| 403 | Forbidden | Account is banned/suspended |
| 413 | Payload Too Large | File is too big |
| 500 | Internal Server Error | Server problem |
Account Status
Your account status:
- Active: You can upload files.
- Suspended: You cannot upload files.
If suspended, contact admin to fix it.