Skip to content
BasiX Media

Upload a file

Direct, presigned and base64 uploads.

On this page

Direct upload

POST https://upload.basix.media/api/v1/upload, multipart/form-data.

FieldRequiredMeaning
fileyesThe file.
pathnoWhere it goes. Omit it and the file lands at the root under its own name.
curl -X POST https://upload.basix.media/api/v1/upload \
  -H "Authorization: Bearer $BASIX_KEY" \
  -F "path=shop/potions/potion_x2.png" \
  -F "[email protected]"

Response, 201 Created (or 200 OK when it replaced a file):

json
{
  "id": "k7x2m9q4pz1a",
  "path": "shop/potions/potion_x2.png",
  "url": "https://cdn.basix.media/a7k2m9x4/shop/potions/potion_x2.png",
  "size": 15320,
  "mime": "image/png",
  "name": "potion.png",
  "replaced": false
}

Path rules.

  • path ending in / is a folder: shop/potions/ stores the file under its own name with the right extension.
  • Any other path is the exact file path. Its extension must match the real type of the file, or you get 400 INVALID_PATH.
  • Paths are lowercased. Allowed characters: a-z, 0-9, ., _, -. Each segment starts with a letter or digit.
  • At most 200 characters, 8 levels, 64 characters per segment.

Same path, new file. Uploading to a path that already exists replaces the file. The URL stays the same. The response says "replaced": true with status 200. The swap is atomic: a reader gets the old file or the new one, never half of each.

Presigned upload (let a client upload without the key)

Your server asks for a one-time URL. The client sends the bytes to it. The key never leaves your server.

POST https://upload.basix.media/api/v3/file/presigned-url, JSON body:

FieldRequiredMeaning
typenoimage, video or audio. Restricts what the URL accepts.
pathnoFolder for the file. Spaces and capitals are repaired.
curl -X POST https://upload.basix.media/api/v3/file/presigned-url \
  -H "Authorization: Bearer $BASIX_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "type": "image", "path": "reports" }'

Response:

json
{
  "status": "ok",
  "success": true,
  "presignedUrl": "https://upload.basix.media/api/v3/file/presigned-url/eyJhbGciOi...",
  "url": "https://upload.basix.media/api/v3/file/presigned-url/eyJhbGciOi...",
  "expiresAt": "2026-10-25T14:15:00.000Z",
  "expiresIn": 900,
  "data": { "presignedUrl": "...", "url": "...", "expiresAt": "..." }
}

Then POST a multipart form (any field name) or PUT the raw bytes to presignedUrl. No auth header. The URL works once and expires after 15 minutes. The file is stored as <folder>/<id>.<ext>. The upload answers with the compatible response shape shown below.

Need several uploads from one page, or a drag-and-drop widget? POST https://upload.basix.media/api/upload-token with your key and an optional JSON body { "folder": "user-uploads", "maxSizeMb": 10, "expiresIn": 600 } returns { "token": "..." }. The browser sends it as Authorization: Bearer <token> to /api/v1/upload. It can only upload, only into that folder, as <folder>/<id>.<ext>. Guides: https://basix.media/docs/recipes/browser-upload and https://basix.media/docs/recipes/upload-widget.

Base64 upload

For bytes you already hold as base64 or a data URI (for example a screenshot in a server script).

POST https://upload.basix.media/api/v3/file/base64, JSON body: base64 (required, a base64 string or data: URI), filename (optional), path (optional folder), retentionExempt (optional, true keeps the file out of folder retention). Body limit: 48 MB. The file is stored as <folder>/<id>.<ext>.

curl -X POST https://upload.basix.media/api/v3/file/base64 \
  -H "Authorization: Bearer $BASIX_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "base64": "iVBORw0KGgo...", "filename": "shot.png", "path": "screenshots" }'

Upload from a Discord bot or web backend

Use POST /api/v1/upload from the server with an upload key (JavaScript example under Direct upload). For browser uploads, your backend calls POST /api/v3/file/presigned-url and gives the presignedUrl to the browser, which PUTs the file to it.

Try it on your own server

Create a free account and your API key is ready in about two minutes. 3 GB included, bandwidth never billed, no card needed.

Create a free account
Upload a file — Standalone docs — BasiX