PlayJam GameStick server API documentation
This is an attempt to document the network API used by the PlayJam GameStick gaming console.
API basics
Use cases
Setup
A new PlayJam GameStick does the following requests:
FIXME verify
OOBE (Out Of Box Experience) process starts with the GameStick setup:
Fetch registration code and show it on screen: POST http://l2.gamestickservices.net/api/rest/connect/stick/stick/xxx/view.json
Check every 5 seconds if the online registration has been finished: also POST http://l2.gamestickservices.net/api/rest/connect/stick/stick/xxx/view.json
Download game metadata: also POST http://l2.gamestickservices.net/api/rest/connect/stick/stick/xxx/view.json
Common data formats
JSON responses share some properties.
- date
Dates have format dd/MM/yyyy - e.g. 23/12/2013.
- time
Time since 01.01.1970 in milliseconds (unix timestamp * 1000)
JSON responses MUST be condensed to a single line.
HTTP Headers
User-Agent
The user agent may have two different values:
Dalvik/1.6.0 (Linux; U; Android 4.1.2; GameStick V1.0 Build/V1.03.04MX01_20130911)
GameStick/1.0
GameStick/1.0
Is used when the HTTP request is coming from com.playjam.EnhancedDownloadService.
The Accept-Encoding header is identity in that case.
Uncategorized
ping connection check
The connection check in com.playjam.gamestick.WifiTools.ChecksFragment#ping sends ICMP ping requests to three domains to see if the network is available:
connectcheck.gamestickservices.net
l2.gamestickservices.net
update.gamestickservices.net
GET http://connectcheck.gamestickservices.net/generate_204
Network availability ping via HTTP.
Firmware 2071 resolves the IP address for the hostname and sends the HTTP request directly to the IP address without providing a Host header.
At least firmware 0.0.53 sends the host name in the request.
HTTP request
- Protocol
http
- Host
connectcheck.gamestickservices.com
connectcheck.gamestickservices.net
clients3.google.com
- Path
generate_204
HTTP response
Success
- Status code
204 No Content
Usage
com.playjam.gamestick.WifiTools.ChecksFragment#http()
Only connectcheck.gamestickservices.net
com.playjam.gamestick.WifiService#ping()
Tries all three servers until it finds one that responds.
GET http://db.gamestickservices.com/api/rest/joystick/bindings/xxx/view.json
Fetch controller mapping for a game.
Games had to request input maps themselves by sending the com.playjam.InputService.Remap intent with the game ID.
They could also send a keymap XML via the com.playjam.InputService.RemapXML intent, and the com.playjam.InputService would then take care of mapping the keys.
Unfortunately, InputService hard-codes the db.gamestickservices.com domain and does not use the .net one.
Games known to request the input map file:
Sela the Space Pirate, id 171
HTTP request
- Protocol
http
- Host
db.gamestickservices.com
- Path
/api/rest/joystick/bindings/xxx/view.json
- xxx
UUID of the game
HTTP response
Must be on a single line.
- Status code
200 OK
Example
{
"body": {
"joyStickBindings": "<keymap>...</keymap>"
}
}
Keymap file
<keymap>
<!-- 4 options, repeat and mix as often as you want -->
<key output="key" from="$intKeycode" to="$intKeycode"/>
<key output="motion" from="$intKeycode" action="$byte">
<axis id="$int" value="$float"/>
<!-- multiple possible -->
</key>
<motion output="key"
axis="$intFromAxis" low="$floatFromLowThreshold" high="$floatFromHighThreshold"
to="$intToKeyCode" action="$byteToAction"
multidown="$boolSendMultiDown"
applyzero="$boolApplyZero" zerovalue="$floatZeroValue"
/>
<motion output="motion"
axis="$intFromAxis" low="$floatFromLowThreshold" high="$floatFromHighThreshold"
applyzero="$boolApplyZero" zerovalue="$floatZeroValue"
>
<axis id="$int" value="$float"/>
<!-- multiple possible -->
</motion>
</keymap>
GET http://dev-db.gamestickservices.net/api/rest/developer/validate/xxx/yyy/view.json
Verify that the GameStick may switch to the developer firmware.
HTTP request
- Protocol
http
- Host
dev-db.gamestickservices.net
- Path
/api/rest/developer/validate/xxx/yyy/view.json;jsessionid=zzz
- /api/rest/developer/validate/xxx/yyy/view.json
OOBE does not add the jsessionid parameter
- xxx
Hardware ID
Example: ac:db:da:09:18:5c
- yyy
Verification code entered by the user.
7 characters long, all digits. Last digit is checksum calculated with the Damm algorithm.
- zzz
Session ID
HTTP response
Standard response, with success set to true.
{"body":{"action":"","message":"","success":true}}
POST http://l2.gamestickservices.net/api/rest/connect/stick/stick/xxx/view.json
Used for several things:
Network connection check
Fetch registration code and session ID for this gamestick.
Fetch information about games and their display in the main menu
HTTP request
When the GameStick is not registered yet, then this URL is fetched every 5 seconds. Once registered, it is fetched every 2 minutes.
The initial request does not contain a session ID. The hardware ID is used to associate the stick with an existing user ID and a new session ID is generated.
- Method
POST
Firmware 0.0.53 uses GET.
DatabaseService.ServiceCore can be put into GET mode in Firmware 2071, in that case, GET will be used as well.
- Protocol
http
- Host
l2.gamestickservices.net
Firmware 0.0.53 uses db.gamestickservices.net.
- Path
/api/rest/connect/stick/stick/xxx/view.json
- xxx
Hardware-ID, e.g. ac:db:da:09:18:5c
- ;jsessionid=zzz
In GET mode, but only after the initial request.
- Headers
- Accept-Encoding
identity
- Content-Type
application/x-www-form-urlencoded
- Content-Length
0
- User-Agent
GameStick/1.0 (when requested via com.playjam.EnhancedDownloadService)
- If-Modified-Since
When the GameStick cache contains a previous version.
Example: If-Modified-Since: Thu, 06 Jul 2023 07:02:39 UTC
Not sent when the Cookie is sent.
- POST parameters
None
- Cookies
- JSESSIONID
Session ID, only when available (not empty)
In POST mode only
- AWSELB
When available
In POST mode only.
HTTP response
When used for connection check, the response must contain one of the following strings (no whitespace after :):
"status":"CONNECTION_IN_PROGRESS" "status":"CONNECTED"
Not registered yet - CONNECTION_IN_PROGRESS
- Status code
200 OK
{
"sid": "dummy",
"time": "1680109254000",
"body": {
"status":"CONNECTION_IN_PROGRESS",
"registrationCode": "abcdefg"
}
}
Registration complete - CONNECTED
- Status code
200 OK
304 Not Modified - when the If-Modified-Since header value is equal or higher than the data timestamp.
- body.config.apps[].genre
Not used in firmware 2071, but still available - probably for older versions.
- body.config.apps[].genres
Known genres:
Action
Adventure
Arcade
Classics
Media
Platformer
Puzzle
Racing
Shmup
Shooter
- body.config.apps[].images.name
Special name STICK_SCREENSHOT adds the image URLs as screenshot, otherwise as thumbnail. (firmware 2071).
Known names:
STICK_ICON (85x48)
STICK_REGISTRATION_GAME_ICON (200x200)
STICK_SCREENSHOT (350x160)
STICK_SCREENSHOT_1080 (525x240)
STICK_THUMBNAIL1 (350x88)
STICK_THUMBNAIL2 (350x160)
STICK_THUMBNAIL3 (350x236)
STICK_THUMBNAIL4 (350x400)
STICK_VIDEO1_SCREENSHOT (350x160)
STICK_SCREENSHOT and STICK_SCREENSHOT_1080 may have multiple URLs; the other ones only one.
- body.config.global.uitranslation
Not used in firmware 2058 and 2071.
- body.config.global.newfeatured.ages[].entries[].columnentries[].thumbnail
The code says this is the "tile size".
6 for full-height (one game in this column) STICK_THUMBNAIL4 is used.
4 for 2/3 height (two games in this column, one size 4, one size 2) STICK_THUMBNAIL3
3 for 1/2 (two games in this column) STICK_THUMBNAIL2
2 for 1/3 height (3 games in this column) STICK_THUMBNAIL1
{
"sid":"dummy",
"time":"1680109254000",
"lastaccessed": 1385115865500,
"x-forwarded-for": null,
"created": 1385115865500,
"accessCount": 0,
"addr": "10.37.137.31",
"remoteaddr": "135.196.28.241",
"body": {
"status":"CONNECTED",
"config": {
"apps": [
{
"id": 23,
"minAge": 3,
"name": "My game title",
"description": "Game description FIXME format",
"package": "org.example.game",
"size": 12345,
"download": {
"version": 123,
"url": "http://example.org/game.apk"
},
"genre": "Racing",
"genres": [
{
"genre": "Racing"
}
],
"popular": 1,
"featured": 1,
"isfree": true,
"bought": false,
"downloadedfree": false,
"multipricing": {
"buy": [
{
"amount": 23.42,
"isocurrency": "EUR"
}
],
"rent": [
]
},
"images": [
{
"name": "STICK_SCREENSHOT",
"width": 512,
"height": 384,
"urls": [
{
"url": "http://example.org/image.jpg"
}
]
}
]
}
],
"global": {
"uitranslation": {
"country": [
],
"version": 0
},
"newfeatured": {
"ages": [
{
"age": 3,
"entries": [
{
"columnentries": [
{
"gameID": 254,
"thumbnail": 12,
"column": 1
}
]
}
]
}
]
}
}
}
}
}
Usage
com.playjam.gamestick.WifiTools.ChecksFragment#doDatabaseConnect()
To check if a network connection is available. Only uses l2.gamestickservices.net.
com.playjam.DatabaseService.apk: com.playjam.Services.Database.ConnectDownloader
GET http://l2.gamestickservices.net/api/rest/parentcontroll/change/agerating/xxx/yyy/view.json
Change the profile's minAge setting.
Only games suitable for that age are shown by the GameStick Console UI.
HTTP request
- Protocol
http
- Host
l2.gamestickservices.net
- Path
/api/rest/parentcontroll/change/agerating/xxx/yyy/view.json;jsessionid=zzz
- xxx
Age rating:
3
7
12
17
- yyy
MD5-hashed user password
- zzz
Session ID
HTTP response
Successful change
- Status code
200 OK
{
"body": {
"success": true,
"message": null,
"action": "ChangeAgeRating"
}
}
action and message do not seem to be needed.
Wrong password
- Status code
200 OK
{
"body": {
"success": false
}
}
Neither action no message seem to be needed.
GET http://l2.gamestickservices.net/api/rest/player/profile/view.json
Fetch player information.
In firmware v2071 OOBE setup will not finish when the profile is not returned properly.
HTTP request
- Protocol
http
- Host
l2.gamestickservices.net
Firmware 0.0.53 used db.gamestickservices.net
- Path
/api/rest/player/profile/view.json;jsessionid=xxx
- xxx
Session ID from the registration check api/rest/connect/stick/stick/xxx/view.json.
Empty when not registered yet.
- Headers
- User-Agent
Examples:
Dalvik/1.6.0 (Linux; U; Android 4.1.2; GameStick V1.0 Build/V1.03.04MX01_20130911)
GameStick/1.0
- Accept-Encoding
gzip only when User-Agent is Dalvik/...
identity when User-Agent is GameStick/1.0
HTTP response
Not registered yet
- Status code
200 OK
FIXME
User has been registered
Property notes:
- addr
IP-Address (probably of client)
Type: string
- accessCount
FIXME
Type: int
Example: 1
- created
Type: int
Example: 1382005635322
- lastaccessed
Type: int
Example: 1382005635738
- sid
Session ID (same as in request URL)
Type: string
Example: 79C9B23DBA2682FEDFD0231A9AA28312
- time
Type: string
Example: "1382005637299"
- body
The actual profile data
- body.accountType
Type: string
Known values:
MANUALY_DEFINED
CONSUMER
- body.achievementStatus
Type: object
- body.achievementStatus.lastAchievementGameName
Type: string | null
Title of the game that the player unlocked the last achievement in.
Mapping to the game data really happens via the game name, and not with a package name or UUID.
The game's logo-1 file is used in the profile overview page.
null when no achievement gotten yet.
Example: Bloo Kid
- body.achievementStatus.numberOfAchievementsUnlocked
Type: int
Sum of achievements unlocked in all games
Example: 23
- body.avatarLargeUrl
Type: string
Image with 400x400
- body.avatarSmallUrl
Type: string
Image with 118x118px
- body.action
null in all known cases.
Type: string
- body.balance
Type: object
- body.balance.amountOfMoneyLeft
Type: string
Examples:
USD 0.00
GBP 25.00
- body.balance.transactions
Type: array
- body.balance.transactions[].amount
Type: string
When buying a game. null when uploading money.
Example: GBP 2.99
- body.balance.transactions[].balance
Type: string
Example: GBP 25.00
- body.balance.transactions[].date
Type: string
Must contain the string " - " (space dash space). Before: date, after: description
Examples:
16/10/2013 - TOP UP:PREPAID_CARD
19/10/2014 - TOP UP:PAYPAL - when uploading money via PayPal
12/10/2014 - Slingshot Racing - game bought
- body.balance.transactions[].description
Type: string
null in all observed files
- body.balance.transactions[].source
Type: string
Known values:
PAYPAL
PREPAID_CARD
WALLET
- body.balance.transactions[].type
Type: string
Known values:
CREDIT_WALLET
GAME PRODUCT
- body.currency
Three-letter currency code
Known values:
GBP
USD
- body.dateJoined
Type: string
Example: 23/09/2014
- body.dateOfBirth
Type: string
Example: 08/08/1984
- body.email
Type: string
- body.founderFlag
Type: int
The 25$ Kickstarter perk:
FOUNDER TAG: Name Check + Reserve your username before launch + Get a founder tag next to that username.
- body.founderName
Type: string
- body.gamertag
Type: string
Profile user name
- body.location
Type: string
Two-letter uppercase country code
Known values:
GB
US
- body.message
Type: string
Does not seem to be used in 2071.
- body.minAge
Type: int
Example: 17
- body.minAgeLabel
Type: string
Example: 17+
- body.password
Password hash (probably for age change verification)
Example: 75381f9f2bd23d8b4a0dcb0ad7c364ff
- body.securityLevel
Type: int
Known values:
0
1
- body.success
Type: string
Does not seem to be used in 2071.
{
"sid": "sessionid",
"time": "1680109254000",
"body": {
"avatarLargeUrl": "http://example.org/avatar.png",
"gamertag": "cweiske",
"avatarSmallUrl": "http://example.org/avatar.png",
"location": "Somewhere",
"dateOfBirth": "23/12/1942",
"dateJoined": "23/12/2013",
"email": "email@example.org",
"password": "mypassword",
"accountType": "FIXME",
"minAge": 17,
"founderFlag": 1,
"founderName": "cweiske-kickstarter",
"minAgeLabel": "17+",
"securityLevel": 0,
"balance": {
"amountOfMoneyLeft": "not much",
"transactions": [
{
"date": "23/12/2024 - buy a game",
"amount": "23.42"
}
]
},
"achievementStatus": {
"lastAchievementGameName": "Some Game",
"numberOfAchievementsUnlocked": 23
}
}
}
Usage
com.playjam.Services.Database.ServiceCore#downloadProfile()
POST http://update.gamestickservices.net/check.php
Check if a new firmware update is available.
Three hosts are checked one after another. When update.gamestickservices.com is not available, it may take up to two minutes until the .net host is tried.
HTTP request
- Protocol
http
- Host
Three hosts are checked in firmware 2071:
update.gamestickservices.com
update.gamestickservices.net
54.215.8.117
- Path
check.php
- Headers
- Content-Type
application/x-www-form-urlencoded
- POST parameters
- v
JSON-encoded hardware information (version 0.0.53):
{ "hwid": "ac:db:da:09:18:5c", "major": 0, "minor": 0, "revision": 53, "platform": 0 }
version 2049:
{"platform":0,"revision":2049,"minor":9,"hwid":"ac:db:da:09:18:5c","major":0}
HTTP response
JSON must be one a single line; parsing will fail otherwise.
Update available
- Status code
200 OK
{
"available": true,
"major": 0,
"minor": 0,
"revision": 53,
"forced": false,
"name": "v2.23.42",
"description": "Update now immediately! We have new features.",
"timestamp": 1680271986000,
"url": "http://example.org/firmware.php?version=2071"
}
No update available
- Status code
200 OK
{
"available": false
}
Usage
com.playjam.gamestick.WifiTools.ChecksFragment#doUpdateConnect()
com.playjam.UpdateService
Update download process
Firmware updates are downloaded by a separate downloading process in com.playjam.UpdateService.
Updates are downloaded in small chunks that are combined to a single file in the end. Firmware updates are standard Android OTA .zip update files that were renamed to .img by PlayJam. (GameStick-Software-v2071.img).
The download URL given in the HTTP reponse is appended with &i= plus the chunk index number.
Two special chunk numbers exist:
- -2
Returns the total size of the download (plain text long value)
- -1
Returns the number of chunks (plain text, int)
-2 is fetched first, -1 second and then 0, 1 and so forth.
After download and chunk combination, the file is verified by standard Android mechanism android.os.RecoverySystem.verifyPackage().
Information about the new firmware is written to /data/GameStickCache/update.info.
Chunks
Generating chunk files:
The firmware update file must be split into files of 102400 bytes.
Each part must be XORed with 91 (hex 5b, binary 1011011).
The binary SHA1 sum of the XORed part file must pre prepended before the data
Having a single chunk file only should work, too.
GET http://www.playjam.com/bundles/system/meta.json
Fetch link to the URL of the latest Companion App configuration file.
Used by the companion app.
HTTP request
- Protocol
http
- Host
www.playjam.com
- Path
/bundles/system/meta.json
HTTP response
Property notes:
- timestamp
Type: long. Optional.
0 to disable Companion App bundle file download.
- bundleURL
Path to .zip file with configuration data.
Example:
{
"timestamp": 0,
"bundleURL": null
}
Usage
com.playjam.companionapp.service.CAServerService#fetchSystemBundle()
Achievements
GET http://l2.gamestickservices.net/api/rest/game/xxx/achievements/view.json
Fetch achievements for a single game.
Accessed from the GameStick profile view when selecting a game.
HTTP request
- Protocol
http
- Host
l2.gamestickservices.net
- Path
/api/rest/game/xxx/achievements/view.json;jsessionid=zzz
- xxx
UUID of the game
- zzz
Session ID
HTTP response
Must be on a single line.
Used achievement properties seem to be id, achievementName, description, fileUrl and isCurrentUserOwner.
Images have an aspect ratio of 7:4, around 177x101px.
Grayscale .png images are not supported; they must be full-colored ones.
- Status code
200 OK
Example
{
"body": {
"success": true,
"gameId": "0cfc156cdca036835aa5414bafb610b8",
"gameList": [
{
"id": 460,
"achievementType": null,
"achievementName": "Happy end",
"description": "Beat the game",
"xpValue": 1,
"fileName": null,
"fileUrl": "http://gamestick.cweiske.de/archive/gamestick_de.eiswuxe.blookid/achievements/resized/achievement_5.png",
"isCurrentUserOwner": 1
},
{
"id": 461,
"achievementType": null,
"achievementName": "Triple hit",
"description": "Jump on three enemies without touching ground",
"xpValue": 1,
"fileName": null,
"fileUrl": "http://gamestick.cweiske.de/archive/gamestick_de.eiswuxe.blookid/achievements/resized/achievement_6.png",
"isCurrentUserOwner": 0
}
]
}
}
GET http://l2.gamestickservices.net/api/rest/user/achievement/summary/view.json
Get an achievement summary with statistics of games and their achievement numbers.
HTTP request
- Protocol
http
- Host
l2.gamestickservices.net
- Path
/api/rest/user/achievement/summary/view.json;jsessionid=zzz
- zzz
Session ID
Example:
GET http://l2.gamestickservices.net/api/rest/user/achievement/summary/view.json;jsessionid=sacdbda09185c
HTTP response
- Status code
200 OK
Example:
{
"body": {
"success": true,
"gameAchievementSummary": [
{
"gameId": 23,
"gameName": "Bloo Kid",
"lastAchievementImageUrl": "http://gamestick.cweiske.de/archive/gamestick_de.eiswuxe.blookid/logo-2.png",
"lastAchievementName": "Reach the sky",
"gameIdentifcation": "0cfc156cdca036835aa5414bafb610b8",
"totalNumberofAchievements": 42,
"numberOfPlayerUnlockedAchievements": 23
}
]
}
}
Property notes:
- body.gameAchievementSummary.gameId
Probably body.config.apps[].id from POST http://l2.gamestickservices.net/api/rest/connect/stick/stick/xxx/view.json.
Type: int
- body.gameAchievementSummary.gameName
Title of the game
Type: string
- body.gameAchievementSummary.gameIdentifcation
Proably UUID of the game release.
Yes, there is a typo in that property name.
Type: string
Example: 0cfc156cdca036835aa5414bafb610b8
- body.gameAchievementSummary.lastAchievementImageUrl
FIXME: Seems not to be used.
Best size: FIXME
Type: string
- body.gameAchievementSummary.totalNumberofAchievements
Number of possible achievements in the game
Yes, the "o" in "of" is inconsistently lowercase.
Type: int
- body.gameAchievementSummary.numberOfPlayerUnlockedAchievements
How many the player unlocked
Type: int
GET http://l2.gamestickservices.net/api/rest/user/achievement/xxx/set-complete/view.json
When some achievement has been reached/completed in a game.
Achievements had to be registered at PlayJam.
HTTP request
- Protocol
http
- Host
l2.gamestickservices.net
- Path
/api/rest/user/achievement/xxx/set-complete/view.json;jsessionid=zzz
- xxx
Global achievement ID.
Example: 461
- zzz
Session ID
Example:
GET http://l2.gamestickservices.net/api/rest/user/achievement/461/set-complete/view.json;jsessionid=sacdbda09185c
HTTP response
Successful registration
- Status code
200 OK
FIXME: Verify if this is correct
{
"body": {
"success": true
}
}
GET http://l2.gamestickservices.net/api/rest/user/game/xxx/achievement/list/view.json
Fetch all achievements for a single game including the info if the user has unlocked them.
Used by games to check which achievements have already been unlocked by the user.
Known usage:
When "Bloo Kid" starts
HTTP request
- Protocol
http
- Host
l2.gamestickservices.net
- Path
/api/rest/user/game/xxx/achievement/list/view.json;jsessionid=zzz
- xxx
UUID of the game
- zzz
Session ID
HTTP response
The response must be on one single line!
At least "Bloo Kid" only cares about the ID. The other properties must exist (JSON parsing fails otherwise), but their values are not used.
The id values are known by the server and had to be registered in the PlayJam Publishing Portal.
isCurrentUserOwner must be an integer, not a boolean.
- Status code
200 OK
Example
{
"body": {
"success": true,
"achievements": [
{
"id":461,
"achievementType": "FIXME",
"achievementName": "FIXME",
"description": "FIXME",
"xpValue": 1,
"fileName": "FIXME",
"fileUrl": "FIXME",
"isCurrentUserOwner": 1
}
]
}
}
"Boulder Dash" does not want the success property but requires body to be an array listing the achievements - which contradicts the requirements by Bloo Kid and the GameStick console API:
{
"body": [
{
"id":461,
"achievementType": "FIXME",
"achievementName": "FIXME",
"description": "FIXME",
"xpValue": 1,
"fileName": "FIXME",
"fileUrl": "FIXME",
"isCurrentUserOwner": 1
}
]
}
Known achievement IDs:
- 461
Bloo Kid: Triple Hit
All known IDs are listed in the game data files.
Analytics
GET http://l2.gamestickservices.net/api/rest/analytics/application-event/analytics/event/view.json
Send user behavior data to the server (tracking).
Known to be used in firmware versions:
2058
HTTP request
- Protocol
http
- Host
l2.gamestickservices.net
- Path
/api/rest/analytics/application-event/analytics/event/view.json;jsessionid=zzz?Map=yyy
- zzz
Session ID from the registration check api/rest/connect/stick/stick/xxx/view.json.
- yyy
Actual tracking data:
{"NAVIGATE":"Games Featured Menu","NAVIGATE":"Media All Menu","NAVIGATE":"Profile"}
Looks like JSON, but has duplicate keys.
Known keys:
NAVIGATE
HTTP response
- Headers
- Content-Type
application/json
All data in the response must be on one line.
{"body":{"success":true}}
If the response is not successful, or the response cannot be parsed into a JSON object from one line of response data, the tracking data are sent again some minutes later.
Usage
Analytics intents are sent by the console application.
Response gets parsed in com.playjam.gamestick.databaseinterfaceservice.DatabaseInterfaceService#ParseResponse()
GET http://l2.gamestickservices.net/api/rest/game/downloadedfreegame/xxx/true/view.json
When a game has been downloaded free of charge.
HTTP request
- Method
GET
- Protocol
http
- Host
l2.gamestickservices.net
- Path
/api/rest/game/downloadedfreegame/xxx/true/view.json;jsessionid=zzz
- xxx
Game ID, e.g. d8a7bea559a34ba2a71b97f99de54884
- zzz
Session ID
- Headers
- User-Agent
Dalvik/1.6.0 (Linux; U; Android 4.1.2; GameStick V1.0 Build/V1.03.04MX01_20130911)
- Connection
Keep-Alive
- Accept-Encoding
gzip
HTTP response
FIXME
GET http://l2.gamestickservices.net/api/rest/game/xxx/event/end-game/view.json
Notify the server that a game has been stopped/ended.
HTTP request
- Protocol
http
- Host
l2.gamestickservices.net
- Path
/api/rest/game/xxx/event/end-game/view.json;jsessionid=zzz
- xxx
UUID of the game
- zzz
Session ID
HTTP response
Must be on a single line.
- Status code
200 OK
Example
{"body":{"success":true,"message":"event saved","action":"end-game"}}
GET http://l2.gamestickservices.net/api/rest/game/xxx/event/start-game/view.json
Notify the server that a game has been started.
HTTP request
- Protocol
http
- Host
l2.gamestickservices.net
- Path
/api/rest/game/xxx/event/start-game/view.json;jsessionid=zzz
- xxx
UUID of the game
- zzz
Session ID
HTTP response
Must be on a single line.
- Status code
200 OK
Example
{"body":{"success":true,"message":"event saved","action":"start-game"}}
Leaderboards
GET http://l2.gamestickservices.net/api/rest/game/xxx/leadrboard/top50/view.json
Fetch the first 50 entries in the game's high score list.
HTTP request
- Protocol
http
- Host
l2.gamestickservices.net
- Path
- /api/rest/game/xxx/leadrboard/top50/view.json;jsessionid=zzz
The missing e is intentional.
- xxx
UUID of the game
- yyy
Score/points (integer)
- zzz
Session ID
HTTP response
Must be on a single line.
FIXME: Unclear what values are expected in avatarId.
- Status code
200 OK
Example
{
"body": {
"success": true,
"leaderBoard": [
{
"position": 1,
"score": 42,
"userPlayTag": "cweiske-dev",
"avatarId": 11
},
{
"position": 2,
"score": 23,
"userPlayTag": "anotheruser",
"avatarId": 11
}
]
}
}
Real response rescued from a GameStick:
{
"sid": "2F1034E2CBC647E510D2554D4B253583",
"body": {
"success": true,
"message": null,
"action": "getTop50",
"leaderBoard": [
{
"userPlayTag": "Chris",
"avatarId": 49,
"score": 39825,
"position": 1,
"extendDetail": null
},
{
"userPlayTag": "LiveTest3",
"avatarId": 36,
"score": 21275,
"position": 2,
"extendDetail": null
},
{
"userPlayTag": "MP1Tim",
"avatarId": 35,
"score": 18275,
"position": 3,
"extendDetail": null
},
{
"userPlayTag": "mumoh",
"avatarId": 59,
"score": 9075,
"position": 4,
"extendDetail": null
},
{
"userPlayTag": "DeathStalker13",
"avatarId": 35,
"score": 8100,
"position": 5,
"extendDetail": null
},
{
"userPlayTag": "fagger1uk",
"avatarId": 41,
"score": 7900,
"position": 6,
"extendDetail": null
},
{
"userPlayTag": "JoeMCooper",
"avatarId": 46,
"score": 5975,
"position": 7,
"extendDetail": null
},
{
"userPlayTag": "dchand0571",
"avatarId": 41,
"score": 5450,
"position": 8,
"extendDetail": null
},
{
"userPlayTag": "liveVega",
"avatarId": 55,
"score": 5125,
"position": 9,
"extendDetail": null
},
{
"userPlayTag": "liveOli",
"avatarId": 55,
"score": 4975,
"position": 10,
"extendDetail": null
},
{
"userPlayTag": "pacman130",
"avatarId": 37,
"score": 4725,
"position": 11,
"extendDetail": null
},
{
"userPlayTag": "hometest10",
"avatarId": 42,
"score": 4525,
"position": 12,
"extendDetail": null
},
{
"userPlayTag": "Danyel",
"avatarId": 48,
"score": 2675,
"position": 13,
"extendDetail": null
},
{
"userPlayTag": "hometest6",
"avatarId": 39,
"score": 2225,
"position": 14,
"extendDetail": null
},
{
"userPlayTag": "hometest1",
"avatarId": 35,
"score": 2075,
"position": 15,
"extendDetail": null
}
]
},
"time": "1402341994155",
"lastaccessed": 1402341982363,
"x-forwarded-for": null,
"created": 1402340389289,
"accessCount": 32,
"addr": "10.37.137.31",
"remoteaddr": "109.151.188.110"
}
GET http://l2.gamestickservices.net/api/rest/game/xxx/save-score/yyy/extend/view.json
Store points in the game-specific leaderboard
HTTP request
- Protocol
http
- Host
l2.gamestickservices.net
- Path
/api/rest/game/xxx/save-score/yyy/extend/view.json;jsessionid=zzz
- xxx
UUID of the game
- yyy
Score/points (integer)
- zzz
Session ID
HTTP response
Must be on a single line.
- Status code
200 OK
Example
{
"body": {
"success": true
}
}
Real response rescued from a GameStick:
{
"sid": "29D6CBE636DB8E10653FFD2EA27B7582",
"body": {
"success": true,
"message": null,
"action": "save-score"
},
"time": "1417290599050",
"lastaccessed": 1417290563332,
"x-forwarded-for": null,
"created": 1417271831966,
"accessCount": 366,
"addr": "10.37.137.31",
"remoteaddr": "50.10.244.222"
}
Payments
GET http://l2.gamestickservices.net/api/rest/wallet/payment/game/xxx/init-transaction/do/view.json
When clicking "buy" in the game details screen.
Known to be used in firmware versions:
2058
HTTP request
- Protocol
http
- Host
l2.gamestickservices.net
- Path
/api/rest/wallet/payment/game/xxx/init-transaction/do/view.json;jsessionid=zzz
- xxx
Game ID.
Empty in firmware 2051.
- zzz
Session ID from the registration check api/rest/connect/stick/stick/xxx/view.json.
HTTP response
Everything must be on one single line!
FIXME
Dummy example:
{ "body": { "pageUrl": "xxx", "url": "yyy" } }
Only one of pageUrl and url is needed, depends on request (if internal request name is webview_displaywebpage or webview_displayactivewebpage -> url, otherwise pageUrl).
This here should use pageUrl.
Usage
com.playjam.gamestick.DatabaseInterfaceService.apk: com.playjam.gamestick.databaseinterfaceservice.DatabaseInterfaceService#ParsePurchaseItemResponse()
GET http://l2.gamestickservices.net/api/rest/wallet/payment/topupwallet/init-transaction/do/view.json
Start adding credits to the wallet in the player profile ("Add credit").
The GameStick shows the webpage URL pageUrl in a window.
FIXME: Somehow the webpage must signal that adding credits worked.
HTTP request
- Protocol
http
- Host
l2.gamestickservices.net
- Path
/api/rest/wallet/payment/topupwallet/init-transaction/do/view.json;jsessionid=zzz
- zzz
Session ID
HTTP response
- Status code
200 OK
{
"body":{
"success": true,
"pageUrl": "http://example.org"
}
}
Savegames
GET http://l2.gamestickservices.net/api/rest/game/xxx/save-state/view.json
Store the current game progress on the server (savegame).
HTTP request
- Protocol
http
- Host
l2.gamestickservices.net
- Path
/api/rest/game/xxx/save-state/view.json;jsessionid=zzz
- xxx
UUID of the game
- zzz
Session ID
- Query parameters
?data=Rm9vIDIzIDQyCg%3D%3D
- mydata
base64-encoded binary save state data (URL-encoded of course)
HTTP response
- Status code
200 OK
Example
{"body":{"success":true}}
GET http://l2.gamestickservices.net/api/rest/game/xxx/state/view.json
Load the current game progress from the server (savegame).
HTTP request
- Protocol
http
- Host
l2.gamestickservices.net
- Path
/api/rest/game/xxx/state/view.json;jsessionid=zzz
- xxx
UUID of the game
- zzz
Session ID
HTTP response
- Status code
200 OK
Example
{
"body": {
"success": true,
"gameState": "Rm9vIDIzIDQyCg=="
}
}
About
This documentation has been written by Christian Weiske, cweiske+ouya@cweiske.de.
Last update: 2024-12-06T18:33:39+01:00
License
It is licensed under the GNU Free Documentation License.
Source code
The documentation sources are available at https://git.cweiske.de/playjam-gamestick-api-docs.git and mirrored at https://codeberg.org/cweiske/playjam-gamestick-api-docs
Home page
A rendered version of this documentation is available at http://cweiske.de/gamestick-api-docs.htm
Building
You need to install rst2html5 before:
$ pip install rst2html5-tools
Rendering the docs is done via a build script:
$ ./build.sh