api documentation

all endpoints are relative to the base url

POST/api/upload

upload a file. returns the file id.

body

multipart/form-data with a file field

query parameters

slugoptional. custom short url (alphanumeric only)
captchaturnstile token (required for files >100MB if configured)
encryptedset to 1 if file is client-side encrypted
salthex-encoded 16-byte encryption salt (required if encrypted)
ivhex-encoded 12-byte encryption IV (required if encrypted)

response

{
  "uploadedId": "uuid"
}

errors

400 — missing file, invalid slug, or invalid encryption params

403 — captcha required or failed

413 — file exceeds 2GB limit

example

curl -X POST \
  -F "file=@photo.jpg" \
  "https://example.com/api/upload?slug=myphoto"
GET/api/download/:id

download a file by its id. redirects to a presigned s3 url (1 hour expiry).

query parameters

rawset to 1 to get the presigned url as json instead of a 302 redirect

default response

302 redirect to presigned s3 url

raw response

{
  "url": "https://s3.../presigned-url"
}

errors

404 — file not found

410 — file has expired

example

# direct download (follows redirect)
curl -L -o file.jpg \
  "https://example.com/api/download/UUID"

# get presigned url
curl "https://example.com/api/download/UUID?raw=1"
GET/api/slug-check

check if a custom slug is available.

query parameters

slugthe slug to check (alphanumeric only)

response

{
  "available": true
}
GET/:slug

short url redirect. resolves a slug to its file view page.

response

307 redirect to /viewfile/:id

PAGE/viewfile/:id

file info page. shows metadata, expiry, and download button. for encrypted files, prompts for password and decrypts in-browser.

notes

  • — files expire after 24 hours
  • — max file size is 2GB
  • — uploads over 100MB may require captcha verification
  • — rate limited to 5 uploads per 10 minutes
  • — encryption is client-side (AES-256-GCM + PBKDF2). the server never sees the password or plaintext
  • — presigned download urls expire after 1 hour