Skip to main content

Endpoint

POST /v1/media/upload
Content-Type: multipart/form-data
Authorization: Bearer sk_live_...

Form Fields

FieldRequiredDescription
fileBinary file (max 10 MB)
expiresInTTL (default 90d). Format: {n}{unit} e.g. 1h, 30d
titleDisplay title
descriptionFile description
pinned"true" to pin (immune to TTL cleanup)
metadataJSON string with custom metadata

Auto-Categorization

Files are automatically categorized by MIME type:
MIME PrefixCategory
image/*photo
video/*video
audio/*audio
Everything elsedocument

Example

curl -X POST "$API/v1/media/upload" \
  -H "Authorization: Bearer $API_KEY" \
  -F "[email protected]" \
  -F "expiresIn=90d" \
  -F "title=Profile Photo" \
  -F 'metadata={"tags":["profile"]}'

Response (201)

{
  "id": "3449d148-5cc5-4bcc-9e02-242398025dc2",
  "category": "photo",
  "filename": "photo.jpg",
  "blobName": "media/photo/photo__a1b2c3d4.jpg",
  "mimeType": "image/jpeg",
  "sizeBytes": 45000,
  "title": "Profile Photo",
  "pinned": false,
  "expiresAt": "2026-06-22T00:00:00Z",
  "createdAt": "2026-03-24T00:00:00Z"
}
Blob names follow the pattern media/{category}/{name}__{shortId}{ext}. The short ID ensures uniqueness even when uploading files with the same name.

Credit Cost

This operation costs 5 credits (media.upload).

Errors

StatusReason
400No file uploaded or invalid expiresIn format
401Missing or invalid API key
429Rate limit exceeded
502Shelby network write failed