Install
openclaw skills install synology-dsmManage 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.
openclaw skills install synology-dsmInteract with a Synology NAS through the DSM Web API using curl.
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 usernameSYNOLOGY_PASS — DSM passwordBase URL: http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi
Security: Always prefer HTTPS (port 5001). Never hardcode credentials in commands shown to the user — use
$SYNOLOGY_PASSreferences. If the user hasn't set env vars, ask them to provide connection details.
Every session starts with login. Use format=sid to get a session ID.
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:
{"data": {"sid": "YOUR_SESSION_ID"}, "success": true}
Save the sid for all subsequent requests: SID=<value from response>
curl -s "http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi/entry.cgi?\
api=SYNO.API.Auth&version=6&method=logout\
&session=FileStation&_sid=$SID"
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.
106 (session timeout), re-authenticateQuery all available APIs on the NAS:
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.
All FileStation calls use _sid=$SID for authentication.
curl -s "http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi/entry.cgi?\
api=SYNO.FileStation.List&version=2&method=list_share&_sid=$SID" | jq .
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)
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 .
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, use method=start to get a task ID, then poll with method=status&taskid=<id>.
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"
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"
# 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 .
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.
curl -s "http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi/entry.cgi?\
api=SYNO.DownloadStation.Info&version=1&method=getinfo&_sid=$SID" | jq .
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.
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"
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
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.
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.
curl -s "http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi/entry.cgi?\
api=SYNO.Storage.CGI.Storage&version=1&method=load_info&_sid=$SID" | jq .
curl -s "http://$SYNOLOGY_HOST:$SYNOLOGY_PORT/webapi/entry.cgi?\
api=SYNO.DSM.Network&version=1&method=list&_sid=$SID" | jq .
All API responses follow: {"success": true/false, "data": {...}, "error": {"code": N}}
| 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 |
| 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.
A typical session:
Always check "success": true in responses before proceeding. On error 106/107, re-login automatically.