Manage Synology NAS via DSM Web API. Authenticate, browse and manage files (FileStation), manage download tasks (DownloadStation), and query system info. Use...
---
name: synology-dsm
description: >
Manage Synology NAS via DSM Web API. Authenticate, browse and manage files
(FileStation), manage download tasks (DownloadStation), and query system info.
Use when the user mentions Synology, NAS, DSM, FileStation, DownloadStation,
or wants to interact with their NAS device.
---
# Synology DSM Skill
Interact with a Synology NAS through the DSM Web API using `curl`.
## Prerequisites
The user must have these environment variables set (or provide them inline):
- `SYNOLOGY_HOST` — NAS hostname or IP (e.g., `192.168.1.100`)
- `SYNOLOGY_PORT` — DSM port (`5000` for HTTP, `5001` for HTTPS)
- `SYNOLOGY_USER` — DSM username
- `SYNOLOGY_PASS` — DSM password
Base URL: `http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi`
> **Security**: Always prefer HTTPS (port 5001). Never hardcode credentials in commands shown to the user — use `$SYNOLOGY_PASS` references. If the user hasn't set env vars, ask them to provide connection details.
## Step 1: Authentication
Every session starts with login. Use `format=sid` to get a session ID.
### Login
```bash
curl -s "http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi/entry.cgi?\
api=SYNO.API.Auth&version=6&method=login\
&account=$SYNOLOGY_USER&passwd=$SYNOLOGY_PASS\
&session=FileStation&format=sid" | jq .
```
Response:
```json
{"data": {"sid": "YOUR_SESSION_ID"}, "success": true}
```
Save the `sid` for all subsequent requests: `SID=<value from response>`
### Logout
```bash
curl -s "http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi/entry.cgi?\
api=SYNO.API.Auth&version=6&method=logout\
&session=FileStation&_sid=$SID"
```
### 2FA Handling
If login returns error code `406`, the account has 2FA enabled. Ask the user for their OTP code, then include `&otp_code=<CODE>` in the login request.
### Session Notes
- Sessions timeout after ~15 minutes of inactivity
- If you get error code `106` (session timeout), re-authenticate
- Always logout when done to clean up sessions
## Step 2: API Discovery (Optional)
Query all available APIs on the NAS:
```bash
curl -s "http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi/query.cgi?\
api=SYNO.API.Info&version=1&method=query" | jq .
```
This returns every API name, path, and supported version range. Useful for checking what packages are installed.
## Step 3: FileStation — File Management
All FileStation calls use `_sid=$SID` for authentication.
### List shared folders (root)
```bash
curl -s "http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi/entry.cgi?\
api=SYNO.FileStation.List&version=2&method=list_share&_sid=$SID" | jq .
```
### List files in a folder
```bash
curl -s "http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi/entry.cgi?\
api=SYNO.FileStation.List&version=2&method=list\
&folder_path=/volume1/homes&additional=size,time&_sid=$SID" | jq .
```
Parameters: `folder_path` (required), `offset`, `limit`, `sort_by` (name|size|mtime), `sort_direction` (asc|desc), `additional` (size,time,perm,type)
### Create folder
```bash
curl -s "http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi/entry.cgi?\
api=SYNO.FileStation.CreateFolder&version=2&method=create\
&folder_path=/volume1/homes&name=new_folder&_sid=$SID" | jq .
```
### Rename file or folder
```bash
curl -s "http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi/entry.cgi?\
api=SYNO.FileStation.Rename&version=2&method=rename\
&path=/volume1/homes/old_name&name=new_name&_sid=$SID" | jq .
```
### Delete file or folder
```bash
curl -s "http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi/entry.cgi?\
api=SYNO.FileStation.Delete&version=2&method=delete\
&path=/volume1/homes/unwanted_file&_sid=$SID" | jq .
```
For large deletions, use `method=start` to get a task ID, then poll with `method=status&taskid=<id>`.
### Upload file
```bash
curl -s -X POST \
-F "api=SYNO.FileStation.Upload" \
-F "version=2" \
-F "method=upload" \
-F "path=/volume1/homes" \
-F "overwrite=true" \
-F "file=@/local/path/to/file.txt" \
-F "_sid=$SID" \
"http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi/entry.cgi"
```
### Download file
```bash
curl -s -o output_file.txt \
"http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi/entry.cgi?\
api=SYNO.FileStation.Download&version=2&method=download\
&path=/volume1/homes/file.txt&mode=download&_sid=$SID"
```
### Search files
```bash
# Start search
curl -s "http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi/entry.cgi?\
api=SYNO.FileStation.Search&version=2&method=start\
&folder_path=/volume1&pattern=*.pdf&_sid=$SID" | jq .
# Returns taskid
# Get results
curl -s "http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi/entry.cgi?\
api=SYNO.FileStation.Search&version=2&method=list\
&taskid=<TASK_ID>&_sid=$SID" | jq .
```
### Get file/folder info
```bash
curl -s "http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi/entry.cgi?\
api=SYNO.FileStation.List&version=2&method=getinfo\
&path=/volume1/homes/file.txt&additional=size,time&_sid=$SID" | jq .
```
For full FileStation API reference, see [references/filestation-api.md](references/filestation-api.md).
## Step 4: DownloadStation — Download Management
### Get DownloadStation info
```bash
curl -s "http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi/entry.cgi?\
api=SYNO.DownloadStation.Info&version=1&method=getinfo&_sid=$SID" | jq .
```
### List all download tasks
```bash
curl -s "http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi/entry.cgi?\
api=SYNO.DownloadStation.Task&version=1&method=list\
&additional=transfer&_sid=$SID" | jq .
```
The `additional=transfer` parameter includes download/upload speed and progress.
### Add download task (URL)
```bash
curl -s -X POST \
-d "api=SYNO.DownloadStation.Task&version=1&method=create\
&uri=https://example.com/file.zip&_sid=$SID" \
"http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi/entry.cgi"
```
### Add download task (torrent file)
```bash
curl -s -X POST \
-F "api=SYNO.DownloadStation.Task" \
-F "version=1" \
-F "method=create" \
-F "file=@/local/path/to/file.torrent" \
-F "_sid=$SID" \
"http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi/entry.cgi"
```
### Pause / Resume / Delete tasks
```bash
# Pause
curl -s "http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi/entry.cgi?\
api=SYNO.DownloadStation.Task&version=1&method=pause\
&id=<TASK_ID>&_sid=$SID"
# Resume
curl -s "http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi/entry.cgi?\
api=SYNO.DownloadStation.Task&version=1&method=resume\
&id=<TASK_ID>&_sid=$SID"
# Delete (force_complete=false keeps downloaded files)
curl -s "http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi/entry.cgi?\
api=SYNO.DownloadStation.Task&version=1&method=delete\
&id=<TASK_ID>&force_complete=false&_sid=$SID"
```
Multiple task IDs can be comma-separated: `&id=task1,task2,task3`
For full DownloadStation API reference, see [references/downloadstation-api.md](references/downloadstation-api.md).
## Step 5: System Info
### Get DSM system information
```bash
curl -s "http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi/entry.cgi?\
api=SYNO.DSM.Info&version=2&method=getinfo&_sid=$SID" | jq .
```
Returns: model, RAM, serial, DSM version, uptime, temperature.
### Get storage/volume info
```bash
curl -s "http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi/entry.cgi?\
api=SYNO.Storage.CGI.Storage&version=1&method=load_info&_sid=$SID" | jq .
```
### Get network info
```bash
curl -s "http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi/entry.cgi?\
api=SYNO.DSM.Network&version=1&method=list&_sid=$SID" | jq .
```
## Error Handling
All API responses follow: `{"success": true/false, "data": {...}, "error": {"code": N}}`
### Common error codes
| Code | Meaning | Action |
|------|---------|--------|
| 100 | Unknown error | Retry once |
| 101 | Bad request | Check parameters |
| 102 | No such API | Package not installed |
| 103 | No such method | Check API version |
| 104 | Version not supported | Use lower version |
| 105 | No permission | Check user privileges |
| 106 | Session timeout | Re-authenticate |
| 107 | Session interrupted | Re-authenticate |
### Auth-specific error codes
| Code | Meaning |
|------|---------|
| 400 | Incorrect password |
| 401 | Account disabled |
| 402 | Permission denied |
| 406 | 2FA code required |
For full error code reference, see [references/error-codes.md](references/error-codes.md).
## Workflow Example
A typical session:
1. Login and capture SID
2. Perform operations (list files, add downloads, etc.)
3. Logout when done
Always check `"success": true` in responses before proceeding. On error 106/107, re-login automatically.
don't have the plugin yet? install it then click "run inline in claude" again.
interact with a synology NAS through the DSM web API using curl. this skill handles authentication via login/logout, file management through FileStation (list, create, rename, delete, upload, download, search), download task management through DownloadStation (add, pause, resume, delete), and system queries (DSM info, storage, network). use this skill when the user needs to manage files on their NAS, track downloads, or check system status. requires network access to the NAS and valid DSM credentials.
environment variables (set these before running, or ask the user to provide them inline):
SYNOLOGY_HOST - NAS hostname or IP address, e.g. 192.168.1.100 or nas.localSYNOLOGY_PORT - DSM listening port: 5000 for HTTP, 5001 for HTTPS. defaults to 5000 if omittedSYNOLOGY_USER - DSM username with file/download permissionsSYNOLOGY_PASS - DSM password (never hardcode in command output; use $SYNOLOGY_PASS variable references)external connection:
http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi (or HTTPS if port 5001). must be reachable from the execution environment. network timeouts typically occur after 30 seconds of inactivity.optional parameters (for specific operations):
SID - session ID obtained after successful login. valid for ~15 minutes of inactivity before auto-expirationTASK_ID - returned by long-running operations like search or multi-file delete, used to poll statusOTP_CODE - 6-digit code if 2FA is enabled on the accountsecurity notes:
$SYNOLOGY_PASS variable references in examples; never show the actual passwordinput: SYNOLOGY_HOST, SYNOLOGY_PORT, SYNOLOGY_USER, SYNOLOGY_PASS
output: SID (session ID string) or error code
run login request:
curl -s "http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi/entry.cgi?\
api=SYNO.API.Auth&version=6&method=login\
&account=$SYNOLOGY_USER&passwd=$SYNOLOGY_PASS\
&session=FileStation&format=sid" | jq .
expected response on success:
{"data": {"sid": "YOUR_SESSION_ID"}, "success": true}
extract the sid value and store it: SID=<value from response>
common outcomes at this step:
success: true with sid - login succeeded, proceed to next step400 - incorrect password, ask user to verify credentials401 - account is disabled on the NAS, contact NAS admin402 - user lacks API permission, enable in DSM control panel406 - 2FA is enabled, proceed to 2FA handling (see decision points)input: SYNOLOGY_HOST, SYNOLOGY_PORT, SID
output: JSON list of all available API endpoints on the NAS
to check which packages/features are installed:
curl -s "http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi/query.cgi?\
api=SYNO.API.Info&version=1&method=query" | jq .
this is useful for determining if DownloadStation or other packages are present before attempting operations. skip this step if you know which APIs you need.
input: SYNOLOGY_HOST, SYNOLOGY_PORT, SID, (folder_path, file path, or search pattern as needed)
output: JSON response with file list, info, or confirmation of action
curl -s "http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi/entry.cgi?\
api=SYNO.FileStation.List&version=2&method=list_share&_sid=$SID" | jq .
returns: all shared folders (e.g. /volume1/homes, /volume1/downloads)
curl -s "http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi/entry.cgi?\
api=SYNO.FileStation.List&version=2&method=list\
&folder_path=/volume1/homes&additional=size,time&_sid=$SID" | jq .
parameters:
folder_path (required) - path to list, e.g. /volume1/homesoffset (optional) - start position, default 0limit (optional) - max results, default 100sort_by (optional) - name, size, or mtimesort_direction (optional) - asc or descadditional (optional) - comma-separated: size, time, perm, typecurl -s "http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi/entry.cgi?\
api=SYNO.FileStation.CreateFolder&version=2&method=create\
&folder_path=/volume1/homes&name=new_folder&_sid=$SID" | jq .
curl -s "http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi/entry.cgi?\
api=SYNO.FileStation.Rename&version=2&method=rename\
&path=/volume1/homes/old_name&name=new_name&_sid=$SID" | jq .
curl -s "http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi/entry.cgi?\
api=SYNO.FileStation.Delete&version=2&method=delete\
&path=/volume1/homes/unwanted_file&_sid=$SID" | jq .
for large deletions (multiple files or folders), use method=start first to get a taskid, then poll method=status&taskid=<id> until complete.
curl -s -X POST \
-F "api=SYNO.FileStation.Upload" \
-F "version=2" \
-F "method=upload" \
-F "path=/volume1/homes" \
-F "overwrite=true" \
-F "file=@/local/path/to/file.txt" \
-F "_sid=$SID" \
"http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi/entry.cgi"
parameters:
path (required) - destination folder on NASoverwrite (optional) - true or false, default falsefile - local file to uploadcurl -s -o output_file.txt \
"http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi/entry.cgi?\
api=SYNO.FileStation.Download&version=2&method=download\
&path=/volume1/homes/file.txt&mode=download&_sid=$SID"
output is binary file content, redirected to local filename.
input: search pattern (wildcard or regex), folder to search
output: task ID (from start), then results (from list)
start search:
curl -s "http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi/entry.cgi?\
api=SYNO.FileStation.Search&version=2&method=start\
&folder_path=/volume1&pattern=*.pdf&_sid=$SID" | jq .
returns taskid. then retrieve results:
curl -s "http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi/entry.cgi?\
api=SYNO.FileStation.Search&version=2&method=list\
&taskid=<TASK_ID>&_sid=$SID" | jq .
may need to poll multiple times if search is still in progress (check "finished": true).
curl -s "http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi/entry.cgi?\
api=SYNO.FileStation.List&version=2&method=getinfo\
&path=/volume1/homes/file.txt&additional=size,time&_sid=$SID" | jq .
returns: size, modified time, permissions, type, etc.
input: SYNOLOGY_HOST, SYNOLOGY_PORT, SID, (download URL or torrent file, task IDs)
output: download list, task info, or task creation confirmation
prerequisite: DownloadStation package must be installed on the NAS. verify with step 2 (API query) if unsure.
curl -s "http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi/entry.cgi?\
api=SYNO.DownloadStation.Info&version=1&method=getinfo&_sid=$SID" | jq .
returns: enabled status, destination folder, max connections, etc.
curl -s "http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi/entry.cgi?\
api=SYNO.DownloadStation.Task&version=1&method=list\
&additional=transfer&_sid=$SID" | jq .
includes download/upload speed and progress percentage with &additional=transfer.
curl -s -X POST \
-d "api=SYNO.DownloadStation.Task&version=1&method=create\
&uri=https://example.com/file.zip&_sid=$SID" \
"http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi/entry.cgi"
returns: taskid if successful
curl -s -X POST \
-F "api=SYNO.DownloadStation.Task" \
-F "version=1" \
-F "method=create" \
-F "file=@/local/path/to/file.torrent" \
-F "_sid=$SID" \
"http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi/entry.cgi"
returns: taskid if successful
curl -s "http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi/entry.cgi?\
api=SYNO.DownloadStation.Task&version=1&method=pause\
&id=<TASK_ID>&_sid=$SID"
curl -s "http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi/entry.cgi?\
api=SYNO.DownloadStation.Task&version=1&method=resume\
&id=<TASK_ID>&_sid=$SID"
curl -s "http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi/entry.cgi?\
api=SYNO.DownloadStation.Task&version=1&method=delete\
&id=<TASK_ID>&force_complete=false&_sid=$SID"
parameters:
id - task ID (comma-separated for multiple: task1,task2,task3)force_complete - false keeps downloaded files; true cleans them upinput: SYNOLOGY_HOST, SYNOLOGY_PORT, SID
output: JSON with system specs and status
curl -s "http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi/entry.cgi?\
api=SYNO.DSM.Info&version=2&method=getinfo&_sid=$SID" | jq .
returns: NAS model, RAM, serial number, DSM version, uptime, system temperature
curl -s "http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi/entry.cgi?\
api=SYNO.Storage.CGI.Storage&version=1&method=load_info&_sid=$SID" | jq .
returns: volume names, total capacity, used space, RAID status
curl -s "http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi/entry.cgi?\
api=SYNO.DSM.Network&version=1&method=list&_sid=$SID" | jq .
returns: IP addresses, MAC addresses, interfaces (eth0, eth1, etc.)
input: SYNOLOGY_HOST, SYNOLOGY_PORT, SID
output: logout confirmation
when done with all operations, always logout to clean up the session:
curl -s "http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi/entry.cgi?\
api=SYNO.API.Auth&version=6&method=logout\
&session=FileStation&_sid=$SID"
if logout fails, the session will auto-expire after ~15 minutes of inactivity anyway.
if the user has not provided env vars:
SYNOLOGY_HOST, SYNOLOGY_PORT, SYNOLOGY_USER, SYNOLOGY_PASS before proceedingif login fails with error code 406 (2FA required):
&otp_code=<CODE> appended to the login URLif any API call returns error code 106 (session timeout) or 107 (session interrupted):
if FileStation or DownloadStation APIs return error code 102 (no such API):
if a file upload returns error code 105 (no permission):
if a download task returns error code 105 or 101:
if network timeout occurs (curl hangs > 30 seconds):
--max-time 60 to curl)if a search or multi-file operation returns a taskid:
method=status&taskid=<id> in a loop until "finished": trueif the user wants to list files but does not specify a folder path:
all API responses follow this format:
{
"success": true,
"data": { /* varies by endpoint */ },
"error": { "code": 0 }
}
login response (success):
{"data": {"sid": "SESSION_ID_STRING"}, "success": true}
file list response (success):
{
"success": true,
"data": {
"files": [
{"name": "file.txt", "path": "/volume1/homes/file.txt", "isdir": false, "size": 1024, "mtime": 1234567890},
{"name": "folder", "path": "/volume1/homes/folder", "isdir": true}
],
"total": 42
}
}
download list response (success):
{
"success": true,
"data": {