Skip to content

API Overview

SkySend exposes a REST API under the /api prefix. All endpoints accept and return JSON unless otherwise noted.

Base URL

http://localhost:3000/api

Endpoints

MethodPathDescriptionAuth
GET/api/configServer configuration (limits)-
POST/api/uploadUpload encrypted file stream-
POST/api/meta/:idSave encrypted metadataOwner Token
GET/api/info/:idUpload info (size, expiry, downloads)-
GET/api/download/:idDownload encrypted file streamAuth Token
POST/api/password/:idVerify password-
DELETE/api/upload/:idDelete uploadOwner Token
GET/api/exists/:idCheck if upload exists-
GET/api/healthHealth check-

Authentication

SkySend uses two token types, both derived from the client-side secret:

Auth Token (X-Auth-Token)

Required for downloading files. Derived from the secret via HKDF + HMAC-SHA256. Proves the requester knows the encryption key.

Owner Token (X-Owner-Token)

Required for deleting uploads and saving metadata. Derived from the secret via HKDF. Proves upload ownership.

Both tokens are provided as base64url-encoded strings in request headers.

Common Response Codes

CodeMeaning
200Success
400Invalid request (missing/invalid parameters)
401Invalid or missing auth token
404Upload not found
409Conflict (e.g., metadata already set)
410Upload expired or download limit reached
429Rate limit or quota exceeded
500Internal server error

Rate Limiting

All endpoints are rate-limited. Response headers:

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 57
X-RateLimit-Reset: 1704067260000

Server Configuration

GET /api/config

Returns server limits and options for the client UI.

Response:

json
{
  "maxFileSize": 2147483648,
  "maxFilesPerUpload": 32,
  "expireOptions": [300, 3600, 86400, 604800],
  "defaultExpire": 86400,
  "downloadOptions": [1, 2, 3, 4, 5, 10, 20, 50, 100],
  "defaultDownload": 1,
  "customTitle": "SkySend",
  "customColor": null,
  "customLogo": null
}

Health Check

GET /api/health

Simple health check for monitoring and Docker health checks.

Response:

json
{
  "status": "ok",
  "timestamp": "2025-01-01T00:00:00.000Z"
}