PlatformXeDocs
Get API Key

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

FieldTypeRequiredDescription
fileFileYesThe file to upload
folderstringNoTarget folder path (e.g. invoices/2026)
accessstringNoAccess level: public, authenticated, or private. Default: public
tagsstringNoComma-separated tags for organization

HEIC/HEIF is accepted and converted. iPhone photos arrive as HEIC, which no browser except Safari renders. PlatformXe transcodes them to JPEG before storage, so the stored file, its url, format and size describe the JPEG (the name keeps its stem with a .jpg extension, and the JPEG is typically ~1.5× the HEIC). A HEIC the decoder cannot read is refused with 415 UNSUPPORTED_MEDIA_TYPE rather than stored unreadable — convert it before uploading (on an iPhone: Settings → Camera → Formats → Most Compatible).

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 { PlatformXeClient } from '@caldera/platformxe-sdk';

const px = new PlatformXeClient({ 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

FieldTypeRequiredDescription
filenamestringYesOriginal filename
contentTypestringYesMIME type of the file (e.g. image/png)
folderstringNoTarget folder path
accessstringNoAccess level. Default: public
maxSizenumberNoMaximum 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

FieldTypeRequiredDescription
urlstringYesPublicly accessible URL of the file
filenamestringNoDisplay name for the file
folderstringNoTarget folder path
copyToCdnbooleanNoIf 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"

A registered HEIC/HEIF (from the signed-upload flow) is normalised the same way as a direct upload: PlatformXe fetches it back, converts it to JPEG, stores the JPEG beside it and deletes the original. The response and the file record describe the JPEG. A blob that cannot be converted returns 415 UNSUPPORTED_MEDIA_TYPE and nothing is recorded.

Use copyToCdn: true if the external URL may become unavailable. The file is downloaded and stored on PlatformXe CDN for reliable access.

Error responses

CodeDescription
BAD_REQUESTMissing file, unsupported file type, or exceeds size limit
FORBIDDENAPI key does not have the storage:upload scope
RATE_LIMITEDRate limit exceeded for this API key
MODERATION_REJECTEDFile was rejected by content moderation
UNSUPPORTED_MEDIA_TYPEHTTP 415. The file is an accepted type that could not be made storable (a HEIC/HEIF the decoder cannot read). Convert it before uploading; retrying will not help