NintendoSwitchRESTAPI icon indicating copy to clipboard operation
NintendoSwitchRESTAPI copied to clipboard

Parental Controls

Open SolidTux opened this issue 5 years ago • 4 comments

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.

SolidTux avatar Apr 01 '20 23:04 SolidTux

This would be cool to see!

frozenpandaman avatar Apr 02 '20 01:04 frozenpandaman

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.

SolidTux avatar Apr 02 '20 16:04 SolidTux

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

SolidTux avatar Apr 06 '20 19:04 SolidTux

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.

SolidTux avatar Apr 06 '20 22:04 SolidTux