Nintendo Switch Online API - tkgstrator/Salmonia3 GitHub Wiki

Session Token

Access Token 取得のための Session Token を取得します。

リクエスト

パラメータ
Method POST
URL https://accounts.nintendo.com/connect/1.0.0/api/session_token
User-Agent OnlineLounge/2.0.0 NASDKAPI iOS
client_id=71b963c1b7b6d119&session_token_code=eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL2FjY291bnRzLm5pbnRlbmRvLmNvbSIsInN0YzpzY3AiOlswLDgsOSwxNywyM10sImp0aSI6IjM1NzQ1MTg5MTkxIiwic3RjOmMiOiJ0ejdaMGhfM2RLMTBYLTc5SlREWUUyaG5seGU1dWhYd0tsUldoQUdBb1ZZIiwic3RjOm0iOiJTMjU2Iiwic3ViIjoiNWFlOGY3YTc4YjBjY2E0ZCIsInR5cCI6InNlc3Npb25fdG9rZW5fY29kZSIsImV4cCI6MTYxOTQ3OTE0OSwiYXVkIjoiNzFiOTYzYzFiN2I2ZDExOSIsImlhdCI6MTYxOTQ3ODU0OX0.XSFscPYMGbcaLLJxBA-fIO0zzt1bWs4X39oZGOs4jrI&session_token_code_verifier=RwKTiEojlJbQInnPCHBitkNHehgICjFsstWUvOkGQibeuukvXx

client_idの値は固定値です。

JSON ではなく Form-Data で Body を送信します。

エラー

// 400
{
  "error_description": "The provided session_token_code is expired",
  "error": "invalid_request"
}

レスポンス

{
  "code": "eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL2FjY291bnRzLm5pbnRlbmRvLmNvbSIsInN1YiI6IjVhZThmN2E3OGIwY2NhNGQiLCJleHAiOjE2MTk0ODIxNTUsImlhdCI6MTYxOTQ3ODU1NSwidHlwIjoiY29kZSIsImF1ZCI6IjcxYjk2M2MxYjdiNmQxMTkiLCJhYzpzY3AiOlswLDgsOSwxNywyM10sImp0aSI6IjM1NzQ1MTYxODQzIn0.vT1aaYdqHaAinY0BKGDeG2cAUqS5DOndH02keQxZXxw",
  "session_token": "eyJhbGciOiJIUzI1NiJ9.eyJzdDpzY3AiOlswLDgsOSwxNywyM10sInN1YiI6IjVhZThmN2E3OGIwY2NhNGQiLCJleHAiOjE2ODI1NTA1NTUsImlzcyI6Imh0dHBzOi8vYWNjb3VudHMubmludGVuZG8uY29tIiwidHlwIjoic2Vzc2lvbl90b2tlbiIsImlhdCI6MTYxOTQ3ODU1NSwiYXVkIjoiNzFiOTYzYzFiN2I2ZDExOSIsImp0aSI6IjUwNjgwMjkzODEifQ.CwI0tqAv186pEgo7HKn_q--l8fB-jmwFu6iJNNvY_W8"
}

Access Token

Nintendo Switch Online のサービスに接続するための Access Token を取得します。

リクエスト

パラメータ
Method POST
URL https://accounts.nintendo.com/connect/1.0.0/api/token
User-Agent OnlineLounge/2.0.0 NASDKAPI iOS
{
  "client_id": "71b963c1b7b6d119",
  "session_token": "eyJhbGciOiJIUzI1NiJ9.eyJzdDpzY3AiOlswLDgsOSwxNywyM10sInN1YiI6IjVhZThmN2E3OGIwY2NhNGQiLCJleHAiOjE2ODI1NTA1NTUsImlzcyI6Imh0dHBzOi8vYWNjb3VudHMubmludGVuZG8uY29tIiwidHlwIjoic2Vzc2lvbl90b2tlbiIsImlhdCI6MTYxOTQ3ODU1NSwiYXVkIjoiNzFiOTYzYzFiN2I2ZDExOSIsImp0aSI6IjUwNjgwMjkzODEifQ.CwI0tqAv186pEgo7HKn_q--l8fB-jmwFu6iJNNvY_W8",
  "grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer-session-token"
}

client_id, grant_typeの値は固定値です。

エラー

// 400
// セッショントークンが誤っている場合
{
    "error_description": "The provided grant is invalid",
    "error": "invalid_grant"
}

// 400
// クライアントIDが誤っている場合
{
    "error": "invalid_client",
    "error_description": "Client authentication failed"
}

// 400
// フォーマットが正しくない場合
{
    "error_description": "The request does not satisfy the schema",
    "error": "invalid_request"
}

レスポンス

{
  "access_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6Ijg1ZTNjN2FkLTBlMTQtNDIxMi1hZTg5LTExMjIwZmM3MDMzYSIsImprdSI6Imh0dHBzOi8vYWNjb3VudHMubmludGVuZG8uY29tLzEuMC4wL2NlcnRpZmljYXRlcyJ9.eyJhdWQiOiI3MWI5NjNjMWI3YjZkMTE5Iiwic3ViIjoiNWFlOGY3YTc4YjBjY2E0ZCIsImp0aSI6IjgyYzUzM2NjLWJkNzQtNDkwOC04NjVkLTAwOWM2MGM5MWY0NiIsImFjOnNjcCI6WzAsOCw5LDE3LDIzXSwiaWF0IjoxNjE5NDc4NTU2LCJpc3MiOiJodHRwczovL2FjY291bnRzLm5pbnRlbmRvLmNvbSIsImFjOmdydCI6NjQsInR5cCI6InRva2VuIiwiZXhwIjoxNjE5NDc5NDU2fQ.lXFbLqUIVFegSHzFvH3aLp1HOB3iwajs107YLt0MePrcqLDvmTpu_MNewGrnpX0BAAfB79lDGt7MFmi6HKcIQxacaExP7tIHYowmHBU5eDM4VSbZJq7LP8SMftRAcvDA1-bNOr3_uFhqtXP18mDDZRYfB7lEXVbcj3sdkNPrWlyic-vHwZTQ-qwMTWPLZzYwwGjage1OfpRwwC-YrU0hpgg-DIj5yTN-eCrwkp48rsQU_MOCw5--HRW90x-LU6rjK7_CgHG3Qafz4pvuYmRzDl3WWtoSGUdZCh6wF3SKta0GzReZIIic-iog3eo21vgagWbnEWz_86iYjsF9DAnPzQ",
  "scope": ["openid", "user", "user.birthday", "user.mii", "user.screenName"],
  "token_type": "Bearer",
  "id_token": "eyJqa3UiOiJodHRwczovL2FjY291bnRzLm5pbnRlbmRvLmNvbS8xLjAuMC9jZXJ0aWZpY2F0ZXMiLCJraWQiOiI1ZTkwMDRlOC1mMDNiLTRjZTEtYmU2Zi1jNzdlZTM4YTA4MjEiLCJhbGciOiJSUzI1NiJ9.eyJleHAiOjE2MTk0Nzk0NTYsImNvdW50cnkiOiJKUCIsInR5cCI6ImlkX3Rva2VuIiwiYXRfaGFzaCI6InVHUzZvQkJRQUJEN2hWMHJOdnpiS2ciLCJpYXQiOjE2MTk0Nzg1NTYsImlzcyI6Imh0dHBzOi8vYWNjb3VudHMubmludGVuZG8uY29tIiwic3ViIjoiNWFlOGY3YTc4YjBjY2E0ZCIsImF1ZCI6IjcxYjk2M2MxYjdiNmQxMTkiLCJqdGkiOiI0NmJjZmRiMy00MmUyLTRmM2UtYjhlYy1jY2YyYzNmNWZjNGYifQ.qy0QMaQ_QsCajYZkkuHlfRtWETFSUtxKfddtAsRT2EBTGpBxNV2p3VsKtWnNHduH5ZvFKa978sqBmTqjSzfPDJEF2T4JciuXvlQL73zlSPN2GxmI65K030nyvGYebd_d7XRBEEtTKGTWuhHmkk_nglToBlKWr0QG23dWGTA2phJUUU2BKiB44Gdbcq4Fopdtu9wqhtxN2lWc_OtpdHaVlmuQfOXqNHI5ohHFp4wzjrsIUOzUTVtq3Br52c1umWoFxOxnlIHdiNz1bNGWbtY9YfJHdEe1PECyj_oB8cQgkz4DDLHHVFGYz5shtGLZ1JlewVERMQw4JzBD1SiNx1FVWw",
  "expires_in": 900
}

User Info

Access Token からユーザ情報を取得する API です。

Splatoon Token 取得時に生年月日などを渡す必要があるため取得しますが、生年月日などは適当に設定してもリクエストは通ります。ここで取得した生年月日をそのまま使うと 13 歳以下のアカウントの iksm session が取得できなくなるため、この API を叩く意味は実はあまりありません。

リクエスト

パラメータ
Method GET
URL https://api.accounts.nintendo.com/2.0.0/users/me
User-Agent OnlineLounge/2.0.0 NASDKAPI iOS
Authorization Bearer

GET リクエストなのでパラメータは存在しません。

レスポンス

{
  "emailOptedIn": false,
  "analyticsPermissions": {
    "targetMarketing": {
      "updatedAt": 1595545468,
      "permitted": true
    },
    "internalAnalysis": {
      "permitted": true,
      "updatedAt": 1595545468
    }
  },
  "analyticsOptedIn": true,
  "emailOptedInUpdatedAt": 1572596527,
  "gender": "female",
  "nickname": "Salmonia",
  "screenName": "sa•••@g•••• / sal•••",
  "id": "5ae8f7a78b0cca4d",
  "analyticsOptedInUpdatedAt": 1595545468,
  "clientFriendsOptedInUpdatedAt": 1572596527,
  "region": null,
  "language": "en-US",
  "clientFriendsOptedIn": true,
  "country": "JP",
  "birthday": "1996-09-01",
  "eachEmailOptedIn": {
    "deals": {
      "optedIn": false,
      "updatedAt": 1572596527
    },
    "survey": {
      "updatedAt": 1572596527,
      "optedIn": false
    }
  },
  "candidateMiis": [],
  "createdAt": 1572596527,
  "updatedAt": 1612832536,
  "timezone": {
    "utcOffset": "+09:00",
    "name": "Asia/Tokyo",
    "id": "Asia/Tokyo",
    "utcOffsetSeconds": 32400
  },
  "emailVerified": true,
  "isChild": false,
  "mii": null
}

Splatoon Token

Splatoon 用の Session Token を発行します。パラメータに f が必要なため s2s API と flapg API を使って f の値を計算する必要があります。

ここではまだ Bearer の値がないため、空文字を指定して大丈夫です。

リクエスト

パラメータ
Method POST
URL https://api-lp1.znc.srv.nintendo.net/v3/Account/Login
X-ProductVersion 2.0.0
X-Platform iOS
Authorization Bearer
{
  "parameter": {
    "id": 5741031244955648,
    "f": "9e4e5b2e13f46e399adb5f390fd95b2b78de7e3d7e886633f8d16c479382d5e5d44caca68bc19351fe1d0b69c7",
    "requestId": "96A80E43-CC15-4724-9196-31708BC56D1D",
    "timestamp": 1648687145,
    "registrationToken": "fK0khI0DhU8KmMKxX6oixI:APA91bEcKhiHi4acYjs495cIih46knhphM1SEUJo7eBu4cCPXfBSK82XnpnDkCrowl9DWN8v7hqwN2eDnFaclhnOyUKE7N1YXtwtps4ES7oQPMQmFqb86NK_V0hblS2ojYoDpSOa7mOD"
  },
  "requestId": "25390584-A6B6-4E4E-8AD8-9C10ABFAB440"
}

2.0.0から何故かrequestIdが二つ必要になりました。ちなみに指定してもレスポンスのcorrelationIdが変わるだけで必須ではないみたい。

エラー

// 200
// Headerのフォーマットが正しくない
// ステータスコードは200なのに実質中身が400エラーなので注意
{
    "errorMessage": "Bad request.",
    "status": 9400,
    "correlationId": "56913522-00755d2d"
}

// 200
// X-ProductVersionが低い
{
    "correlationId": "b0f908ec-8363cb18",
    "errorMessage": "Upgrade required.",
    "status": 9427
}

// 200
// naIdTokenの有効期限切れ
{
    "status": 9403,
    "errorMessage": "Invalid token.",
    "correlationId": "33f960d7-324c66c2"
}

レスポンス

旧フォーマット

{
  "result": {
    "webApiServerCredential": {
      "expiresIn": 7200,
      "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOjQ3MzczNjA4MzEzODE1MDQsImV4cCI6MTYxOTQ4NTc1OCwiYXVkIjoiZjQxN2UxdGlianFkOTFjaDk5dTQ5aXd6NXNuOWNoeTMiLCJ0eXAiOiJpZF90b2tlbiIsImlhdCI6MTYxOTQ3ODU1OCwibWVtYmVyc2hpcCI6eyJhY3RpdmUiOnRydWV9LCJpc3MiOiJhcGktbHAxLnpuYy5zcnYubmludGVuZG8ubmV0In0.tjMhqXiaiO4keh5x17xJ1NKMxXw97wZ9xaJGYYOuB2U"
    },
    "user": {
      "membership": {
        "active": true
      },
      "id": 4737360831381504,
      "name": "まゆしぃのかみ",
      "supportId": "0457-8405-4211-3149-1927-5",
      "imageUri": "https://cdn-image-e0d67c509fb203858ebcb2fe3f88c2aa.baas.nintendo.com/1/6d55aa14478fbb82"
    },
    "firebaseCredential": {
      "expiresIn": 3600,
      "accessToken": ""
    }
  },
  "status": 0,
  "correlationId": "22bf5c73-fc96deb5"
}

新フォーマット

{
  "status": 0,
  "result": {
    "user": {
      "id": 6445457169973248,
      "nsaId": "91d160aa84e88da6",
      "imageUri": "https://cdn-image-e0d67c509fb203858ebcb2fe3f88c2aa.baas.nintendo.com/1/430d0e57d74d2366",
      "name": "めがねっこをあがめよ",
      "supportId": "1050-7285-6911-2261-7766-2",
      "isChildRestricted": false,
      "etag": "\"b956035ff2461637\"",
      "links": {
        "nintendoAccount": {
          "membership": {
            "active": true
          }
        },
        "friendCode": {
          "regenerable": true,
          "regenerableAt": 1513589500,
          "id": "1384-4712-4713"
        }
      },
      "permissions": {
        "presence": "FRIENDS"
      },
      "presence": {
        "state": "OFFLINE",
        "updatedAt": 1648654440,
        "logoutAt": 1648654440,
        "game": {}
      }
    },
    "webApiServerCredential": {
      "accessToken": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc0NoaWxkUmVzdHJpY3RlZCI6ZmFsc2UsIm1lbWJlcnNoaXAiOnsiYWN0aXZlIjp0cnVlfSwiYXVkIjoiZjQxN2UxdGlianFkOTFjaDk5dTQ5aXd6NXNuOWNoeTMiLCJleHAiOjE2NDg2OTYwNzQsImlhdCI6MTY0ODY4ODg3NCwiaXNzIjoiYXBpLWxwMS56bmMuc3J2Lm5pbnRlbmRvLm5ldCIsInN1YiI6NjQ0NTQ1NzE2OTk3MzI0OCwidHlwIjoiaWRfdG9rZW4ifQ.UjXgsX4lPi5_3lYCrQh475UkSho2FbsESEsJRw19X_Q",
      "expiresIn": 7200
    },
    "firebaseCredential": {
      "accessToken": "",
      "expiresIn": 3600
    }
  },
  "correlationId": "E6293799-06DC-4B73-BF7B-3EEBD7F14511-0ec95b4f"
}

かなりデータが変更されて、ログイン情報やフレンドコードなどが見れるようになりました。

Splatoon Access Token

Splatoon 用の Access Token を発行します。パラメータに f が必要なため s2s API と flapg API を使って f の値を計算する必要があります。

Bearer には Splatoon Token を指定する必要があります。

リクエスト

パラメータ
Method POST
URL https://api-lp1.znc.srv.nintendo.net/v2/Game/GetWebServiceToken
X-ProductVersion 2.0.0
X-Platform iOS
Authorization Bearer
{
  "parameter": {
    "registrationToken": "fK0khI0DhU8KmMKxX6oixI:APA91bEcKhiHi4acYjs495cIih46knhphM1SEUJo7eBu4cCPXfBSK82XnpnDkCrowl9DWN8v7hqwN2eDnFaclhnOyUKE7N1YXtwtps4ES7oQPMQmFqb86NK_V0hblS2ojYoDpSOa7mOD",
    "requestId": "70ADAB23-9FEE-4C16-8B2D-85EE2F690502",
    "timestamp": 1648689090,
    "id": 5741031244955648,
    "f": "462b2175be068ecc445a869f19fbff1f0a2962b92f405c0eec21a43909c0c17bccf0e6aa9cf7fb77b31bf208a8"
  },
  "requestId": "BB294B86-5C4A-433C-86A9-B7E54742542E"
}

こちらもrequestIdを二つ指定できるようになりました。

レスポンス

{
  "status": 0,
  "result": {
    "accessToken": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6ImI3ZXhudVJhTG05SlpaRWxHMEl5RExnMGk1MCIsImprdSI6Imh0dHBzOi8vYXBpLWxwMS56bmMuc3J2Lm5pbnRlbmRvLm5ldC92MS9XZWJTZXJ2aWNlL0NlcnRpZmljYXRlL0xpc3QifQ.eyJpc0NoaWxkUmVzdHJpY3RlZCI6ZmFsc2UsImF1ZCI6IjV2bzJpMmtteng2cHMxbDF2anNqZ25qczk5eW16Y3cwIiwiZXhwIjoxNjQ4Njk2MjkxLCJpYXQiOjE2NDg2ODkwOTEsImlzcyI6ImFwaS1scDEuem5jLnNydi5uaW50ZW5kby5uZXQiLCJqdGkiOiI1YzUyMzA0Yy1kYjYyLTRlN2UtYjk2NS00MGE0OWJjNDNiNDEiLCJzdWIiOjY0NDU0NTcxNjk5NzMyNDgsImxpbmtzIjp7Im5ldHdvcmtTZXJ2aWNlQWNjb3VudCI6eyJpZCI6IjkxZDE2MGFhODRlODhkYTYifX0sInR5cCI6ImlkX3Rva2VuIiwibWVtYmVyc2hpcCI6eyJhY3RpdmUiOnRydWV9fQ.Ba-ZzlxhReetMFpB7lHFJ_a4OW4C1CohLV3JSWjoD2V5Tj4Sl5mcPt7mSHYDkmIX_K2hHwrJNoCWxZivpamUq_rkPf8NXAwcOM0OtaqHfvVO_6knuiJ7A2N0z55T3C1h6ww2bNiwKgZ0eNcyys2O8WtKn0aNzBZOi8UiVfW2EwiN7su7IcZJrOh0f8e-IB3Yo6PKzucq1O0vEgyBAW4R2RgAstSQuCZf1gpxCmeO3IUDs4cmgQ8fawqq1QtHlg7soXEryB7FXk1xO6aUNoIss-zGJWcvINNwpf7XKtgnhaokvLT9bIqRIjWisa_9Lszb6tXkr4N_Nu7TyqF7Nij8sQ",
    "expiresIn": 7200
  },
  "correlationId": "BB294B86-5C4A-433C-86A9-B7E54742542E-119883ef"
}

エラー

// 200
{
    "status": 9400,
    "correlationId": "02094d49-a2f6b0f1",
    "errorMessage": "Bad request."
}

// 200
// Splatoon Tokenが有効期限切れ
{
    "status": 9404,
    "errorMessage": "Token expired.",
    "correlationId": "0f217900-92b9041b"
}

// 200
// Bearer Tokenがセットされていない
{
    "correlationId": "b7b6ca68-a4f79aaf",
    "status": 9406,
    "errorMessage": "Unauthorized."
}

// 200
// X-ProductVersionが低い
{
    "correlationId": "b0f908ec-8363cb18",
    "errorMessage": "Upgrade required.",
    "status": 9427
}

API

// 403
{
    "message": "api_error_authentication_error",
    "code": "AUTHENTICATION_ERROR"
}

// 403
Forbidden

フレンドリスト

パラメータ
Method POST
URL https://api-lp1.znc.srv.nintendo.net/v3/Friend/List

必要なのはAuthorization Bearerのみ。SplatoonTokenで見る感じなので有効期限は多分7200秒。

{
    "status": 9404,
    "errorMessage": "Token expired.",
    "correlationId": "A6AAFDA0-E23B-45EA-83B7-1211ECA1404E-168c6990"
}