arrow_back Back to File Manager
api REST API v1

ShareWith API

Programmatically manage your files, folders, and account. Authenticate with API keys and integrate with any language or tool.

Base URL: /api/v1
smart_toy Reading this as a bot or AI agent?

Take the machine-readable versions instead of scraping this page — or connect over MCP and work the files directly.

Overview

The ShareWith API provides full programmatic access to your file management operations. You can list, upload, download, move, rename, and delete files and folders, as well as manage your account and API keys.

All API endpoints are prefixed with /api/v1/. The API uses JSON for request and response bodies (except file downloads and uploads). Authentication is done via API keys passed in the X-API-Key header.

info
Paths use forward slashes (/). An empty or omitted path refers to your root. The API reaches everything the web UI can see — your own files, folders an administrator shared with you, and mounted FTP/SFTP/Google Drive storage. See Paths & Locations.

Paths & Locations

Every endpoint that takes a path accepts the same virtual path namespace the file manager uses. A path either starts at your own root, or begins with a mount prefix that selects another location.

Path looks likeWhere it goes
reports/q3.pdfYour own files
__adm_<id>/…A server folder an administrator shared with you
__conn_<id>/…A mounted FTP, SFTP or Google Drive connector

You do not have to guess the ids — call GET /locations, or list your root with GET /files and read the mount field on each entry.

curl -H "X-API-Key: YOUR_KEY" https://sharewith.xyz/api/v1/locations { "success": true, "data": [ { "kind": "own", "name": "My Files", "path": "", "target": "this server" }, { "kind": "shared", "name": "EMBY", "path": "__adm_807351b0", "target": "/DATA/AppData/emby/config/Movie", "readOnly": false }, { "kind": "ftp", "name": "ZHost FTP", "path": "__conn_38ab92fe", "target": "user@host:21/" } ] }

From there, treat the mount like any other folder:

# list inside a shared folder GET /api/v1/files?path=__adm_807351b0/Movies # download a file from an FTP mount GET /api/v1/files/download?path=__conn_38ab92fe/backups/site.zip # copy from a shared folder into your own files (streamed across backends) PUT /api/v1/files/copy?from=__adm_807351b0/Movies/clip.mp4&to=
warning
A shared folder may be marked read-only by the administrator. You can list, download and copy out of it, but upload, rename, move and delete return 403. The readOnly flag on listings and on /locations tells you in advance.
info
Storage quota applies to your own files only — writing into a mount does not count against it, because the bytes live on the remote server.

Authentication

Every API request must include a valid API key in the X-API-Key HTTP header. You can generate API keys from the File Manager sidebar (API tab) or via the API itself (if you already have a key).

Header Format

X-API-Key: your-api-key-uuid-here

Folder-Scoped Keys

API keys can be scoped to a specific folder. When creating a key, you can optionally set a Folder Scope to restrict the key's access to only that folder and its subfolders. If no folder scope is set, the key has full access to your entire storage.

info
When using a folder-scoped key, all paths in API requests are relative to the scoped folder. For example, if a key is scoped to Projects/Web, then path=images refers to Projects/Web/images. Requests outside the scope return a 403 error.
warning
Keep your API keys secret. Do not share them in public repositories or client-side code. If a key is compromised, revoke it immediately from the API Keys panel.

Response Format

All API responses return JSON with a consistent structure:

Success Response

{ "success": true, "data": { ... } }

Error Response

{ "success": false, "error": "Description of what went wrong" }

Error Codes

StatusMeaning
200Success
400Bad Request - Missing or invalid parameters
401Unauthorized - Invalid or missing API key
403Forbidden - Path traversal or access denied
404Not Found - File, folder, or resource not found
409Conflict - Resource already exists
413Payload Too Large - Storage quota exceeded

Files

GET /api/v1/locations List every place this key can reach expand_more

Returns your own files plus each shared folder and connector mount, with the virtual path to use for it. Start here instead of hard-coding mount ids.

Response

{ "success": true, "data": [ { "kind": "own", "name": "My Files", "path": "", "target": "this server", "readOnly": false }, { "kind": "shared", "name": "EMBY", "path": "__adm_807351b0", "target": "/DATA/AppData/emby/config/Movie", "readOnly": false }, { "kind": "ftp", "name": "ZHost FTP", "path": "__conn_38ab92fe", "target": "user@host:21/", "readOnly": false } ] }

kind is one of own, shared, ftp, sftp, drive — or scoped when the key is restricted to a single folder.

GET /api/v1/files List files and folders expand_more

Query Parameters

NameTypeRequiredDescription
pathstringoptionalFolder path. Empty = your root, which also lists shared folders and mounts. May start with __adm_<id> or __conn_<id>.

Entries carry mount (shared, ftp, sftp, gdrive, or null for ordinary items), mountTarget, and readOnly.

Response

{ "success": true, "data": [ { "name": "Documents", "relativePath": "Documents", "isDirectory": true, "size": 0, "formattedSize": "--", "createdAt": "2025-01-15T10:30:00", "modifiedAt": "2025-01-20T14:00:00", "extension": "", "description": "" }, { "name": "report.pdf", "relativePath": "report.pdf", "isDirectory": false, "size": 245760, "formattedSize": "240.0 KB", "createdAt": "2025-01-10T09:00:00", "modifiedAt": "2025-01-10T09:00:00", "extension": ".pdf", "description": "Monthly report" } ] }

Example

curl -H "X-API-Key: YOUR_KEY" \ "https://YOUR_HOST/api/v1/files?path=Documents"
import requests resp = requests.get( "https://YOUR_HOST/api/v1/files", headers={"X-API-Key": "YOUR_KEY"}, params={"path": "Documents"} ) print(resp.json())
const resp = await fetch( "https://YOUR_HOST/api/v1/files?path=Documents", { headers: { "X-API-Key": "YOUR_KEY" } } ); const data = await resp.json(); console.log(data);
GET /api/v1/files/download Download a file expand_more

Query Parameters

NameTypeRequiredDescription
pathstringrequiredRelative path to the file to download.

Response

Returns the raw file content with appropriate Content-Type and Content-Disposition headers.

Example

curl -H "X-API-Key: YOUR_KEY" \ -o downloaded_file.pdf \ "https://YOUR_HOST/api/v1/files/download?path=report.pdf"
import requests resp = requests.get( "https://YOUR_HOST/api/v1/files/download", headers={"X-API-Key": "YOUR_KEY"}, params={"path": "report.pdf"} ) with open("downloaded_file.pdf", "wb") as f: f.write(resp.content)
const resp = await fetch( "https://YOUR_HOST/api/v1/files/download?path=report.pdf", { headers: { "X-API-Key": "YOUR_KEY" } } ); const blob = await resp.blob(); // Use blob as needed
POST /api/v1/files/upload Upload file(s) expand_more

Query Parameters

NameTypeRequiredDescription
pathstringoptionalTarget folder path. Empty = root.

Request Body

Multipart form data with one or more files. The storage quota is checked before upload. If the upload would exceed the quota, a 413 error is returned.

Response

{ "success": true, "data": { "uploaded": ["file1.txt", "image.png"], "count": 2 } }

Example

curl -X POST \ -H "X-API-Key: YOUR_KEY" \ -F "files=@/path/to/file.txt" \ -F "files=@/path/to/image.png" \ "https://YOUR_HOST/api/v1/files/upload?path=Documents"
import requests files = [ ("files", open("file.txt", "rb")), ("files", open("image.png", "rb")) ] resp = requests.post( "https://YOUR_HOST/api/v1/files/upload", headers={"X-API-Key": "YOUR_KEY"}, params={"path": "Documents"}, files=files ) print(resp.json())
const formData = new FormData(); formData.append("files", fileInput.files[0]); const resp = await fetch( "https://YOUR_HOST/api/v1/files/upload?path=Documents", { method: "POST", headers: { "X-API-Key": "YOUR_KEY" }, body: formData } ); const data = await resp.json();
POST /api/v1/files/folder Create a folder expand_more

Query Parameters

NameTypeRequiredDescription
pathstringoptionalParent folder path. Empty = root.
namestringrequiredName of the new folder.

Response

{ "success": true, "data": { "message": "Folder created" } }

Example

curl -X POST \ -H "X-API-Key: YOUR_KEY" \ "https://YOUR_HOST/api/v1/files/folder?path=Documents&name=Projects"
import requests resp = requests.post( "https://YOUR_HOST/api/v1/files/folder", headers={"X-API-Key": "YOUR_KEY"}, params={"path": "Documents", "name": "Projects"} ) print(resp.json())
const resp = await fetch( "https://YOUR_HOST/api/v1/files/folder?path=Documents&name=Projects", { method: "POST", headers: { "X-API-Key": "YOUR_KEY" } } ); const data = await resp.json();
POST /api/v1/files/file Create an empty file expand_more

Query Parameters

NameTypeRequiredDescription
pathstringoptionalParent folder path. Empty = root.
namestringrequiredName of the new file (with extension).

Response

{ "success": true, "data": { "message": "File created" } }
PUT /api/v1/files/move Move a file or folder expand_more

Query Parameters

NameTypeRequiredDescription
fromstringrequiredSource path. May be inside a shared folder or a mount.
tostringoptionalDestination folder. Empty = your root. May be a different backend.

Response

{ "success": true, "data": { "message": "Moved successfully" } }
info
Source and destination may live on different backends — the content is streamed across. A mount root itself cannot be moved; open it and move what is inside.
PUT /api/v1/files/copy Copy a file or folder expand_more

Same shape as move, but the source is left in place. This is how you pull data out of a read-only shared folder.

Query Parameters

NameTypeRequiredDescription
fromstringrequiredSource path. Folders are copied recursively.
tostringoptionalDestination folder. Empty = your root.

Example

curl -X PUT -H "X-API-Key: YOUR_KEY" \ "https://sharewith.xyz/api/v1/files/copy?from=__conn_38ab92fe/backup.zip&to="

Response

{ "success": true, "data": { "message": "Copied successfully" } }
PUT /api/v1/files/rename Rename a file or folder expand_more

Query Parameters

NameTypeRequiredDescription
pathstringrequiredRelative path of the item to rename.
newNamestringrequiredNew name for the file/folder.

Response

{ "success": true, "data": { "message": "Renamed successfully" } }
DELETE /api/v1/files Delete a file or folder expand_more

Query Parameters

NameTypeRequiredDescription
pathstringrequiredRelative path of the file/folder to delete.
error
Deleting a folder will recursively delete all its contents. This action cannot be undone.

Response

{ "success": true, "data": { "message": "Deleted successfully" } }
GET /api/v1/files/info Get file or folder info expand_more

Query Parameters

NameTypeRequiredDescription
pathstringrequiredRelative path of the file/folder.

Response

{ "success": true, "data": { "name": "report.pdf", "path": "Documents/report.pdf", "isDirectory": false, "size": 245760, "formattedSize": "240.0 KB", "createdAt": "2025-01-10T09:00:00", "modifiedAt": "2025-01-10T09:00:00", "extension": ".pdf" } }

Account

GET /api/v1/account Get account info expand_more

Response

{ "success": true, "data": { "username": "john", "displayName": "John Doe", "role": "User", "storageUsed": 52428800, "storageUsedFormatted": "50.0 MB", "storageLimit": 1073741824, "storageLimitFormatted": "1.00 GB", "folderScope": "Full access" } }

Example

curl -H "X-API-Key: YOUR_KEY" \ "https://YOUR_HOST/api/v1/account"
import requests resp = requests.get( "https://YOUR_HOST/api/v1/account", headers={"X-API-Key": "YOUR_KEY"} ) print(resp.json())
const resp = await fetch( "https://YOUR_HOST/api/v1/account", { headers: { "X-API-Key": "YOUR_KEY" } } ); const data = await resp.json(); console.log(data);

API Keys

GET /api/v1/keys List your API keys expand_more

Response

{ "success": true, "data": [ { "id": "a1b2c3d4e5f6...", "keyPreview": "d4e5f6a1...", "name": "My Script", "folderPath": "Projects/Web", "folderScope": "Projects/Web", "createdAt": "2025-01-15T10:00:00", "lastUsedAt": "2025-01-20T14:30:00" } ] }
POST /api/v1/keys Create a new API key expand_more

Query Parameters

NameTypeRequiredDescription
namestringrequiredA friendly name for the key (e.g., "My Script").
folderstringoptionalFolder path to scope the key to (e.g., "Projects/Web"). Leave empty for full access.

Response

{ "success": true, "data": { "id": "a1b2c3d4e5f6...", "key": "d4e5f6a1-b2c3-4d5e-f6a1-b2c3d4e5f6a1", "name": "My Script", "folderPath": "Projects/Web", "folderScope": "Projects/Web", "createdAt": "2025-01-15T10:00:00" } }
warning
The full API key is only shown once upon creation. Store it securely. You cannot retrieve the full key later.
DELETE /api/v1/keys/{id} Revoke an API key expand_more

Path Parameters

NameTypeRequiredDescription
idstringrequiredThe ID of the API key to revoke.

Response

{ "success": true, "data": { "message": "Key revoked" } }

Full Code Examples

Python: Upload a file and list directory

import requests BASE = "https://YOUR_HOST/api/v1" HEADERS = {"X-API-Key": "YOUR_KEY"} # Create a folder requests.post(f"{BASE}/files/folder", headers=HEADERS, params={"path": "", "name": "uploads"}) # Upload a file with open("data.csv", "rb") as f: resp = requests.post(f"{BASE}/files/upload", headers=HEADERS, params={"path": "uploads"}, files={"files": f}) print("Upload:", resp.json()) # List files in the folder resp = requests.get(f"{BASE}/files", headers=HEADERS, params={"path": "uploads"}) for item in resp.json()["data"]: print(f" {item['name']} ({item['formattedSize']})") # Get account info resp = requests.get(f"{BASE}/account", headers=HEADERS) info = resp.json()["data"] print(f"Storage: {info['storageUsedFormatted']} / {info['storageLimitFormatted']}")

JavaScript/Node.js: Download and re-upload

const BASE = "https://YOUR_HOST/api/v1"; const HEADERS = { "X-API-Key": "YOUR_KEY" }; // List root directory const listResp = await fetch(`${BASE}/files`, { headers: HEADERS }); const files = await listResp.json(); console.log("Files:", files.data); // Download a specific file const dlResp = await fetch( `${BASE}/files/download?path=Documents/notes.txt`, { headers: HEADERS } ); const content = await dlResp.text(); console.log("Content:", content); // Rename a file await fetch( `${BASE}/files/rename?path=old_name.txt&newName=new_name.txt`, { method: "PUT", headers: HEADERS } ); // Delete a file await fetch( `${BASE}/files?path=temp/old_file.txt`, { method: "DELETE", headers: HEADERS } );

cURL: Complete workflow

# Set your API key export API_KEY="your-api-key-here" export HOST="https://YOUR_HOST" # List files in root curl -s -H "X-API-Key: $API_KEY" "$HOST/api/v1/files" | jq . # Create a new folder curl -s -X POST -H "X-API-Key: $API_KEY" \ "$HOST/api/v1/files/folder?path=&name=backups" # Upload a file curl -s -X POST -H "X-API-Key: $API_KEY" \ -F "files=@backup.tar.gz" \ "$HOST/api/v1/files/upload?path=backups" # Get file info curl -s -H "X-API-Key: $API_KEY" \ "$HOST/api/v1/files/info?path=backups/backup.tar.gz" | jq . # Move a file curl -s -X PUT -H "X-API-Key: $API_KEY" \ "$HOST/api/v1/files/move?from=backups/backup.tar.gz&to=archive" # Check account storage curl -s -H "X-API-Key: $API_KEY" "$HOST/api/v1/account" | jq .