// every endpoint of the server, v0
no endpoints match the filter.
All API responses are JSON unless stated otherwise. Errors use the shape
{"error": "...", "message": "..."}, where message is omitted when absent.
Auth is registered per endpoint but currently disabled for all of them — no
Authorization header is required. Resource tokens
(repository, short url, file) are separate from that and always required where listed.
Returns the build version of the running server.
{
"version": "1.4.0"
}
curl -s $BASE/api/v0/version
AES-GCM helpers. Keys and payloads travel as Base64 strings; the server never stores them.
Generates a fresh AES key. The key is returned once and never persisted.
{
"key": "b64-encoded-aes-key"
}
curl -s $BASE/api/v0/cipher/aes
Encrypts data with the given AES key.
| field | type | description | |
|---|---|---|---|
| data | string | required | plain text to encrypt |
| key | string | required | Base64 AES key |
{
"data": "b64-cipher-text"
}
data or key blank
500encryption failed
curl -s -X POST $BASE/api/v0/cipher/aes/encrypt \
-H 'Content-Type: application/json' \
-d '{"data":"hello","key":"<key>"}'
Decrypts data produced by the encrypt endpoint using the same key.
| field | type | description | |
|---|---|---|---|
| data | string | required | Base64 cipher text |
| key | string | required | the same Base64 AES key |
{
"data": "hello"
}
data or key blank
500wrong key or corrupted payload
curl -s -X POST $BASE/api/v0/cipher/aes/decrypt \
-H 'Content-Type: application/json' \
-d '{"data":"<cipher>","key":"<key>"}'
The delete token is returned only once, at creation time. Without it a short url cannot be removed.
Creates a short url pointing at url.
| field | type | description | |
|---|---|---|---|
| url | string | required | target url |
| name | string | optional | human readable label |
| description | string | optional | free form note |
{
"id": "aB3xY",
"token": "8f14e45f-…"
}
url missing or invalid
curl -s -X POST $BASE/api/v0/short-url \
-H 'Content-Type: application/json' \
-d '{"url":"https://example.com"}'
Resolves a short url and redirects to the target. This is the link you share.
| param | type | description | |
|---|---|---|---|
| id | string | required | short id from creation |
id missing
404unknown id
curl -sI $BASE/api/v0/short-url/aB3xY
Deletes a short url. The token may be passed as a query param or in the JSON body.
| param | in | description | |
|---|---|---|---|
| id | path | required | short id |
| token | query / body | required | delete token from creation |
curl -s -X DELETE "$BASE/api/v0/short-url/aB3xY?token=<token>"
A repository is a token-protected bag of links. The token is shown only in the
create response — every other call needs it as ?token=. A wrong token is answered
with 404 on purpose, so repository ids cannot be probed.
Creates a new link repository. Note the trailing slash — it is part of the route.
| field | type | description | |
|---|---|---|---|
| name | string | optional | repository label |
{
"repositoryId": "3f1c…-uuid",
"token": "1a2b…-uuid",
"name": "my links",
"createdAt": "2026-07-22T10:15:30Z"
}
curl -s -X POST $BASE/api/v0/repository/links/ \
-H 'Content-Type: application/json' \
-d '{"name":"my links"}'
Returns the repository with all of its links. The token is never echoed back.
| param | in | description | |
|---|---|---|---|
| repositoryId | path | required | repository uuid |
| token | query | required | repository token |
{
"repositoryId": "3f1c…-uuid",
"name": "my links",
"createdAt": "2026-07-22T10:15:30Z",
"links": [
{
"uuid": "9d0e…-uuid",
"url": "https://example.com",
"name": "example",
"description": ""
}
]
}
curl -s "$BASE/api/v0/repository/links/<id>?token=<token>"
Deletes a repository together with all links inside it.
| param | in | description | |
|---|---|---|---|
| repositoryId | path | required | repository uuid |
| token | query | required | repository token |
curl -s -X DELETE "$BASE/api/v0/repository/links/<id>?token=<token>"
Adds a link to the repository.
| param | in | description | |
|---|---|---|---|
| repositoryId | path | required | repository uuid |
| token | query | required | repository token |
| url | body | required | link target |
| name | body | optional | link label |
| description | body | optional | free form note |
{
"uuid": "9d0e…-uuid",
"url": "https://example.com",
"name": "example",
"description": ""
}
curl -s -X POST "$BASE/api/v0/repository/links/<id>/links?token=<token>" \
-H 'Content-Type: application/json' \
-d '{"url":"https://example.com","name":"example"}'
Replaces the stored link with the values from the body.
| param | in | description | |
|---|---|---|---|
| repositoryId | path | required | repository uuid |
| uuid | path | required | link uuid |
| token | query | required | repository token |
| url | body | required | new link target |
| name | body | optional | new label |
| description | body | optional | new note |
url blank
404repository or link not found
curl -s -X PUT "$BASE/api/v0/repository/links/<id>/links/<uuid>?token=<token>" \
-H 'Content-Type: application/json' \
-d '{"url":"https://example.org"}'
Removes a single link from the repository.
| param | in | description | |
|---|---|---|---|
| repositoryId | path | required | repository uuid |
| uuid | path | required | link uuid |
| token | query | required | repository token |
curl -s -X DELETE "$BASE/api/v0/repository/links/<id>/links/<uuid>?token=<token>"
Files are stored with an optional TTL and are swept by a background cleanup task once expired.
Every read and delete needs the token handed out at upload time.
Uploads a single file as multipart/form-data.
| field | type | description | |
|---|---|---|---|
| file | file | required | the file itself; exactly one |
| name | string | optional | display name, defaults to the original filename |
| ttl | number | optional | lifetime in seconds; 0 or absent means no expiry |
{
"uuid": "7c2d…-uuid",
"token": "4e5f…-uuid",
"name": "report.pdf",
"expiredTime": 1785000000000
}
curl -s -X POST $BASE/api/v0/uploaded-files \ -F '[email protected]' \ -F 'name=report.pdf' \ -F 'ttl=3600'
Returns the configured upload limit, so clients can reject oversized files before sending them.
{
"megabytes": 100,
"bytes": 104857600
}
curl -s $BASE/api/v0/uploaded-files/max-size
Metadata of one file. The token is never included in the response.
| param | in | description | |
|---|---|---|---|
| uuid | path | required | file uuid |
| token | query | required | file access token |
{
"uuid": "7c2d…-uuid",
"name": "report.pdf",
"expiredTime": 1785000000000
}
curl -s "$BASE/api/v0/uploaded-files/<uuid>?token=<token>"
Streams the file content as application/octet-stream with a
Content-Disposition attachment header.
| param | in | description | |
|---|---|---|---|
| uuid | path | required | file uuid |
| token | query | required | file access token |
curl -sOJ "$BASE/api/v0/uploaded-files/<uuid>/download?token=<token>"
Deletes the file and its metadata. The token may be a query param or a JSON body field.
| param | in | description | |
|---|---|---|---|
| uuid | path | required | file uuid |
| token | query / body | required | file access token |
curl -s -X DELETE "$BASE/api/v0/uploaded-files/<uuid>?token=<token>"
Listing every uploaded file is deliberately not allowed — the route exists but always refuses. Files are reachable only by uuid plus token.
{
"error": "Listing all files is not allowed"
}
Backed by yt-dlp on the server. Playlist parameters are ignored, age-restricted
videos need server-side cookies, and each call is capped at a 120 second timeout.
Returns the raw yt-dlp metadata JSON for a video.
| param | type | description | |
|---|---|---|---|
| url | string | required | video url |
url missing or rejected
500yt-dlp failure
curl -s "$BASE/api/v0/youtube/info?url=https://youtu.be/<id>"
Downloads the video on the server and returns the MP4 bytes (video/mp4).
| param | type | description | |
|---|---|---|---|
| url | string | required | video url |
url missing or rejected
500yt-dlp failure
curl -s -o video.mp4 "$BASE/api/v0/youtube/download?url=https://youtu.be/<id>"
Returns the caller's ip as the server sees it. Behind a proxy the value comes from
CF-Connecting-IP, then X-Forwarded-For, then the socket address —
good enough to show users their own ip, not for auth or rate limiting.
{
"ip": "203.0.113.7"
}
curl -s $BASE/api/v0/network/ip
Classpath resources served straight from the jar. Every category behaves the same way: without a name it lists what is available, with a name it returns the file.
The index page listing every service.
The site favicon (ss_icon.svg).
Lists the files available in a category.
| category | content |
|---|---|
| html | service pages |
| css | stylesheets |
| js | client scripts |
| images | raster images |
| svg | vector images |
| json | static datasets |
| documents | |
| domain | domain files |
curl -s $BASE/static/v0/json
Returns one static file with the content type of its category.
curl -s $BASE/static/v0/html/api_docs.html