Introduction
REST APIs usable via HTTP in any environment. The CLI is also available.
curl https://storage.liteio.dev/files \
-H "Authorization: Bearer $STORAGE_API_KEY"Base URL: https://storage.liteio.dev
REST APIs usable via HTTP in any environment. The CLI is also available.
curl https://storage.liteio.dev/files \
-H "Authorization: Bearer $STORAGE_API_KEY"Create API keys via POST /auth/keys or the dashboard. Provide them as Bearer tokens.
Authorization: Bearer STORAGE_API_KEYKeys can be scoped to a path prefix (e.g. docs/) and set to expire. Keep keys secret. Never expose in client-side code.
Send request bodies as JSON with Content-Type: application/json.
GET /files/{path} returns a 302 redirect to a presigned URL by default. Set Accept: application/json to get metadata instead.
Errors return JSON with a consistent shape:
{
"error": "not_found",
"message": "File not found"
}| Code | Error | Meaning |
|---|---|---|
| 400 | bad_request | Invalid parameters or body |
| 401 | unauthorized | Missing or invalid auth |
| 403 | forbidden | Path not allowed |
| 404 | not_found | Resource not found |
| 409 | conflict | Already exists |
| 429 | rate_limited | Too many requests |
| 500 | internal | Server error |
/files/{path}
Downloads a file by path. By default returns a 302 redirect to a presigned R2 URL. With Accept: application/json, returns metadata including the presigned URL, file size, content type, and ETag.
File path (e.g. docs/report.pdf)
302 Redirect to presigned URL
404 File not found
1curl https://storage.liteio.dev/files/:path \
2 -H "Authorization: Bearer $STORAGE_API_KEY"
/files/{path}
Returns file metadata in HTTP response headers (Content-Type, Content-Length, ETag) without downloading the file body. Useful for checking if a file exists or getting its size.
File path (e.g. docs/report.pdf)
Metadata in headers
404 Not found
1curl https://storage.liteio.dev/files/:path \
2 -H "Authorization: Bearer $STORAGE_API_KEY"
/files
Returns a list of files and folders in the authenticated user's storage. Results are paginated and can be filtered by prefix to list contents of a specific folder.
Folder prefix (e.g. docs/)
Defaults to 200.
Defaults to 0.
Directory listing
1curl https://storage.liteio.dev/files \
2 -H "Authorization: Bearer $STORAGE_API_KEY"
1{
2 "prefix": "string",
3 "entries": [
4 {
5 "name": "string",
6 "type": "string",
7 "size": 0,
8 "updated_at": 0,
9 "tx": 0,
10 "tx_time": 0
11 }
12 ],
13 "truncated": true
14}/files/search
Searches for files by name across the authenticated user's storage. Supports multi-word queries with relevance scoring. Results are sorted by match quality.
Search query
Defaults to 50.
Search results
1curl https://storage.liteio.dev/files/search \
2 -H "Authorization: Bearer $STORAGE_API_KEY"
1{
2 "query": "string",
3 "results": [
4 {
5 "path": "string",
6 "name": "string"
7 }
8 ]
9}/files/mkdir
Creates an empty folder marker in storage. The path must end with /. Folders are virtual — they exist as zero-byte objects in R2.
Folder path (must end with /)
Folder created
1curl -X POST https://storage.liteio.dev/files/mkdir \
2 -H "Authorization: Bearer $STORAGE_API_KEY" \
3 -H "Content-Type: application/json" \
4 -d '{"path":"docs/drafts/"}'
1{
2 "path": "string",
3 "created": true
4}/files/move
Moves or renames a file within the authenticated user's storage. Both the source and destination paths must be valid. The file's content and metadata are preserved.
Commit message for the move
Moved
1curl -X POST https://storage.liteio.dev/files/move \
2 -H "Authorization: Bearer $STORAGE_API_KEY" \
3 -H "Content-Type: application/json" \
4 -d '{"from":"string","to":"string","message":"string"}'
1{
2 "from": "string",
3 "to": "string",
4 "tx": 0,
5 "time": 0
6}/files/{path}
Permanently deletes a file or folder. For folders (paths ending with /), recursively deletes all contents. This action cannot be undone.
File path (e.g. docs/report.pdf)
Delete result
1curl -X DELETE https://storage.liteio.dev/files/:path \
2 -H "Authorization: Bearer $STORAGE_API_KEY"
1{
2 "deleted": 0,
3 "tx": 0,
4 "time": 0
5}/files/stats
Returns aggregate storage statistics for the authenticated user, including total file count and total bytes used.
Usage
1curl https://storage.liteio.dev/files/stats \
2 -H "Authorization: Bearer $STORAGE_API_KEY"
1{
2 "files": 0,
3 "bytes": 0
4}/files/log
Filter events by file path
Return events after this tx number
Defaults to 50.
Event log
1curl https://storage.liteio.dev/files/log \
2 -H "Authorization: Bearer $STORAGE_API_KEY"
1{
2 "events": [
3 {
4 "tx": 0,
5 "action": "string",
6 "path": "string",
7 "size": 0,
8 "msg": "string",
9 "ts": 0
10 }
11 ]
12}/files/uploads
Initiates a file upload by generating a presigned PUT URL. Upload the file directly to this URL using an HTTP PUT request, then call Complete an upload to index it in the database.
Presigned upload URL
1curl -X POST https://storage.liteio.dev/files/uploads \
2 -H "Authorization: Bearer $STORAGE_API_KEY" \
3 -H "Content-Type: application/json" \
4 -d '{"path":"docs/report.pdf","content_type":"string"}'
1{
2 "url": "string",
3 "content_type": "string",
4 "expires_in": 0
5}/files/uploads/complete
Confirms a file upload after the file has been uploaded to the presigned URL. Verifies the object exists in R2 and indexes it in the database with its metadata.
Commit message
File metadata
1curl -X POST https://storage.liteio.dev/files/uploads/complete \
2 -H "Authorization: Bearer $STORAGE_API_KEY" \
3 -H "Content-Type: application/json" \
4 -d '{"path":"string","message":"string"}'
1{
2 "path": "string",
3 "name": "string",
4 "size": 0,
5 "tx": 0,
6 "time": 0
7}/files/uploads/multipart
Initiates a multipart upload for large files. Returns presigned URLs for each part. Upload parts in parallel for faster transfers, then call Complete a multipart upload.
Multipart upload initiated
1curl -X POST https://storage.liteio.dev/files/uploads/multipart \
2 -H "Authorization: Bearer $STORAGE_API_KEY" \
3 -H "Content-Type: application/json" \
4 -d '{"path":"string","content_type":"string","part_count":0}'
1{
2 "upload_id": "string",
3 "key": "string",
4 "content_type": "string",
5 "part_urls": ["string"],
6 "expires_in": 0
7}/files/uploads/multipart/complete
Finalizes a multipart upload by assembling all uploaded parts into a single object. You must provide the ETag returned from each part upload.
Commit message
Upload completed
1curl -X POST https://storage.liteio.dev/files/uploads/multipart/complete \
2 -H "Authorization: Bearer $STORAGE_API_KEY" \
3 -H "Content-Type: application/json" \
4 -d '{"path":"string","upload_id":"string","parts":[{"part_number":0,"etag":"string"}],"message":"string"}'
1{
2 "path": "string",
3 "name": "string",
4 "size": 0,
5 "tx": 0,
6 "time": 0
7}/files/uploads/multipart/abort
Cancels an in-progress multipart upload and cleans up any parts that have already been uploaded.
Upload aborted
1curl -X POST https://storage.liteio.dev/files/uploads/multipart/abort \
2 -H "Authorization: Bearer $STORAGE_API_KEY" \
3 -H "Content-Type: application/json" \
4 -d '{"path":"string","upload_id":"string"}'
1{
2 "aborted": true
3}/s/{token}
Accesses a file using a share token created via Share a file. Returns a 302 redirect to a presigned R2 URL for downloading. No authentication is required.
Share token
302 Redirect to presigned R2 URL
Invalid or expired token
1curl https://storage.liteio.dev/s/:token
/auth/magic-link
Sends a passwordless sign-in link to the provided email address. The link is single-use and expires after 15 minutes. A generic response is always returned to prevent email enumeration.
Turnstile token (browser clients)
Magic link sent
Bad request
Bot check failed
Conflict
Rate limited
Email delivery failed
1curl -X POST https://storage.liteio.dev/auth/magic-link \
2 -H "Content-Type: application/json" \
3 -d '{"email":"you@email.com","cf-turnstile-response":"string"}'
1{
2 "message": "string"
3}/auth/register
Creates a new account with an Ed25519 public key for cryptographic signature-based authentication. The actor name must be 1-64 characters, alphanumeric with hyphens and underscores.
human or agent Defaults to human.
Base64 Ed25519 public key
Created
Bad request
Actor already exists
Rate limited
1curl -X POST https://storage.liteio.dev/auth/register \
2 -H "Content-Type: application/json" \
3 -d '{"actor":"alice","type":"human","public_key":"string"}'
1{
2 "actor": "string",
3 "type": "string"
4}/auth/challenge
Issues a cryptographic nonce for Ed25519 signature verification. The challenge expires after 5 minutes. Sign the nonce with your private key and submit via Verify a signature.
Challenge issued
Bad request
Actor not found
Rate limited
1curl -X POST https://storage.liteio.dev/auth/challenge \
2 -H "Content-Type: application/json" \
3 -d '{"actor":"alice"}'
1{
2 "challenge_id": "string",
3 "nonce": "string",
4 "expires_at": 0
5}/auth/verify
Verifies an Ed25519 signature of the challenge nonce and issues a session token. The session token can be used as a Bearer token for authenticated requests.
Base64 Ed25519 signature of the nonce
Session token
Bad request
Invalid signature
Challenge not found
Rate limited
1curl -X POST https://storage.liteio.dev/auth/verify \
2 -H "Content-Type: application/json" \
3 -d '{"challenge_id":"string","actor":"string","signature":"string"}'
1{
2 "token": "string",
3 "actor": "string",
4 "expires_at": 0
5}/auth/logout
Invalidates the current session token. Accepts the token from either the Authorization header or a session cookie.
OK
1curl -X POST https://storage.liteio.dev/auth/logout
1{
2 "ok": true
3}/auth/keys
Creates a new API key for programmatic access. The key token is returned exactly once in the response — store it securely, as it cannot be retrieved again.
Defaults to .
Restrict to paths starting with this prefix Defaults to .
Seconds until expiry
API key (token shown once)
Store securely — not shown again
Rate limited
1curl -X POST https://storage.liteio.dev/auth/keys \
2 -H "Authorization: Bearer $STORAGE_API_KEY" \
3 -H "Content-Type: application/json" \
4 -d '{"name":"deploy-bot","prefix":"string","expires_in":0}'
1{
2 "id": "string",
3 "token": "string",
4 "name": "string",
5 "prefix": "string",
6 "expires_at": 0
7}/auth/keys
Returns all API keys for the authenticated user. Key tokens (secrets) are never included in the response — only metadata like name, prefix scope, and expiry.
API keys
1curl https://storage.liteio.dev/auth/keys \
2 -H "Authorization: Bearer $STORAGE_API_KEY"
1{
2 "keys": [
3 {
4 "id": "string",
5 "name": "string",
6 "prefix": "string",
7 "expires_at": 0,
8 "created_at": 0
9 }
10 ]
11}/auth/keys/{id}
Permanently revokes an API key. Any requests using this key will immediately start returning 401 Unauthorized.
Deleted
Not found
1curl -X DELETE https://storage.liteio.dev/auth/keys/:id \
2 -H "Authorization: Bearer $STORAGE_API_KEY"
1{
2 "deleted": true
3}GET /files/{path}
Downloads a file by path. By default returns a 302 redirect to a presigned R2 URL. With Accept: application/json, returns metadata including the presigned URL, file size, content type, and ETag.
Requires authentication
Parameters:
- path (path, required) — File path (e.g. docs/report.pdf)
HEAD /files/{path}
Returns file metadata in HTTP response headers (Content-Type, Content-Length, ETag) without downloading the file body. Useful for checking if a file exists or getting its size.
Requires authentication
Parameters:
- path (path, required) — File path (e.g. docs/report.pdf)
GET /files
Returns a list of files and folders in the authenticated user's storage. Results are paginated and can be filtered by prefix to list contents of a specific folder.
Requires authentication
Parameters:
- prefix (query, optional) — Folder prefix (e.g. docs/)
- limit (query, optional) — integer
- offset (query, optional) — integer
GET /files/search
Searches for files by name across the authenticated user's storage. Supports multi-word queries with relevance scoring. Results are sorted by match quality.
Requires authentication
Parameters:
- q (query, required) — Search query
- limit (query, optional) — integer
POST /files/mkdir
Creates an empty folder marker in storage. The path must end with /. Folders are virtual — they exist as zero-byte objects in R2.
Requires authentication
Body:
- path (required, string) — Folder path (must end with /)
POST /files/move
Moves or renames a file within the authenticated user's storage. Both the source and destination paths must be valid. The file's content and metadata are preserved.
Requires authentication
Body:
- from (required, string) —
- to (required, string) —
- message (optional, string) — Commit message for the move
DELETE /files/{path}
Permanently deletes a file or folder. For folders (paths ending with /), recursively deletes all contents. This action cannot be undone.
Requires authentication
Parameters:
- path (path, required) — File path (e.g. docs/report.pdf)
GET /files/stats
Returns aggregate storage statistics for the authenticated user, including total file count and total bytes used.
Requires authentication
GET /files/log
Requires authentication
Parameters:
- path (query, optional) — Filter events by file path
- since_tx (query, optional) — Return events after this tx number
- limit (query, optional) — integer
POST /files/uploads
Initiates a file upload by generating a presigned PUT URL. Upload the file directly to this URL using an HTTP PUT request, then call Complete an upload to index it in the database.
Requires authentication
Body:
- path (required, string) —
- content_type (optional, string) —
POST /files/uploads/complete
Confirms a file upload after the file has been uploaded to the presigned URL. Verifies the object exists in R2 and indexes it in the database with its metadata.
Requires authentication
Body:
- path (required, string) —
- message (optional, string) — Commit message
POST /files/uploads/multipart
Initiates a multipart upload for large files. Returns presigned URLs for each part. Upload parts in parallel for faster transfers, then call Complete a multipart upload.
Requires authentication
Body:
- path (required, string) —
- content_type (optional, string) —
- part_count (optional, integer) —
POST /files/uploads/multipart/complete
Finalizes a multipart upload by assembling all uploaded parts into a single object. You must provide the ETag returned from each part upload.
Requires authentication
Body:
- path (required, string) —
- upload_id (required, string) —
- parts (required, array) —
- message (optional, string) — Commit message
POST /files/uploads/multipart/abort
Cancels an in-progress multipart upload and cleans up any parts that have already been uploaded.
Requires authentication
Body:
- path (required, string) —
- upload_id (required, string) —
POST /files/share
Creates a temporary, public share link for a file. The link expires after the specified TTL (default 1 hour, maximum 7 days). Anyone with the link can download the file.
Requires authentication
Body:
- path (required, string) —
- ttl (optional, integer) — Seconds (default 3600, max 604800)
GET /s/{token}
Accesses a file using a share token created via Share a file. Returns a 302 redirect to a presigned R2 URL for downloading. No authentication is required.
Parameters:
- token (path, required) — Share token
POST /auth/magic-link
Sends a passwordless sign-in link to the provided email address. The link is single-use and expires after 15 minutes. A generic response is always returned to prevent email enumeration.
Body:
- email (required, string) —
- cf-turnstile-response (optional, string) — Turnstile token (browser clients)
POST /auth/register
Creates a new account with an Ed25519 public key for cryptographic signature-based authentication. The actor name must be 1-64 characters, alphanumeric with hyphens and underscores.
Body:
- actor (required, string) —
- type (optional, string) —
- public_key (required, string) — Base64 Ed25519 public key
POST /auth/challenge
Issues a cryptographic nonce for Ed25519 signature verification. The challenge expires after 5 minutes. Sign the nonce with your private key and submit via Verify a signature.
Body:
- actor (required, string) —
POST /auth/verify
Verifies an Ed25519 signature of the challenge nonce and issues a session token. The session token can be used as a Bearer token for authenticated requests.
Body:
- challenge_id (required, string) —
- actor (required, string) —
- signature (required, string) — Base64 Ed25519 signature of the nonce
POST /auth/logout
Invalidates the current session token. Accepts the token from either the Authorization header or a session cookie.
POST /auth/keys
Creates a new API key for programmatic access. The key token is returned exactly once in the response — store it securely, as it cannot be retrieved again.
Requires authentication
Body:
- name (optional, string) —
- prefix (optional, string) — Restrict to paths starting with this prefix
- expires_in (optional, integer) — Seconds until expiry
GET /auth/keys
Returns all API keys for the authenticated user. Key tokens (secrets) are never included in the response — only metadata like name, prefix scope, and expiry.
Requires authentication
DELETE /auth/keys/{id}
Permanently revokes an API key. Any requests using this key will immediately start returning 401 Unauthorized.
Requires authentication
Parameters:
- id (path, required) — string