Open SolidTux opened 4 years ago
This would be cool to see!
My current problem is the session_code_verifier
for the /connect/1.0.0/api/session_token
. It is not the state like with the normal Switch app. In fact it doesn't appear in any form in the initial URL or the redirection URL.
Ok, I can now login, it works like here, but the rest doesn't really work yet as you apparently need to set special "X-Moon-*" headers.
Currently, the backend returns null pointer exceptions :-D
Ok, I got it to run and made an example to print play time per game (see here). As said before, the authentication works as expected up to the token
API. After that you have an access_token
and an id_token
.
First we have to get the user id with
GET /2.0.0/users/me HTTP/1.1
Authorization: Bearer access_token
Host: api.accounts.nintendo.com
HTTP/1.1 200 OK
{
"nickname": "nickname",
"id": "user_id",
...a lot of other stuff...
}
Now the next step is to register the device with the online service. From now on the following headers probably have to be present (I didn't test which you can remove, but the device id should probably be required):
Authorization: Bearer access_token
X-Moon-App-Id: com.nintendo.znma
X-Moon-Os: ANDROID
X-Moon-Os-Version: 28
X-Moon-Model: some model
X-Moon-TimeZone: Europe/Berlin
X-Moon-Os-Language: de-DE
X-Moon-App-Language: de-DE
X-Moon-App-Display-Version: 1.11.0
X-Moon-App-Internal-Version: 229
X-Moon-Smart-Device-Id: device_id
User-Agent: moon_ANDROID/1.11.0 (com.nintendo.znma; build:229; ANDROID 28)
device_id
can be chosen. The device is registered using
POST /moon/v1/users/user_id/smart_devices HTTP/1.1
Host: api-lp1.pctl.srv.nintendo.net
{
"appLanguage": "de-DE",
"appVersion": {
"displayedVersion": "1.11.0",
"internalVersion": "229"
},
"bundleId": "com.nintendo.znma",
"id": "device_id",
"modelName": some model name,
"os": "ANDROID",
"osLanguage": "de-DE",
"osVersion": "28",
"timeZone": "Europe/Berlin"
}
HTTP/1.1 201 Created
{
"id": device_id,
"nintendoAccountId": account_id,
"bundleId": "com.nintendo.znma",
"os": "ANDROID",
"osVersion": "28",
"modelName": some model name,
"timeZone": "Europe/Berlin",
"appVersion": {
"displayedVersion": "1.11.0",
"internalVersion": 229
},
"osLanguage": "de-DE",
"appLanguage": "de-DE",
"notificationToken": null,
"updateRequired": false,
"createdAt": timestamp,
"updatedAt": timestamp
}
The registration is only needed once. This allows us now to get the ids of the registered devices
GET /moon/v1/users/user_id/devices?filter.device.activated.$eq=true HTTP/1.1
Host: api-lp1.pctl.srv.nintendo.net
HTTP/1.1 200 OK
{
"count": 1,
"items": [
{
"deviceId": "device_id",
"device": {
"id": "device_id",
...more information...
},
...more information...
},
...
]
}
For each device we can get the daily summaries
GET /moon/v1/devices/device_id/daily_summaries HTTP/1.1
Host: api-lp1.pctl.srv.nintendo.net
HTTP/1.1 200 OK
{
"count": 31,
"items": [
{
"deviceId": "device_id",
"date": "2020-04-06",
"result": "CALCULATING" or "ARCHIEVED",
"playingTime": seconds,
"exceededTime": null,
"disabledTime": 0,
"miscTime": 0,
"importantInfos": [],
"notices": [],
"observations": [],
"playedApps": [
{
"applicationId": "application id",
"title": "title",
...
},
...
],
"anonymousPlayer": null,
"devicePlayers": [
{
"playerId": "player_id",
"nickname": "nickname",
"imageUri": "image",
"playingTime": seconds,
"playedApps": [
{
"applicationId": "app_id",
"firstPlayDate": date,
"playingTime": seconds
},
...
]
}
],
"timeZoneUtcOffsetSeconds": 7200,
"lastPlayedAt": time stamp,
"createdAt": time stamp,
"updatedAt": time stamp
},
...
],
"updatedRecently": true
}
or a list of available monthly summaries
GET /moon/v1/devices/device_id/monthly_summaries HTTP/1.1
Host: api-lp1.pctl.srv.nintendo.net
HTTP/1.1 200 OK
{
"count": 11,
"indexes": [
"2020-03",
...
],
"items": [
{
"deviceId": "device_id",
"month": "2020-03"
},
...
]
}
Each montly summary can be obtained with
GET /moon/v1/devices/device_id/monthly_summaries/2020-03 HTTP/1.1
Host: api-lp1.pctl.srv.nintendo.net
HTTP/1.1 200 OK
{
"deviceId": "device_id",
"month": "2020-03",
"dailySummaries": {
"2020-03-11": {
"date": "2020-03-11",
"result": "ACHIEVED",
"playingTime": seconds
},
...
},
"playingDays": 31,
"playedApps": [
{
"applicationId": "application id",
"title": "title",
...
},
...
],
"insights": {
"thisMonth": {
"averagePlayingTime": seconds,
"playingDays": days,
"playingTime": seconds
},
"previousMonth": {
"averagePlayingTime": second,
"playingDays": days,
"playingTime": seconds
},
"rankings": {
"byDay": [
{
"applicationId": "application id",
"units": days,
"position": "UP"/"DOWN"/"STAY",
"ratio": ratio
},
...
],
"byTime": [
{
"applicationId": "application id",
"units": seconds,
"position": "UP"/"DOWN"/"STAY",
"ratio": ratio
},
...
]
}
},
"devicePlayers": [
{
"playerId": "player_id",
"nickname": "nickname",
"imageUri": "image",
"dailySummaries": {
"2020-03-11": {
"date": "2020-03-11",
"result": "ACHIEVED",
"playingTime": seconds
},
...
},
"insights": {
"thisMonth": {
"averagePlayingTime": seconds,
"playingDays": days,
"playingTime": seconds
},
"previousMonth": {
"averagePlayingTime": seconds,
"playingDays": days,
"playingTime": seconds
},
"rankings": {
"byDay": [
{
"applicationId": "application id",
"units": days,
"position": "UP"/"DOWN"/"STAY",
"ratio": ratio
},
...
],
"byTime": [
{
"applicationId": "application id",
"units": seconds,
"position": "UP"/"DOWN"/"STAY",
"ratio": ratio
},
...
]
}
}
},
...
],
"includedMajorVersions": [
9
],
"createdAt": timestamp,
"updatedAt": timestamp
}
There are a lot or more endpoints, e.g. for the parental control setting, but I haven't looked at them.
Would be great to have more information about the parental control API to get a detailed playtime per game. I have a Wireshark recording, but I'll first have to figure out how to strip sensitive information from that before posting.