Upload a file
Direct, presigned and base64 uploads.
On this page
Direct upload
POST https://upload.basix.media/api/v1/upload, multipart/form-data.
| Field | Required | Meaning |
|---|---|---|
file | yes | The file. |
path | no | Where 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):
{
"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.
pathending in/is a folder:shop/potions/stores the file under its own name with the right extension.- Any other
pathis the exact file path. Its extension must match the real type of the file, or you get400 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:
| Field | Required | Meaning |
|---|---|---|
type | no | image, video or audio. Restricts what the URL accepts. |
path | no | Folder 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:
{
"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.