Server REST API
REST API endpoints for file management
Authentication
All authenticated endpoints require a Bearer token in the Authorization header.
Authorization: Bearer YOUR_API_KEYIf your API key is not associated with an app_id, pass it via the x-app-id header:
x-app-id: YOUR_APP_IDUpload
POST /upload
Upload a single file. Requires authentication.
Content-Type: multipart/form-data
| Field | Type | Description |
|---|---|---|
file | File | The file to upload. |
category | string | Optional category for the file. |
tags | string | Optional comma-separated tags. |
Response: 201
{
"id": "abc-123",
"url": "https://your-server.com/f/abc-123",
"filename": "photo.jpg",
"size": 102400,
"mimeType": "image/jpeg",
"contentHash": "sha256...",
"createdAt": "2026-01-01T00:00:00.000Z",
"category": "avatars",
"tags": ["profile"]
}File Management
GET /files/me
List all files owned by the authenticated user. Requires authentication.
Query Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
limit | number | 50 | Maximum files to return (max 500). |
offset | number | 0 | Number of files to skip. |
category | string | — | Filter by category. |
tag | string | — | Filter by tags (comma-separated). |
Response: 200
{
"files": [
{
"id": "abc-123",
"filename": "photo.jpg",
"url": "https://your-server.com/f/abc-123",
"mimeType": "image/jpeg",
"size": 102400,
"createdAt": "2026-01-01T00:00:00.000Z",
"category": "avatars",
"tags": ["profile"]
}
],
"total": 1,
"offset": 0,
"limit": 50,
"hasMore": false
}GET /files/me/:id
Get a single file's metadata by ID. Requires authentication. Returns only files owned by the authenticated user.
Response: 200
{
"id": "abc-123",
"filename": "photo.jpg",
"url": "https://your-server.com/f/abc-123",
"mimeType": "image/jpeg",
"size": 102400,
"contentHash": "sha256...",
"createdAt": "2026-01-01T00:00:00.000Z",
"category": "avatars",
"tags": ["profile"],
"isChunked": false
}Error Responses:
| Status | Description |
|---|---|
401 | Missing or invalid API key. |
403 | File does not belong to your app or user. |
404 | File not found. |
File Serving
GET /f/:id
Stream file content. Public — no authentication required.
Supports image transformations via query parameters (powered by wsrv.nl):
| Parameter | Description |
|---|---|
w | Width in pixels. |
h | Height in pixels. |
fit | Resize fit mode (inside, outside, cover, fill, contain). |
q | Quality (1–100). |
output | Output format (webp, jpg, png, gif, tiff, avif). |
blur | Gaussian blur (0.3–1000). |
ro | Rotation angle. |
flip | Flip vertically. |
flop | Flip horizontally. |
Example:
GET /f/abc-123?w=200&h=200&fit=cover&output=webpDELETE /f/:id
Delete a file. Requires authentication. Only the file owner can delete.
Response: 204 No Content
Error Responses:
| Status | Description |
|---|---|
401 | Missing or invalid API key. |
403 | File does not belong to your app or user. |
404 | File not found. |
Chunked Uploads
For files larger than 4MB, use chunked uploads.
POST /upload/init
Start a chunked upload session. Requires authentication.
Body:
{
"filename": "video.mp4",
"totalSize": 50000000,
"mimeType": "video/mp4",
"chunkCount": 8,
"contentHash": "sha256...",
"category": "videos",
"tags": "recording,screen"
}Response: 201
{
"uploadId": "upload-xyz",
"chunkSize": 7340032,
"chunkCount": 8,
"expiresAt": "2026-01-01T01:00:00.000Z"
}POST /upload/chunk
Upload a single chunk. Uses uploadId for auth (no API key needed).
Content-Type: multipart/form-data
| Field | Type | Description |
|---|---|---|
uploadId | string | The upload session ID. |
chunkIndex | number | Zero-based chunk index. |
file | File | The chunk data. |
Response: 200
{
"uploadId": "upload-xyz",
"chunkIndex": 0,
"chunksReceived": 1,
"chunksTotal": 8
}POST /upload/complete
Finalize a chunked upload. Requires authentication.
Body:
{
"uploadId": "upload-xyz"
}Response: 201 — Same format as single upload response.
Statistics
GET /stats/:appId
Get bandwidth usage for the current month.
{
"appId": "your-app-id",
"bandwidth": 1048576
}GET /stats/:appId/history
Get bandwidth history across all tracked months.
{
"appId": "your-app-id",
"months": {
"2026-01": 1048576,
"2026-02": 2097152
}
}