Skip to content

Instantly share code, notes, and snippets.

@anthonydahanne
Last active July 20, 2019 02:21
Show Gist options
  • Save anthonydahanne/4583444 to your computer and use it in GitHub Desktop.
Save anthonydahanne/4583444 to your computer and use it in GitHub Desktop.
*unofficial* Documentation of the Synology PhotoStation remote api

Logging in :

POST /photo/mApp/ajax/login.php HTTP/1.1
Content-Length: 113
Content-Type: application/x-www-form-urlencoded
Host: 192.168.1.2:80
Connection: Keep-Alive

action=login&username=user&passwd=password&video_formats=%5B%5B%22*%22%2C0%2C0%2C1280%2C720%2C0%2C%5B%5D%5D%5D
HTTP/1.1 200 OK
Date: Fri, 18 Jan 2013 14:50:01 GMT
Server: Apache/2.2.22 (Unix) PHP/5.3.15
X-Powered-By: PHP/5.3.15
Set-Cookie: PHPSESSID=0ge01bhrgtsmn1gvabshe5i9n7; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Vary: Accept-Encoding
Content-Length: 149
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html

{"success":true,"isAdmin":false,"isSearchEnabled":true,"allow_orig":false,"version":"2668","packageVersion":{"major":"5","minor":"2","build":"2306"}}

Notes :

the string : %5B%5B%22*%22%2C0%2C0%2C1280%2C720%2C0%2C%5B%5D%5D%5D is the urlencoded version of : [["*",0,0,1280,720,0,[]]]

If the login fails, the result will be :

{"success":"login_error_account","isAdmin":false,"isSearchEnabled":true,"allow_orig":true,"version":"2668","packageVersion":{"major":"5","minor":"2","build":"2306"}}

Curl command :

curl -c cookies.txt -d "action=login&username=user&passwd=password&video_formats=%5B%5B%22*%22%2C0%2C0%2C1280%2C720%2C0%2C%5B%5D%5D%5D"-i "http://192.168.1.2/photo/mApp/ajax/login.php"

Retrieving the list of root albums :

GET /photo/mApp/get_root_album_list.php?albumsPerLoad=24&page=1&client=android_app&refresh=1&mostRecent=TRUE HTTP/1.1
Host: 192.168.1.2:80
Connection: Keep-Alive
Cookie: PHPSESSID=0ge01bhrgtsmn1gvabshe5i9n7
Cookie2: $Version=1
HTTP/1.1 200 OK
Date: Fri, 18 Jan 2013 14:57:35 GMT
Server: Apache/2.2.22 (Unix) PHP/5.3.15
X-Powered-By: PHP/5.3.15
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Vary: Accept-Encoding
Content-Length: 5432
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html

{
    "albumCount": 2, 
    "albums": [
        {
            "bigCover": {
                "height": 240, 
                "src": "/photo/images/loading_big.png", 
                "width": 320
            }, 
            "cover": {
                "height": 120, 
                "src": "/photo/convert.php?dir=7061735f73617576652f31322d612d6d6f6e747265616c2d6465632d32303132&name=612d6d6f6e747265616c2d6465632d323031325f3230313231323238543039343634342e4a5047&type=0&v=0", 
                "width": 90
            }, 
            "desc": "", 
            "dir": "", 
            "dirName": "", 
            "hit": 0, 
            "isPublic": true, 
            "itemType": 0, 
            "name": "", 
            "photos": 80, 
            "showTitle": "", 
            "title": "[__MostRecentPhotos__]", 
            "uploadable": false
        }, 
        {
            "bigCover": {
                "height": 240, 
                "src": "/photo/images/loading_big.png", 
                "width": 320
            }, 
            "cover": {
                "height": 240, 
                "src": "/photo/images/loading_big.png", 
                "width": 320
            }, 
            "desc": "", 
            "dir": "49736162656c6c6546616d696c6c65416d6973", 
            "dirName": "Plouf", 
            "hit": "0", 
            "itemType": 0, 
            "name": "Plouf", 
            "permissionType": 1, 
            "photos": 0, 
            "showTitle": "Plouf", 
            "title": "", 
            "uploadable": false
        }
    ], 
    "isGuestLogin": false
}

Notes :

if the root album is empty :

{"albums":[],"albumCount":0,"isGuestLogin":false} 

will be returned

Curl command :

curl -b cookies.txt -i "http://192.168.1.2/photo/mApp/get_root_album_list.php?albumsPerLoad=24&page=1&client=android_app&mostRecent=TRUE"

Downloading any image :

GET /photo/convert.php?dir=616d6973&name=6661625f64616e735f6c655f73616c6f6e5f61755f7075795f323030332e4a5047&type=4&v=0 HTTP/1.1
Host: 192.168.1.2:80
Connection: Keep-Alive
Cookie: PHPSESSID=0ge01bhrgtsmn1gvabshe5i9n7
Cookie2: $Version=1
HTTP/1.1 200 OK
Date: Fri, 18 Jan 2013 15:00:25 GMT
Server: Apache/2.2.22 (Unix) PHP/5.3.15
X-Powered-By: PHP/5.3.15
Last-Modified: Sat, 25 Jun 2011 20:06:36 GMT
Cache-Control: max-age=604800
Content-Disposition: inline; filename="fab_dans_le_salon_au_puy_2003.JPG"
Accept-Ranges: bytes
Content-Range: bytes 0-19739/19740
Content-Length: 19740
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: image/jpeg

[...]

Loading an album content :

GET /photo/mApp/get_album_content.php?dir=7061735f7361757665&page=1&client=android_app&refresh=1&sort_type=name&sort_order=asc HTTP/1.1
Host: 192.168.1.2:80
Connection: Keep-Alive
Cookie: PHPSESSID=0ge01bhrgtsmn1gvabshe5i9n7
Cookie2: $Version=1
HTTP/1.1 200 OK
Date: Fri, 18 Jan 2013 15:01:51 GMT
Server: Apache/2.2.22 (Unix) PHP/5.3.15
X-Powered-By: PHP/5.3.15
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Vary: Accept-Encoding
Keep-Alive: timeout=5, max=99
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: text/html

{
    "isGuestLogin": false, 
    "itemCount": 58, 
    "items": [
        {
            "bigCover": {
                "height": 240, 
                "src": "/photo/images/loading_big.png", 
                "width": 320
            }, 
            "cover": {
                "height": 90, 
                "src": "/photo/convert.php?dir=7061735f73617576652f7a75726963685f6a617a6f6f6e5f66696e5f6a75696e5f32303039&name=7a75726963682d6a617a6f6f6e2d32332d30362d323030395f30326835356d3430732e6a7067&type=0&v=0", 
                "width": 120
            }, 
            "desc": "", 
            "dir": "7061735f73617576652f7a75726963685f6a617a6f6f6e5f66696e5f6a75696e5f32303039", 
            "dirName": "pif", 
            "hit": "0", 
            "itemType": 0, 
            "name": "bing/pif", 
            "permissionType": 1, 
            "photos": 0, 
            "showTitle": "pif", 
            "title": "", 
            "uploadable": true
        }, 
        {
            "GPSInfo": null, 
            "bigCover": {
                "height": 240, 
                "src": "/photo/convert.php?dir=7061735f7361757665&name=616e74686f6e795f7665727665696e652d736175636973736f6e2d6d6f6e747265616c2e6a7067&type=4&v=0", 
                "width": 320
            }, 
            "bigThumb": {
                "height": 480, 
                "src": "/photo/convert.php?dir=7061735f7361757665&name=616e74686f6e795f7665727665696e652d736175636973736f6e2d6d6f6e747265616c2e6a7067&type=1&v=0", 
                "width": 640
            }, 
            "cover": {
                "height": 90, 
                "src": "/photo/convert.php?dir=7061735f7361757665&name=616e74686f6e795f7665727665696e652d736175636973736f6e2d6d6f6e747265616c2e6a7067&type=0&v=0", 
                "width": 120
            }, 
            "desc": "", 
            "isCommentable": true, 
            "itemType": 1, 
            "largeThumb": {
                "height": 480, 
                "src": "/photo/convert.php?dir=7061735f7361757665&name=616e74686f6e795f7665727665696e652d736175636973736f6e2d6d6f6e747265616c2e6a7067&type=12&v=0", 
                "width": 640
            }, 
            "path": "/volume1/photo/bing/montreal.jpg", 
            "resolutionx": 640, 
            "resolutiony": 480, 
            "showTitle": "montreal", 
            "timetaken": "2011-06-23 06:19:32", 
            "title": "montreal", 
            "xLargeThumb": {
                "height": 480, 
                "src": "/photo/convert.php?dir=7061735f7361757665&name=616e74686f6e795f7665727665696e652d736175636973736f6e2d6d6f6e747265616c2e6a7067&type=12&v=0", 
                "width": 640
            }
        }        
    ], 
    "subAlbumCount": 54, 
    "success": true, 
    "totalVideoCount": 0, 
    "videoCount": 0
}

Uploading a file (photo/video) :

POST /photo/mApp/ajax/uploader.php?action=photo_upload HTTP/1.1
Transfer-Encoding: chunked
Content-Type: multipart/form-data; boundary=wpvshMMtkjn_aVdzLMUXOdnmZ8B4dphN1Xucvx
Host: 192.168.1.2:80
Connection: Keep-Alive
Cookie: PHPSESSID=0ge01bhrgtsmn1gvabshe5i9n7
Cookie2: $Version=1

c1
--wpvshMMtkjn_aVdzLMUXOdnmZ8B4dphN1Xucvx
Content-Disposition: form-data; name="upload_file_type"
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 8bit

file_type_video
ce

--wpvshMMtkjn_aVdzLMUXOdnmZ8B4dphN1Xucvx
Content-Disposition: form-data; name="album"
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 8bit

plif/plaf
bc

--wpvshMMtkjn_aVdzLMUXOdnmZ8B4dphN1Xucvx
Content-Disposition: form-data; name="upload_client"
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 8bit

android_app
a9

--wpvshMMtkjn_aVdzLMUXOdnmZ8B4dphN1Xucvx
Content-Disposition: form-data; name="title"
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 8bit


af

--wpvshMMtkjn_aVdzLMUXOdnmZ8B4dphN1Xucvx
Content-Disposition: form-data; name="description"
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 8bit


b6

--wpvshMMtkjn_aVdzLMUXOdnmZ8B4dphN1Xucvx
Content-Disposition: form-data; name="upload_file_ext"
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 8bit

mp4
b3

--wpvshMMtkjn_aVdzLMUXOdnmZ8B4dphN1Xucvx
Content-Disposition: form-data; name="is_last_item"
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 8bit

yes
b0

--wpvshMMtkjn_aVdzLMUXOdnmZ8B4dphN1Xucvx
Content-Disposition: form-data; name="lat"
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 8bit

43.516944
b1

--wpvshMMtkjn_aVdzLMUXOdnmZ8B4dphN1Xucvx
Content-Disposition: form-data; name="lng"
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 8bit

-72.560535
10f1

--wpvshMMtkjn_aVdzLMUXOdnmZ8B4dphN1Xucvx
Content-Disposition: form-data; name="file"; filename="file:///storage/emulated/0/DCIM/Camera/VID_20130113_172123.mp4"
Content-Type: application/octet-stream
Content-Transfer-Encoding: binary
HTTP/1.1 200 OK
Date: Fri, 18 Jan 2013 15:07:09 GMT
Server: Apache/2.2.22 (Unix) PHP/5.3.15
X-Powered-By: PHP/5.3.15
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Vary: Accept-Encoding
Content-Length: 16
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html

{"success":true}

Notes :

if the session is lost, the result is : {"success":"error_not_login"} (doh !)

Curl command :

curl -b cookies.txt  -F "upload_file_type=file_type_photo" -F "album=plif/plaf"  -F "upload_client=android_app" -F "title=" " -F "upload_file_ext=png" -F "is_last_item=yes" -F "lat=43.516944" -F "lng=-72.560535" -F "[email protected]"   -i "http://192.168.1.2/photo/mApp/ajax/uploader.php?action=photo_upload"

Creating a new album :

POST /photo/mApp/ajax/uploader.php?action=album_create HTTP/1.1
Content-Length: 85
Content-Type: application/x-www-form-urlencoded
Host: 192.168.1.2:80
Connection: Keep-Alive
Cookie: PHPSESSID=e7odt417egqmb87u7tjhm4smr3
Cookie2: $Version=1
X-Forwarded-For: 192.168.1.25

parent_dir_path=bing%2Fbam&album=plof&album_permission=0
HTTP/1.1 200 OK
Date: Sat, 19 Jan 2013 01:20:30 GMT
Server: Apache/2.2.22 (Unix) PHP/5.3.15
X-Powered-By: PHP/5.3.15
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Vary: Accept-Encoding
Content-Length: 16
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html

{"success":true}

Curl command :

curl -b cookies.txt  -d "parent_dir_path=dir/subdir&album=bing&album_permission=0" -i "http://192.168.1.2/photo/mApp/ajax/uploader.php?action=album_create"
@friesoft
Copy link

Did you do anything further with this information? I'm currently looking into writing a java library which could be used to integrate Photostation photos into all sorts of gallery apps..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment