DEVELOPER

UFOLOAD API documentation

Automate uploads, import files by URL, organize your library and issue signed links over a plain JSON REST API. WebDAV and FTP are available with the same API key.

25Public endpoints in 4 groups
REST + JSONBase URL https://ufoload.com/api/v1
API key

Send Authorization: Bearer ufo_... on every request.

Overview

Everything you can do in the dashboard with files and folders is available over HTTPS.

  • Base URL: https://ufoload.com/api/v1. Requests and responses are JSON, except file uploads and downloads.
  • Files are processed after upload (uploading, queued, processing, ready or failed); poll GET /files/{id} or filter the list by status.
  • Uploading the same content again does not use extra storage: the existing file is returned with "duplicate": true.
  • Errors use standard HTTP statuses: 401 (missing or invalid key), 404 (not found), 409 (not enough storage), 413 (file too large), 429 (rate limited, retry later).

Authentication

Create an API key in your account (Developers section) and send it as a bearer token.

Authorization: Bearer ufo_...

The key is shown only once when it is created; store it in an environment variable or a secrets manager and revoke it from the dashboard if it leaks. The same key works as the password for WebDAV and FTP, with your account email as the login. Create a free account or log in to get a key.

Common operations

Examples assume UFOLOAD_API_KEY is set in your shell.

POST

Upload a file

/api/v1/files

Send the file as the raw request body and give its name in X-File-Name. Optional folder: ?folder_id= or X-Folder-Id (root is the top level).

curl -X POST "https://ufoload.com/api/v1/files" \
  -H "Authorization: Bearer $UFOLOAD_API_KEY" \
  -H "X-File-Name: report.pdf" \
  -H "Content-Type: application/pdf" \
  --data-binary @report.pdf

Multipart form uploads work too (field file):

curl -X POST "https://ufoload.com/api/v1/files?folder_id=root" \
  -H "Authorization: Bearer $UFOLOAD_API_KEY" \
  -F "file=@video.mp4"
POST

Import by URL

/api/v1/files/import

The server downloads the file itself from a public http(s) link (up to 10 active imports). Track progress with GET /files/import.

curl -X POST "https://ufoload.com/api/v1/files/import" \
  -H "Authorization: Bearer $UFOLOAD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com/video.mp4", "name": "video.mp4"}'
GET

List files

/api/v1/files

Query parameters: status, q (name search), folder_id, limit (default 50, max 200), offset. The response contains items, total, limit and offset.

curl "https://ufoload.com/api/v1/files?status=ready&limit=20" \
  -H "Authorization: Bearer $UFOLOAD_API_KEY"
POST

Issue signed links

/api/v1/files/{fileID}/links

Playback and download links with a lifetime of 60 seconds to 30 days (ttl), optionally bound to an IP (bind_ip) or cookie (bind_cookie).

curl -X POST "https://ufoload.com/api/v1/files/FILE_ID/links" \
  -H "Authorization: Bearer $UFOLOAD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"ttl": 86400}'

WebDAV and FTP

Mount your library as a network drive or script transfers with standard tools. Login is your account email, the password is an API key.

WebDAV

HTTPS, port 443

https://ufoload.com/dav/
curl -u "you@example.com:$UFOLOAD_API_KEY" https://ufoload.com/dav/
curl -u "you@example.com:$UFOLOAD_API_KEY" -T report.pdf https://ufoload.com/dav/report.pdf
FTP

FTP and FTPS, port 21

ftp://ufoload.com/
curl -u "you@example.com:$UFOLOAD_API_KEY" ftp://ufoload.com/
curl -u "you@example.com:$UFOLOAD_API_KEY" --ftp-ssl -T report.pdf ftp://ufoload.com/report.pdf

Python

Using the requests library.

import os
import requests

BASE = "https://ufoload.com/api/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['UFOLOAD_API_KEY']}"}

# Upload a file (raw body; the name goes into X-File-Name)
with open("report.pdf", "rb") as f:
    r = requests.post(f"{BASE}/files", data=f, headers={**HEADERS, "X-File-Name": "report.pdf"})
r.raise_for_status()
print(r.json()["file"]["id"])

# Import by URL
r = requests.post(f"{BASE}/files/import", headers=HEADERS, json={"url": "https://example.com/video.mp4"})
r.raise_for_status()

# List ready files
page = requests.get(f"{BASE}/files", headers=HEADERS, params={"status": "ready", "limit": 20}).json()
for item in page["items"]:
    print(item["id"], item["name"])

Node.js

Node.js 18 or newer: built-in fetch, no dependencies.

import { readFile } from 'node:fs/promises'

const BASE = 'https://ufoload.com/api/v1'
const headers = { Authorization: `Bearer ${process.env.UFOLOAD_API_KEY}` }

// Upload a file (raw body; the name goes into X-File-Name)
const res = await fetch(`${BASE}/files`, {
  method: 'POST',
  headers: { ...headers, 'X-File-Name': 'report.pdf', 'Content-Type': 'application/pdf' },
  body: await readFile('report.pdf'),
})
if (!res.ok) throw new Error(`upload failed: ${res.status}`)
const { file } = await res.json()
console.log(file.id)

// Import by URL
await fetch(`${BASE}/files/import`, {
  method: 'POST',
  headers: { ...headers, 'Content-Type': 'application/json' },
  body: JSON.stringify({ url: 'https://example.com/video.mp4' }),
})

// List ready files
const page = await (await fetch(`${BASE}/files?status=ready&limit=20`, { headers })).json()
for (const item of page.items) console.log(item.id, item.name)

Endpoint reference

All 25 public operations. Paths are relative to https://ufoload.com; request and response schemas are in the OpenAPI specification.

Files

Upload, list, rename, delete and share files; manage covers and chapters of videos.

MethodPathDescription
POST/api/v1/filesUpload a file (multipart form or raw request body)
GET/api/v1/filesList your files (filter by status, name, folder; paginated)
GET/api/v1/files/{fileID}Get a file with playback and download links
PATCH/api/v1/files/{fileID}Rename a file or move it to a folder
DELETE/api/v1/files/{fileID}Delete a file
POST/api/v1/files/{fileID}/linksIssue signed links with a custom lifetime and IP/cookie binding
GET/api/v1/files/{fileID}/coverCover state: current, automatic, candidate frames, custom
PUT/api/v1/files/{fileID}/coverChoose the cover
POST/api/v1/files/{fileID}/cover/uploadUpload your own cover image
GET/api/v1/files/{fileID}/chaptersChapters (timecodes) of a video
PUT/api/v1/files/{fileID}/chaptersSet chapters manually
DELETE/api/v1/files/{fileID}/chaptersRevert to chapters from the video file
GET/api/v1/files/statsSummary of your files

Import by URL

The server downloads a file from a direct http(s) link and queues it for processing.

MethodPathDescription
POST/api/v1/files/importStart an import from a direct link (up to 10 active imports)
GET/api/v1/files/importActive and recent imports
DELETE/api/v1/files/import/{id}Cancel an import or remove a finished one from the list

Folders

Folder hierarchy and bulk operations on files and folders.

MethodPathDescription
GET/api/v1/foldersSubfolders of a folder and the path to it
POST/api/v1/foldersCreate a folder
GET/api/v1/folders/treeAll folders as a flat list
PATCH/api/v1/folders/{id}Rename and/or move a folder
DELETE/api/v1/folders/{id}Delete a folder with its contents
POST/api/v1/fs/moveMove files and folders into a folder
POST/api/v1/fs/deleteDelete files and folders

Public playback

Endpoints behind the public watch and embed pages; no API key required.

MethodPathDescription
GET/api/v1/public/files/{fileID}Data for the public watch and embed page
POST/api/v1/public/files/{fileID}/viewCount a view

OpenAPI specification

Machine-readable description for code generators and API clients.