Upload Files
API reference for uploading files via direct upload, signed URLs, or external URL registration.
PlatformXe supports three upload methods depending on your architecture: direct server-side upload, signed URLs for client-side upload, and external URL registration.
Direct upload
Upload a file directly from your server to PlatformXe.
POST /api/v1/storage/media/upload
Scope: storage:upload
Content-Type: multipart/form-data
Request body
| Field | Type | Required | Description |
|---|---|---|---|
file | File | Yes | The file to upload |
folder | string | No | Target folder path (e.g. invoices/2026) |
access | string | No | Access level: public, authenticated, or private. Default: public |
tags | string | No | Comma-separated tags for organization |
Response
{
"success": true,
"data": {
"fileId": "file_abc123def456",
"url": "https://cdn.platformxe.com/org_123/invoices/2026/receipt.pdf",
"format": "pdf",
"size": 245760,
"width": null,
"height": null,
"createdAt": "2026-04-05T14:30:00.000Z"
}
}
curl
curl -X POST https://api.platformxe.com/api/v1/storage/media/upload \
-H "x-api-key: pxk_live_your_api_key_here" \
-F "file=@/path/to/image.png" \
-F "folder=products/thumbnails" \
-F "access=public" \
-F "tags=product,thumbnail"
SDK
import { PlatformXe } from '@caldera/platformxe-sdk';
const px = new PlatformXe({ apiKey: 'pxk_live_your_api_key_here' });
const result = await px.storage.upload({
file: fileBuffer,
folder: 'products/thumbnails',
access: 'public',
tags: ['product', 'thumbnail'],
});
console.log(result.data.url);
// "https://cdn.platformxe.com/org_123/products/thumbnails/image.png"
Signed upload
Generate a pre-signed URL so clients can upload files directly from the browser without routing through your server.
POST /api/v1/storage/media/sign-upload
Scope: storage:upload
Request body
| Field | Type | Required | Description |
|---|---|---|---|
filename | string | Yes | Original filename |
contentType | string | Yes | MIME type of the file (e.g. image/png) |
folder | string | No | Target folder path |
access | string | No | Access level. Default: public |
maxSize | number | No | Maximum allowed file size in bytes |
Response
{
"success": true,
"data": {
"uploadUrl": "https://upload.platformxe.com/signed/abc123...",
"fileId": "file_pending_abc123",
"expiresAt": "2026-04-05T15:30:00.000Z"
}
}
Signed upload URLs expire after 60 minutes. The client must complete the upload before expiry or request a new signed URL.
curl
# Step 1: Get the signed URL
curl -X POST https://api.platformxe.com/api/v1/storage/media/sign-upload \
-H "Content-Type: application/json" \
-H "x-api-key: pxk_live_your_api_key_here" \
-d '{
"filename": "avatar.jpg",
"contentType": "image/jpeg",
"folder": "avatars",
"maxSize": 5242880
}'
# Step 2: Upload to the signed URL (from client)
curl -X PUT "https://upload.platformxe.com/signed/abc123..." \
-H "Content-Type: image/jpeg" \
--data-binary @avatar.jpg
Register external URL
Register a file that is already hosted elsewhere. PlatformXe indexes the file and optionally copies it to CDN storage.
POST /api/v1/storage/media/register
Scope: storage:upload
Request body
| Field | Type | Required | Description |
|---|---|---|---|
url | string | Yes | Publicly accessible URL of the file |
filename | string | No | Display name for the file |
folder | string | No | Target folder path |
copyToCdn | boolean | No | If true, download and re-host on CDN. Default: false |
Response
{
"success": true,
"data": {
"fileId": "file_ext_abc123",
"url": "https://cdn.platformxe.com/org_123/imported/avatar.jpg",
"sourceUrl": "https://example.com/avatar.jpg",
"copied": true,
"createdAt": "2026-04-05T14:30:00.000Z"
}
}
SDK
const result = await px.storage.register({
url: 'https://example.com/product-photo.jpg',
folder: 'products',
copyToCdn: true,
});
console.log(result.data.fileId);
// "file_ext_abc123"
Use copyToCdn: true if the external URL may become unavailable. The file is downloaded and stored on PlatformXe CDN for reliable access.
Error responses
| Code | Description |
|---|---|
BAD_REQUEST | Missing file, unsupported file type, or exceeds size limit |
FORBIDDEN | API key does not have the storage:upload scope |
RATE_LIMITED | Rate limit exceeded for this API key |
MODERATION_REJECTED | File was rejected by content moderation |