Exploring the Synology PhotoStation API
I’ve started to use PhotoStation on my Synology NAS device at home to organize my photos and provide easy means to access remotely. I have been quite pleased overall, especially with the integration with the DS Photo app which can sync photos from an iPhone’s camera roll to the Synology NAS.
I was looking for an automated way to sort my photos into a hierarchy of folders by date. Unable to find a built-in way to do this or any public documentation for the PhotoStation API, I set about to explore the API and see what I could figure out.
Synology API Structure
While the Synology developer documentation site does not have any API reference for PhotoStation, it does contain information on some of the other REST APIs from Synology which proved useful to understanding the basic workings of the PhotoStation API. For example, in the documentation for FileStation one can see how the general request/response workflow is for a Synology application.
Each application has several named APIs (eg. SYNO.FileStation.Info
or SYNO.FileStation.List
)
that provide different functionality. To make a request against one of these APIs,
one must first find its endpoint (the path portion of the URL) and then send an
HTTP
request with the following parameters:
api
- API namemethod
- name of method being invokedversion
- version of API being accessedsid
- session ID received during login step
The API endpoints and available versions can be found by querying the
SYNO.API.Info
API at http://mysynology:5000/webapi/query.cgi
. Sending a
request with the above parameters (sans sid
) and additional parameter
query=all
will return a list of all available APIs from the NAS device.
Unfortunately, there are no PhotoStation APIs listed in the response. This, as it turns out, is because the PhotoStation API is handled differently, as we see below.
Listening on the Wire
Since the FileStation documentation didn’t lead to the list of APIs as I hoped,
the next step was to examine the network traffic between the browser and NAS when running
PhotoStation. Since the web interface for PhotoStation does not use HTTPS by default, it is rather
easy to use a packet tracing tool like wireshark to
examine the network traffic between my browser and the NAS system. By setting
a capture filter to "host 10.20.30.40 and port 80"
(the IP of my NAS device) and then
using a display filter "http"
, I could start to see the HTTP traffic between the
javascript UI running in my browser and the PhotoStation backend.
Alternatively, one could use developer tools in the
browser itself to show the network requests and responses being sent from a particular session.
The built-in browser tools can be easier to understand than wireshark but only works (obviously)
when using that browser. Later on, when doing testing from the command line with curl
wireshark is useful (though curl
too can display some additional info with the -v
flag)
The first thing to notice when looking at the network traffic from a browser is that the
all the requests are going to port 80 on the NAS and not port 5000 where the DSM GUI operates.
Secondly, there appeared to be two broad sets of requests - those going to files in /photo
and
those accessing files in /photo/webapi
. The first are all the files for displaying and
running the PhotoStation GUI. The latter set are requests to the backend API. Finally, the
observed /photo/webapi
calls all (or mostly all) appeared to have .php
suffixes.
Given this, a quick trial shows that there is a separate API info endpoint for PhotoStation that can be accessed as follows:
curl 'http://mysynology/photo/webapi/query.php?api=SYNO.API.Info&version=1&method=query&query=all'`
The response (truncated below, see full response here) lists approximately 30 separate APIs along with their path (endpoint) and versions:
{
"success": true,
"data": {
"SYNO.PhotoStation.Auth": {
"path": "auth.php",
"minVersion": 1,
"maxVersion": 1
},
"SYNO.PhotoStation.Info": {
"path": "info.php",
"minVersion": 1,
"maxVersion": 2
},
"SYNO.PhotoStation.Album": {
"path": "album.php",
"minVersion": 1,
"maxVersion": 1
},
... truncated ...
"SYNO.API.Info": {
"path": "query.php",
"minVersion": 1,
"maxVersion": 1
}
}
}
Understanding Authentication
Having made some progress, the next step was to tackle authentication. None of the
backend requests I observed had a sid
or session
parameter mentioned in the
FileStation documentation, so it was unclear how an authenticated session was
communicated to the backend.
I experimented some with curl
to try to mimic the queries that were being
sent by my browser but would get different results or errors because it
did not recognize my session. Even copying the SynoToken
parameter that
was sent on some backend queries did not help.
In the end, I discovered that session ID was being sent as a cookie (with
the key PHPSESSID
) on each request. Once I started to send a similar cookie
in curl
(with the -b KEY=VALUE
option), I could start getting the
same responses via curl
as from the browser.
However, I still needed to understand how to start a session (ie. login) rather
than piggyback on an existing session. The login
method of SYNO.PhotoStation.Auth
certainly seemed promising but without knowing the parameters to send, it
doesn’t do much good. Fortunately, I was able to log out of PhotoStation and
then login again while tracing the network and was able to see the needed
parameters (username
and password
).
Sending my credentials to this API returned (among other items) a session ID that I could use to send in cookie form on subsequent requests.
Diving into the Code
Tracing requests and responses can be informative but does not always give insight into the meaning of parameters or even the existence of parameters not being used by the GUI. Thankfully, I was able to also dig into the PhotoStation code some.
Synology’s NAS products are based on Linux and they provide local shell access through
ssh
. With this, one can log into the NAS and explore what is going on. Unfortunately
it takes a while to find where things are.
Synology Packaging
Synology applications are distributed in packages, bundled archives of files that provide
the necessary code and data to run an application. When installed on a Synology machine
these packages are unpacked into a subfolder in /var/packages
named for the
application, for instance /var/packages/PhotoStation
.
Within this package directory there are a number of files and directories that pertain
to the packaging itself (eg. versioning, install/upgrade/remove scripts, etc…) while
the core application code and data are saved in a target
directory.
Synology only allocates a few GB to its operating system, so this target
directory is
typically a symlink to another directory within one of the storage volumes, /volume1/@appstore/PhotoStation
in this case. Within this directory are all the files used by PhotoStation – all 3700+ of them!
While a daunting number to examine, there is a silver lining … one reason why there are
so many files is that the backend REST API is written in PHP, and thus is present in
readable code on the NAS device (unlike other applications that might have only compiled binaries
installed).
Exploring photo/webapi
Directory
The photo/webapi
directory within /var/packages/PhotoStation/target
contains the bulk
of the PHP code used in the backend of PhotoStation. These are the files that the
webserver calls to handle requests. For instance, a request to http://mysynology/photo/webapi/auth.php
will run the PHP script contained in photo/webapi/auth.php
. Knowing this, one can explore
the individual code for each command.
In addition to these PHP files, there are additional files located in photo/include
and photo/webapi/sdk
that may be referenced by the PHP files in photo/webapi
.
Finally, there is a file named photo/webapi/PhotoStation.api
that provides the same
information as the SYNO.API.Info
query (API name, path and versions) but also provides
a list of all the methods associated with an API!
Here is a small subset of the APIs defined in photo/webapi/PhotoStation.api
:
{
"SYNO.PhotoStation.Auth": {
"path": "auth.php",
"minVersion": 1,
"maxVersion": 1,
"methods": {
"1": [
"login",
"photo_login",
"logout",
"checkauth"
]
}
},
"SYNO.PhotoStation.Info": {
"path": "info.php",
"minVersion": 1,
"maxVersion": 2,
"methods": {
"2": [
"getinfo",
"getexternalip"
],
"1": [
"getinfo"
]
}
},
"SYNO.PhotoStation.Album": {
"path": "album.php",
"minVersion": 1,
"maxVersion": 1,
"methods": {
"1": [
"list",
"getinfo",
"create",
"edit",
"delete",
"arrangeitem",
"move",
"cleararrangeitem",
"cancel"
]
}
},
...
}
Documenting the API
With this information, wireshark and time to experiment and test, I was able to gradually understand some of the key parts of the PhotoStation API - notably those parts associated with creating albums, moving photos and the like. Initially, I was taking notes in a small text file but soon I was inspired to take it a step further and started my own unofficial Synology PhotoStation API documentation using the wonderful TechDoc Hugo theme.
I’ve tried to lay out the basics for using the API in the Getting Started section. This should, hopefully, allow others to get up to speed with accessing the API directly. The API Reference section provides detailed information on a limited number of APIs (as I have been able to examine and document them). Within this section, I provide information on the request parameters and the responses for various methods of the APIs.
I don’t expect I will completely document the entire API, as frankly there are only a limit subset of calls required for my immediate project. However, I as I understand the API more, I will try to update this documentation for others. I’ve hosted the documentation on GitHub at https://github.com/jamesbo13/syno-photostation-api and would be open to any pull request improvements.