├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── NintendoAccountBlueprint.md ├── OpenSource.md ├── Splatoon 2.paw ├── Splatoon2Blueprint.md ├── SwitchBlueprint.md └── readme.md /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at zekesnider@me.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | If you have any questions about the API or getting anything working, feel free to open an issue and I will see if I can look into it. 4 | 5 | If you have any improvements to the documentation or corrections, opening a pull request would be much appreciated. I would be especially interested in any additional research into how the initial login URL is generated. -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2017 Zeke Snider 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /NintendoAccountBlueprint.md: -------------------------------------------------------------------------------- 1 | FORMAT: 1A 2 | HOST: https://accounts.nintendo.com 3 | 4 | # Nintendo Account API Blueprint 5 | 6 | ## Session Token [/connect/1.0.0/api/session_token] 7 | 8 | ### Get session token [POST] 9 | The body of the request should be of type Form URL-Encoded. 10 | The `session_token_code` should be `session_token_code` from the login page's redirect. `session_token_code_verifier` should be `state` from the login page's redirect. `client_id` should be the client id from the URL of your login/authentication page on Nintendo's site. 11 | 12 | + Request (application/json) 13 | 14 | + Body 15 | 16 | client_id=[client id here]&session_token_code=[session token code here]&session_token_code_verifier=[verifier code here] 17 | 18 | + Response 200 (application/json) 19 | 20 | + Body 21 | 22 | { 23 | "code": "codehere", 24 | "session_token": "sessiontokenhere" 25 | } 26 | 27 | ## Service Token [/connect/1.0.0/api/token] 28 | 29 | ### Get service token [POST] 30 | 31 | `session_token` in body of request should be the `session_token` from the response of [GET /connect/1.0.0/api/session_token](#GetSessionToken). `client_id` should be retrieved from the auth page URL. 32 | 33 | + Request (application/json) 34 | + Headers 35 | Host: accounts.nintendo.com 36 | Content-Type: application/json; charset=utf-8 37 | Connection: keep-alive 38 | User-Agent: OnlineLounge/1.0.4 NASDKAPI iOS 39 | Accept: application/json 40 | Accept-Language: en-US 41 | Accept-Encoding: gzip, deflate 42 | 43 | + Body 44 | 45 | { 46 | "client_id":"[clientidhere]", 47 | "grant_type":"urn:ietf:params:oauth:grant-type:jwt-bearer-session-token", 48 | "session_token":"Nintendo Account Session Token Here" 49 | } 50 | 51 | + Response 200 (application/json) 52 | 53 | + Body 54 | 55 | { 56 | "token_type": "Bearer", 57 | "expires_in": 900, 58 | "access_token": "accesstokenhere", 59 | "id_token": "idtokenhere", 60 | "scope": [ 61 | "openid", 62 | "user", 63 | "user.birthday", 64 | "user.mii", 65 | "user.screenName" 66 | ] 67 | } 68 | 69 | 70 | ## My user details [/2.0.0/users/me] 71 | 72 | ### Get my user details [GET] 73 | 74 | Note: personal information has been redacted from the response body. 75 | 76 | Bearer token is `access_token` from the response of [GET /connect/1.0.0/api/token](#GetServiceToken) 77 | 78 | + Request 79 | + Headers 80 | 81 | Host: api.accounts.nintendo.com 82 | Connection: keep-alive 83 | Accept: application/json 84 | User-Agent: OnlineLounge/1.0.4 NASDKAPI iOS 85 | Accept-Language: en-US 86 | Authorization: Bearer [Bearer token here] 87 | Accept-Encoding: gzip, deflate 88 | 89 | + Response 200 (application/json) 90 | 91 | + Body 92 | ```json 93 | { 94 | "region": null, 95 | "isChild": false, 96 | "timezone": { 97 | "name": "America/Los_Angeles", 98 | "utcOffsetSeconds": -25200, 99 | "id": "America/Los_Angeles", 100 | "utcOffset": "-07:00" 101 | }, 102 | "mii": { 103 | "clientId": "clientidhere", 104 | "storeData": { 105 | "3": "storedatahere" 106 | }, 107 | "id": "mii_idhere", 108 | "imageUriTemplate": "https://{imageOrigin}/1.0.0/miis{/id}/image{/etag}.{format}{?type,expression,width,bgColor,clothesColor,cameraXRotate,cameraYRotate,cameraZRotate,characterXRotate,characterYRotate,characterZRotate,lightXDirection,lightYDirection,lightZDirection,lightDirectionMode,splitDepthOffset,splitMode,instanceCount,instanceRotationMode}", 109 | "imageOrigin": "cdn-mii.accounts.nintendo.com", 110 | "etag": "etaghere", 111 | "updatedAt": 1455678671, 112 | "favoriteColor": "green", 113 | "type": "profile" 114 | }, 115 | "clientFriendsOptedIn": true, 116 | "emailVerified": true, 117 | "updatedAt": 1488606410, 118 | "screenName": "censoredemailhere / censoredusernamehere", 119 | "emailOptedInUpdatedAt": 1455678552, 120 | "emailOptedIn": true, 121 | "clientFriendsOptedInUpdatedAt": 0, 122 | "nickname": "Zeke", 123 | "eachEmailOptedIn": { 124 | "survey": { 125 | "updatedAt": 1494449469, 126 | "optedIn": true 127 | }, 128 | "deals": { 129 | "optedIn": true, 130 | "updatedAt": 1494449469 131 | } 132 | }, 133 | "analyticsOptedInUpdatedAt": 1455678552, 134 | "country": "US", 135 | "gender": "male", 136 | "birthday": "yyyy-mm-dd", 137 | "id": "idhere", 138 | "candidateMiis": [ 139 | { 140 | "updatedAt": 1455678671, 141 | "favoriteColor": "green", 142 | "type": "candidate", 143 | "clientId": "clientidhere", 144 | "storeData": { 145 | "3": "storedatahere" 146 | }, 147 | "id": "idhere", 148 | "imageUriTemplate": "https://{imageOrigin}/1.0.0/miis{/id}/image{/etag}.{format}{?type,expression,width,bgColor,clothesColor,cameraXRotate,cameraYRotate,cameraZRotate,characterXRotate,characterYRotate,characterZRotate,lightXDirection,lightYDirection,lightZDirection,lightDirectionMode,splitDepthOffset,splitMode,instanceCount,instanceRotationMode}", 149 | "imageOrigin": "cdn-mii.accounts.nintendo.com", 150 | "etag": "etaghere" 151 | }, 152 | { 153 | "type": "candidate", 154 | "favoriteColor": "yellowgreen", 155 | "updatedAt": 1492719363, 156 | "etag": "etaghere", 157 | "imageOrigin": "cdn-mii.accounts.nintendo.com", 158 | "imageUriTemplate": "https://{imageOrigin}/1.0.0/miis{/id}/image{/etag}.{format}{?type,expression,width,bgColor,clothesColor,cameraXRotate,cameraYRotate,cameraZRotate,characterXRotate,characterYRotate,characterZRotate,lightXDirection,lightYDirection,lightZDirection,lightDirectionMode,splitDepthOffset,splitMode,instanceCount,instanceRotationMode}", 159 | "id": "idhere", 160 | "storeData": { 161 | "3": "storedatahere" 162 | }, 163 | "clientId": "clientidhere" 164 | } 165 | ], 166 | "createdAt": 1455678552, 167 | "analyticsOptedIn": true, 168 | "language": "en-US" 169 | } 170 | ``` 171 | -------------------------------------------------------------------------------- /OpenSource.md: -------------------------------------------------------------------------------- 1 | # Open Source Dependencies 2 | 3 | This is a list of all the respositories listed under the "acknowledgements" link at the bottom of the splatoon pages in the the app, and settings menu from the main page of the app. Since those pages only list the licenses, I have compiled a list with the github/npm links. 4 | 5 | Based on the open source dependencies, I think we can safely assume that the Nintendo is using Node for the back-end API, and React for the front-end web view in the Splatoon section of the app. The main app itself is built using Xamarin (C#). Opus is used as the codec for the voice chat features. 6 | 7 | 8 | ## Switch App 9 | * Echo Cancellation Program 10 | * [libSRTP](https://github.com/cisco/libsrtp) (Note: Using version commited before [Mar 26, 2017](https://github.com/cisco/libsrtp/commit/445c1c94dc3df48fb633779d1b5d0b743bf522a4)) 11 | * [Opus](https://github.com/xiph/opus) 12 | * [WebRTC AudioProcessing](https://github.com/jhgorse/webrtc-audio-processing) 13 | * [Breakpad](https://chromium.googlesource.com/breakpad/breakpad/) 14 | * [Curl](https://curl.haxx.se) 15 | * [Libdisasm](http://bastard.sourceforge.net/libdisasm.html) 16 | * [gflags](https://github.com/gflags/gflags) 17 | * [Linux SysCall Support](https://chromium.googlesource.com/linux-syscall-support/) 18 | * [musl](https://www.musl-libc.org) 19 | * [CarouselView.FormsPlugin](https://github.com/alexrainman/nativescript-carousel-view) 20 | * [Lottie](https://airbnb.design/lottie/) 21 | * [Plugins for Xamarin](https://github.com/jamesmontemagno/Xamarin.Plugins) 22 | * [Hockey SDK](https://hockeyapp.net) 23 | * [Math.NET Numerics](https://numerics.mathdotnet.com) 24 | * [Json.NET](http://www.newtonsoft.com/json) 25 | * [PCLCrypto](https://github.com/AArnott/PCLCrypto) 26 | * [P/Invoke](https://github.com/AArnott/pinvoke) 27 | * [Share Plugin](https://github.com/jguertl/SharePlugin) 28 | * [Validation](https://github.com/AArnott/Validation) 29 | * [Xamarin Forms Lab](https://github.com/XLabs/Xamarin-Forms-Labs) 30 | * [Xamarin SDK](https://open.xamarin.com) 31 | * [FFImageLoading](https://github.com/luberda-molinet/FFImageLoading) 32 | * [SkiaSharp](https://github.com/mono/SkiaSharp) 33 | * [WebP.Touch](https://github.com/luberda-molinet/WebP.Touch) 34 | * [ModernHttpClient](https://github.com/paulcbetts/ModernHttpClient) 35 | 36 | ## Splatoon 2 37 | * [ASAP](https://github.com/kriskowal/asap) 38 | * [babel-polyfill](https://github.com/babel/babel) 39 | * [babel-runtime](https://github.com/babel/babel) 40 | * [chain-function](https://github.com/jquense/chain-function) 41 | * [consolidated-events](https://github.com/lencioni/consolidated-events) 42 | * [core-js](https://github.com/zloirock/core-js) (Note: Using version commited [before Feb 24, 2016](https://github.com/zloirock/core-js/commits/master/LICENSE)) 43 | * [create-react-class](https://www.npmjs.com/package/create-react-class) 44 | * [deep-equal](https://github.com/substack/node-deep-equal) 45 | * [dom-helpers](https://github.com/react-bootstrap/dom-helpers) 46 | * [encoding](https://github.com/andris9/encoding) 47 | * [exenv](https://github.com/JedWatson/exenv) 48 | * [fbjs](https://github.com/facebook/fbjs/tree/master/packages/fbjs) 49 | * [history](https://github.com/ReactTraining/history) 50 | * [hoist-non-react-statics](https://github.com/mridgway/hoist-non-react-statics) 51 | * [iconv-lite](https://github.com/ashtuchkin/iconv-lite) 52 | * [immutability-helper](https://github.com/kolodny/immutability-helper) 53 | * [immutable](https://github.com/facebook/immutable-js) 54 | * [invariant](https://github.com/zertosh/invariant) 55 | * [is-stream](https://github.com/sindresorhus/is-stream) 56 | * [isarray](https://github.com/juliangruber/isarray) 57 | * [isomorphic-fetch](https://github.com/matthew-andrews/isomorphic-fetch) 58 | * [js-tokens](https://github.com/lydell/js-tokens) 59 | * [lodash](https://github.com/lodash/lodash) 60 | * [lodash-es](https://www.npmjs.com/package/lodash-es) 61 | * [loose-envify](https://github.com/zertosh/loose-envify) 62 | * [moment](https://github.com/moment/moment) 63 | * [mustache](https://github.com/janl/mustache.js) 64 | * [node-fetch](https://github.com/bitinn/node-fetch) 65 | * [object-assign](https://github.com/sindresorhus/object-assign) 66 | * [path-to-regexp](https://github.com/pillarjs/path-to-regexp) 67 | * [promise](https://github.com/then/promise) 68 | * [prop-types](https://github.com/facebook/prop-types) 69 | * [react](https://github.com/facebook/react) 70 | * [react-dom](https://www.npmjs.com/package/react-dom) 71 | * [react-helmet](https://github.com/nfl/react-helmet) 72 | * [react-redux](https://github.com/reactjs/react-redux) 73 | * [react-router](https://github.com/ReactTraining/react-router) 74 | * [react-router-dom](https://www.npmjs.com/package/react-router-dom) 75 | * [react-router-redux](https://github.com/ReactTraining/react-router/tree/master/packages/react-router-redux) 76 | * [react-side-effect](https://github.com/gaearon/react-side-effect) 77 | * [react-transition-group](https://github.com/reactjs/react-transition-group) 78 | * [react-waypoint](https://github.com/brigade/react-waypoint) 79 | * [reduce-reducers](https://github.com/acdlite/reduce-reducers) 80 | * [redux](https://github.com/reactjs/redux) 81 | * [redux-actions](https://github.com/acdlite/redux-actions) 82 | * [redux-saga](https://github.com/redux-saga/redux-saga) 83 | * [regenerator-runtime](https://github.com/facebook/regenerator/tree/master/packages/regenerator-runtime) 84 | * [resolve-pathname](https://github.com/mjackson/resolve-pathname) 85 | * [setimmediate](https://github.com/YuzuJS/setImmediate) 86 | * [shallowequal](https://github.com/dashed/shallowequal) 87 | * [symbol-observable](https://github.com/benlesh/symbol-observable) 88 | * [ua-parser-js](https://github.com/faisalman/ua-parser-js) 89 | * [url-search-params](https://github.com/WebReflection/url-search-params) 90 | * [uuid](https://github.com/broofa/node-uuid) 91 | * [value-equal](https://github.com/mjackson/value-equal) 92 | * [warning](https://github.com/BerkeleyTrue/warning) 93 | * [whatwg-fetch](https://github.com/github/fetch) -------------------------------------------------------------------------------- /Splatoon 2.paw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZekeSnider/NintendoSwitchRESTAPI/409b82df5bd6f478bec07fad7362266e11d4c072/Splatoon 2.paw -------------------------------------------------------------------------------- /SwitchBlueprint.md: -------------------------------------------------------------------------------- 1 | FORMAT: 1A 2 | HOST: https://api-lp1.znc.srv.nintendo.net 3 | 4 | # Nintendo Switch API Blueprint 5 | 6 | ## Account Login [/v1/Account/Login] 7 | 8 | It is currently not possible to generate the `f` parameter for this endpoint without using the Nintendo Switch app. For more details, see `f` details below. 9 | 10 | If you wish to use this API, extract the needed response from your phone using something like [Telerik Fiddler](http://www.telerik.com/fiddler) or [mitmproxy](https://mitmproxy.org). 11 | 12 | Or, if you wish to use exclusively the [_Splatoon 2 API_](Splatoon2Blueprint.md), extract your iksm_session from a response while on the game specific integration. 13 | 14 | ### Login to Account [POST] 15 | 16 | `naIdToken` is `id_token` from the response of [GET /connect/1.0.0/api/token](#GetServiceToken). 17 | `naBirthday` should be the birthday on the account used to login in the specified format. 18 | `timestamp` is the current [unix (epoch) timestamp](https://www.epochconverter.com). 19 | `requestId` is a generated [UUID version 4](https://www.uuidgenerator.net/version4). 20 | `f` is a parameter which is generated by the switch app. It used to be able to be generated by the splatnet2statink API, but the parameter has recently changed so this is not currently possible. For now, the only way to retrieve `f` is by using mitmproxy or similar with a device running the Nintendo switch app. For more info on `f` see [splatnet2statink API](https://github.com/frozenpandaman/splatnet2statink/wiki/api-docs) and [this issue](https://github.com/frozenpandaman/splatnet2statink/issues/56). 21 | 22 | + Request 23 | 24 | + Body 25 | { 26 | "parameter": { 27 | "language": "en-US", 28 | "naBirthday": "yyyy-mm-dd", 29 | "naCountry": "US", 30 | "naIdToken": "[tokengoeshere]", 31 | "requestId": "123e4567-e89b-12d3-a456-426655440000", 32 | "timestamp": 1537249847, 33 | "f": "[fparameterhere]" 34 | } 35 | } 36 | 37 | + Response 200 (application/json) 38 | 39 | + Body 40 | 41 | { 42 | "result": { 43 | "user": { 44 | "imageUri": "[userimagehere]", 45 | "supportId": "[supportidhere]", 46 | "name": "[namehere]", 47 | "id": [useridhere] 48 | }, 49 | "firebaseCredential": { 50 | "accessToken": "firebasetokenhere", 51 | "expiresIn": 3600 52 | }, 53 | "webApiServerCredential": { 54 | "accessToken": "webapitokenhere", 55 | "expiresIn": 7200 56 | } 57 | }, 58 | "status": 0, 59 | "correlationId": "61becf03-0ae45082" 60 | } 61 | 62 | ## Game List [/v1/Game/ListWebServices] 63 | 64 | ### Get game list [POST] 65 | 66 | Web API Access Token should be webApiServerCredential["accesstoken"] from [POST /v1/Account/Login](#LoginAccount). 67 | 68 | + Request 69 | 70 | + Headers 71 | 72 | Host: api-lp1.znc.srv.nintendo.net 73 | Content-Type: application/json; charset=utf-8 74 | Content-Length: 0 75 | Connection: keep-alive 76 | X-ProductVersion: 1.0.4 77 | Accept: application/json 78 | User-Agent: com.nintendo.znca/1.0.4 (iOS/10.3.3) 79 | Accept-Language: en-us 80 | X-Platform: iOS 81 | Authorization: Bearer [Web API Access Token Goes here] 82 | 83 | + Response 200 (application/json) 84 | 85 | + Body 86 | 87 | { 88 | "status": 0, 89 | "correlationId": "d02af7dc-bf169f85", 90 | "result": [ 91 | { 92 | "whiteList": [ 93 | "app.splatoon2.nintendo.net" 94 | ], 95 | "id": 5741031244955648, 96 | "uri": "https://app.splatoon2.nintendo.net/", 97 | "name": "Splatoon 2", 98 | "imageUri": "https://cdn.znc.srv.nintendo.net/gameWebServices/splatoon2/images/usEn/banner.png" 99 | } 100 | ] 101 | } 102 | 103 | ## Game Web Service Token [/v1/Game/GetWebServiceToken] 104 | 105 | ### Get Game Web Service Token [POST] 106 | 107 | Web API Access Token should be webApiServerCredential["accesstoken"] from [POST /v1/Account/Login](#LoginAccount). 108 | 109 | + Request (application/json) 110 | + Headers 111 | ``` 112 | Host: api-lp1.znc.srv.nintendo.net 113 | Content-Type: application/json; charset=utf-8 114 | X-ProductVersion: 1.0.4 115 | Authorization: Bearer [Web API Access Token Goes here] 116 | Accept-Language: en-us 117 | Accept-Encoding: gzip, deflate 118 | Accept: application/json; charset=utf-8 119 | User-Agent: com.nintendo.znca/1.0.4 (iOS/10.3.3) 120 | Connection: keep-alive 121 | X-Platform: iOS 122 | ``` 123 | + Body 124 | ```json 125 | { 126 | "parameter": { 127 | "id": [gameIDgoeshere] 128 | } 129 | } 130 | ``` 131 | 132 | + Response 200 (application/json) 133 | 134 | + Body 135 | 136 | { 137 | "result": { 138 | "accessToken": "accesstokenwillbehere", 139 | "expiresIn": 7200 140 | }, 141 | "status": 0, 142 | "correlationId": "d91de63c-f186fb6f" 143 | } 144 | 145 | ## Active Event ID [/v1/Event/GetActiveEventId] 146 | 147 | ### Get Active Event ID [GET] 148 | 149 | Web API Access Token should be webApiServerCredential["accesstoken"] from [POST /v1/Account/Login](#LoginAccount). 150 | 151 | I think this is used for the current lobby events. 152 | 153 | + Response 200 (application/json) 154 | 155 | + Body 156 | 157 | { 158 | "status": 0, 159 | "result": { 160 | "eventId": 0 161 | }, 162 | "correlationId": "6c63576e-3e41f536" 163 | } 164 | 165 | ## Event List [/v1/Event/List] 166 | 167 | ### Get all events [POST] 168 | 169 | Web API Access Token should be webApiServerCredential["accesstoken"] from [POST /v1/Account/Login](#LoginAccount). 170 | 171 | Obtains all joinable lobbies. 172 | 173 | + Request 174 | 175 | + Headers 176 | 177 | ``` 178 | X-ProductVersion: 1.1.0 179 | X-Platform: Android 180 | User-Agent: com.nintendo.znca/1.1.0 (Android/7.0) 181 | Accept: application/json 182 | Authorization: Bearer [Web API access token] 183 | Content-Type: application/json; charset=utf-8 184 | Content-Length: 0 185 | Host: api-lp1.znc.srv.nintendo.net 186 | Connection: Keep-Alive 187 | Accept-Encoding: gzip 188 | ``` 189 | 190 | + Response 200 (application/json) 191 | 192 | + Body 193 | 194 | ```json 195 | { 196 | "correlationId": "499ab925-56d67923", 197 | "status": 0, 198 | "result": [ 199 | { 200 | "allowJoinGameWithoutCoral": false, 201 | "members": [ 202 | { 203 | "isPlaying": false, 204 | "isInvited": true, 205 | "imageUri": "https://cdn-image-e0d67c509fb203858ebcb2fe3f88c2aa.baas.nintendo.com/1/ae160604808ae5ad", 206 | "id": 6403160302157824, 207 | "name": "Virepri" 208 | }, 209 | { 210 | "isPlaying": true, 211 | "isInvited": true, 212 | "imageUri": "https://cdn-image-e0d67c509fb203858ebcb2fe3f88c2aa.baas.nintendo.com/1/26f4a1e2a08ee69b", 213 | "id": 5409588421591040, 214 | "name": "TPoS-Shin" 215 | } 216 | ], 217 | "gameStatus": { 218 | "isClosed": false 219 | }, 220 | "id": 5714341576835072, 221 | "passCode": "", 222 | "shareUri": "https://lounge.nintendo.com/room/DDx46PX1Ck", 223 | "ownerUserId": 5409588421591040, 224 | "game": { 225 | "instructionPageUri": "", 226 | "minMember": 1, 227 | "imageUri": "", 228 | "maxMember": 1, 229 | "selectedGameMode": { 230 | "instructionPageUri": "https://web-lp1.znc.srv.nintendo.net/games/hac-aab6b/gameModes/SalmonRun/howtoJoin/index.html", 231 | "minMember": 1, 232 | "imageUri": "https://cdn.znc.srv.nintendo.net/games/hac-aab6b/gameModes/SalmonRun/images/usEn/banner.jpg", 233 | "maxMember": 1, 234 | "id": 5, 235 | "name": "Salmon Run", 236 | "ogpTitle": "Join {room_name} now!" 237 | }, 238 | "id": 5741031244955648, 239 | "voiceChatBackgroundImageUri": "https://cdn.znc.srv.nintendo.net/games/hac-aab6b/voiceChat/background.webp", 240 | "name": "Splatoon 2", 241 | "officialSiteUri": "http://www.nintendo.com/games/detail/splatoon-2-switch" 242 | }, 243 | "description": "", 244 | "name": "TPoS-Shin's Room" 245 | } 246 | ] 247 | } 248 | ``` 249 | 250 | ## Show Event [/v1/Event/Show] 251 | 252 | ### [POST] 253 | 254 | Web API Access Token should be webApiServerCredential["accesstoken"] from [POST /v1/Account/Login](#LoginAccount). 255 | 256 | + Request (application/json) 257 | 258 | + Headers 259 | 260 | ``` 261 | X-ProductVersion: 1.1.0 262 | X-Platform: Android 263 | User-Agent: com.nintendo.znca/1.1.0 (Android/7.0) 264 | Accept: application/json 265 | Authorization: Bearer [Web API Access Token] 266 | Content-Type: application/json; charset=utf-8 267 | Content-Length: 37 268 | Host: api-lp1.znc.srv.nintendo.net 269 | Connection: Keep-Alive 270 | Accept-Encoding: gzip 271 | ``` 272 | 273 | + Body 274 | 275 | ```json 276 | { 277 | "parameter":{ 278 | "id":5714341576835072 279 | } 280 | } 281 | ``` 282 | 283 | + Response 200 (application/json) 284 | 285 | + Body 286 | 287 | ```json 288 | { 289 | "result": { 290 | "passCode": "", 291 | "id": 5714341576835072, 292 | "description": "", 293 | "ownerUserId": 5409588421591040, 294 | "shareUri": "https://lounge.nintendo.com/room/DDx46PX1Ck", 295 | "members": [ 296 | { 297 | "id": 6403160302157824, 298 | "name": "Virepri", 299 | "isPlaying": false, 300 | "isInvited": true, 301 | "imageUri": "https://cdn-image-e0d67c509fb203858ebcb2fe3f88c2aa.baas.nintendo.com/1/ae160604808ae5ad" 302 | }, 303 | { 304 | "id": 5409588421591040, 305 | "name": "TPoS-Shin", 306 | "isPlaying": true, 307 | "isInvited": true, 308 | "imageUri": "https://cdn-image-e0d67c509fb203858ebcb2fe3f88c2aa.baas.nintendo.com/1/26f4a1e2a08ee69b" 309 | } 310 | ], 311 | "allowJoinGameWithoutCoral": false, 312 | "name": "TPoS-Shin's Room", 313 | "game": { 314 | "officialSiteUri": "http://www.nintendo.com/games/detail/splatoon-2-switch", 315 | "id": 5741031244955648, 316 | "minMember": 1, 317 | "imageUri": "", 318 | "voiceChatBackgroundImageUri": "https://cdn.znc.srv.nintendo.net/games/hac-aab6b/voiceChat/background.webp", 319 | "instructionPageUri": "", 320 | "maxMember": 1, 321 | "selectedGameMode": { 322 | "id": 5, 323 | "minMember": 1, 324 | "imageUri": "https://cdn.znc.srv.nintendo.net/games/hac-aab6b/gameModes/SalmonRun/images/usEn/banner.jpg", 325 | "name": "Salmon Run", 326 | "ogpTitle": "Join {room_name} now!", 327 | "maxMember": 1, 328 | "instructionPageUri": "https://web-lp1.znc.srv.nintendo.net/games/hac-aab6b/gameModes/SalmonRun/howtoJoin/index.html" 329 | }, 330 | "name": "Splatoon 2" 331 | }, 332 | "gameStatus": { 333 | "isClosed": false 334 | } 335 | }, 336 | "correlationId": "4b0d88f2-e642524a", 337 | "status": 0 338 | } 339 | ``` 340 | 341 | ## Invite to Event [/v1/Event/Invite] 342 | 343 | ### Invite to Event [POST] 344 | 345 | Web API Access Token should be webApiServerCredential["accesstoken"] from [POST /v1/Account/Login](#LoginAccount). 346 | 347 | + Request 348 | 349 | + Headers 350 | 351 | ``` 352 | X-ProductVersion: 1.1.0 353 | X-Platform: Android 354 | User-Agent: com.nintendo.znca/1.1.0 (Android/7.0) 355 | Accept: application/json 356 | Authorization: Bearer [Web API Access Token] 357 | Content-Type: application/json; charset=utf-8 358 | Content-Length: 71 359 | Host: api-lp1.znc.srv.nintendo.net 360 | Connection: Keep-Alive 361 | Accept-Encoding: gzip 362 | ``` 363 | 364 | + Body 365 | 366 | ```json 367 | { 368 | "parameter": { 369 | "id": 5123588421058560, 370 | "users": [ 371 | { 372 | "id": 5409588421591040 373 | } 374 | ] 375 | } 376 | } 377 | ``` 378 | 379 | + Response 380 | 381 | + Body 382 | 383 | ```json 384 | { 385 | "result": {}, 386 | "status": 0, 387 | "correlationId": "ae0f0cf7-f03bfb4e" 388 | } 389 | ``` 390 | 391 | ## Register Device [/v1/Notification/RegisterDevice] 392 | 393 | ### Register device for notifications [POST] 394 | 395 | Web API Access Token should be webApiServerCredential["accesstoken"] from [POST /v1/Account/Login](#LoginAccount). 396 | 397 | Device ID is generated in-app. Extract it from this call on your device. 398 | 399 | I don't know why you'd use this, either, unless you're the phone. 400 | 401 | + Request (application/json) 402 | 403 | + Headers 404 | 405 | ``` 406 | X-ProductVersion: 1.1.0 407 | X-Platform: Android 408 | User-Agent: com.nintendo.znca/1.1.0 (Android/7.0) 409 | Accept: application/json 410 | Authorization: Bearer [Web API access token] 411 | Content-Type: application/json 412 | Content-Length: 190 413 | Host: api-lp1.znc.srv.nintendo.net 414 | Connection: Keep-Alive 415 | Accept-Encoding: gzip 416 | ``` 417 | 418 | + Body 419 | 420 | ```json 421 | { 422 | "parameter": { 423 | "registrationToken":"[Device ID]" 424 | } 425 | } 426 | ``` 427 | 428 | + Response 200 (application/json) 429 | 430 | + Body 431 | 432 | ```json 433 | { 434 | "correlationId":"a7c8abce-e0427bfb", 435 | "result": {}, 436 | "status":0 437 | } 438 | ``` 439 | 440 | ## Join VOIP [/v1/Voip/Join] 441 | 442 | ### Join VoIP. [POST] 443 | 444 | Web API Access Token should be webApiServerCredential["accesstoken"] from [POST /v1/Account/Login](#LoginAccount). 445 | 446 | Device ID is generated in-app. Extract it from [POST /v1/Notification/RegisterDevice](#RegisterDevice) on your device. 447 | 448 | + Request (application/json) 449 | 450 | + Headers 451 | 452 | ``` 453 | X-ProductVersion: 1.1.0 454 | X-Platform: Android 455 | User-Agent: com.nintendo.znca/1.1.0 (Android/7.0) 456 | Accept: application/json 457 | Authorization: Bearer [Web API Access Token] 458 | Content-Type: application/json; charset=utf-8 459 | Content-Length: 230 460 | Host: api-lp1.znc.srv.nintendo.net 461 | Connection: Keep-Alive 462 | Accept-Encoding: gzip 463 | ``` 464 | 465 | + Body 466 | 467 | ```json 468 | { 469 | "parameter": { 470 | "id": 6088424361558016, 471 | "deviceIdentifier": "[Device ID]", 472 | "muteUserIds": null 473 | } 474 | } 475 | ``` 476 | 477 | + Response 200 (application/json) 478 | 479 | + Body 480 | 481 | ```json 482 | { 483 | "result": { 484 | "remoteKeyHex": "a61216832df4c22914c2a976730d399b75cd0f0f247f38f45781945c7cc8", 485 | "remoteSsrc": 1151231983, 486 | "localKeyHex": "922509928cb51eb163a4b4feff7339ef1f1b23f23556d4eae161128a6e61", 487 | "channelId": 0, 488 | "remotePort": 2001, 489 | "localSsrc": 685664239, 490 | "remoteHost": "104.154.86.184" 491 | }, 492 | "status": 0, 493 | "correlationId": "bc3021dd-528df2ad" 494 | } 495 | ``` 496 | 497 | ## Get VOIP configuration [/v1/Voip/GetConfig] 498 | 499 | ### Get VoIP configuration [POST] 500 | 501 | Web API Access Token should be webApiServerCredential["accesstoken"] from [POST /v1/Account/Login](#LoginAccount). 502 | 503 | + Request (application/json) 504 | 505 | + Headers 506 | 507 | ``` 508 | X-ProductVersion: 1.1.0 509 | X-Platform: Android 510 | User-Agent: com.nintendo.znca/1.1.0 (Android/7.0) 511 | Accept: application/json 512 | Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJmNDE3ZTF0aWJqcWQ5MWNoOTl1NDlpd3o1c245Y2h5MyIsInN1YiI6NjQwMzE2MDMwMjE1NzgyNCwiaXNzIjoiYXBpLWxwMS56bmMuc3J2Lm5pbnRlbmRvLm5ldCIsImlhdCI6MTUwNzQyNDU4MywidHlwIjoiaWRfdG9rZW4iLCJleHAiOjE1MDc0MzE3ODN9.MHZxeCuV_cWm-9IyXXtmMDiLaS316tPjUg1v6B9aBtg 513 | Content-Type: application/json; charset=utf-8 514 | Content-Length: 230 515 | Host: api-lp1.znc.srv.nintendo.net 516 | Connection: Keep-Alive 517 | Accept-Encoding: gzip 518 | ``` 519 | 520 | + Body 521 | 522 | ```json 523 | { 524 | "parameter": { 525 | "platform": "Android", 526 | "model": "SM-G935U", 527 | "product": "hero2qlteue", 528 | "device": "hero2qlteue", 529 | "manufacturer": "samsung", 530 | "versionRelease": "7.0", 531 | "versionSdkInt": 24 532 | } 533 | } 534 | ``` 535 | 536 | + Response 200 (application/json) 537 | 538 | + Body 539 | 540 | ```json 541 | { 542 | "status": 0, 543 | "correlationId": "d806c612-3f51520f", 544 | "result": { 545 | "androidAudioMode": 3, 546 | "smaec": 1, 547 | "androidRecordingPreset": 4, 548 | "smaecEc": true, 549 | "androidStreamType": 0 550 | } 551 | } 552 | ``` 553 | 554 | ## Leave VOIP [/v1/Voip/Leave] 555 | 556 | ### Leave VoIP [POST] 557 | 558 | Web API Access Token should be webApiServerCredential["accesstoken"] from [POST /v1/Account/Login](#LoginAccount). 559 | 560 | Device ID is generated in-app. Extract it from [POST /v1/Notification/RegisterDevice](#RegisterDevice) on your device. 561 | 562 | ID should be the group ID, obtained via [POST /v1/Event/List](#GetEventList) 563 | 564 | + Request (application/json) 565 | 566 | + Headers 567 | 568 | ``` 569 | X-ProductVersion: 1.1.0 570 | X-Platform: Android 571 | User-Agent: com.nintendo.znca/1.1.0 (Android/7.0) 572 | Accept: application/json 573 | Authorization: Bearer [Web API Access Token] 574 | Content-Type: application/json; charset=utf-8 575 | Content-Length: 230 576 | Host: api-lp1.znc.srv.nintendo.net 577 | Connection: Keep-Alive 578 | Accept-Encoding: gzip 579 | ``` 580 | 581 | + Body 582 | 583 | ```json 584 | { 585 | "parameter": { 586 | "id": 5123588421058560, 587 | "deviceIdentifier": "[Device ID]" 588 | } 589 | } 590 | ``` 591 | 592 | + Response 200 (application/json) 593 | 594 | + Body 595 | 596 | ```json 597 | { 598 | "result": {}, 599 | "status": 0, 600 | "correlationId": "85906060-9e307e23" 601 | } 602 | ``` 603 | 604 | ## Obtain friends list [/v1/User/List] 605 | 606 | ### Obtain Friends List [POST] 607 | 608 | Web API Access Token should be webApiServerCredential["accesstoken"] from [POST /v1/Account/Login](#LoginAccount). 609 | 610 | + Request 611 | 612 | + Headers 613 | 614 | ``` 615 | X-ProductVersion: 1.1.0 616 | X-Platform: Android 617 | User-Agent: com.nintendo.znca/1.1.0 (Android/7.0) 618 | Accept: application/json 619 | Authorization: Bearer [Web API Access Token] 620 | Content-Type: application/json; charset=utf-8 621 | Content-Length: 230 622 | Host: api-lp1.znc.srv.nintendo.net 623 | Connection: Keep-Alive 624 | Accept-Encoding: gzip 625 | ``` 626 | 627 | + Response 200 (application/json) 628 | 629 | + Body 630 | 631 | ```json 632 | { 633 | "status": 0, 634 | "correlationId": "fffa6813-70e8fde9", 635 | "result": [ 636 | { 637 | "name": "Virepri", 638 | "isServiceUser": true, 639 | "supportId": "0664-9173-0838-4959-9123-9", 640 | "isFriend": false, 641 | "lastSeenAt": 0, 642 | "imageUri": "https://cdn-image-e0d67c509fb203858ebcb2fe3f88c2aa.baas.nintendo.com/1/ae160604808ae5ad", 643 | "id": 6403160302157824, 644 | "isFavoriteFriend": false 645 | }, 646 | { 647 | "name": "Centzilius", 648 | "isServiceUser": true, 649 | "isFriend": true, 650 | "lastSeenAt": 0, 651 | "imageUri": "https://cdn-image-e0d67c509fb203858ebcb2fe3f88c2aa.baas.nintendo.com/1/3b0937a3e09e6517", 652 | "id": 6330250325655552, 653 | "isFavoriteFriend": false 654 | }, 655 | { 656 | "name": "TPoS-Shin", 657 | "isServiceUser": true, 658 | "isFriend": true, 659 | "lastSeenAt": 0, 660 | "imageUri": "https://cdn-image-e0d67c509fb203858ebcb2fe3f88c2aa.baas.nintendo.com/1/26f4a1e2a08ee69b", 661 | "id": 5409588421591040, 662 | "isFavoriteFriend": false 663 | }, 664 | { 665 | "name": "AJ", 666 | "isServiceUser": false, 667 | "isFriend": true, 668 | "lastSeenAt": 0, 669 | "imageUri": "https://cdn-image-e0d67c509fb203858ebcb2fe3f88c2aa.baas.nintendo.com/1/aa25d9cdc3f03350", 670 | "id": 0, 671 | "isFavoriteFriend": false 672 | }, 673 | { 674 | "name": "Some1CP", 675 | "isServiceUser": true, 676 | "isFriend": true, 677 | "lastSeenAt": 0, 678 | "imageUri": "https://cdn-image-e0d67c509fb203858ebcb2fe3f88c2aa.baas.nintendo.com/1/4a4af58feed30a0e", 679 | "id": 6612396567166976, 680 | "isFavoriteFriend": false 681 | }, 682 | { 683 | "name": "Atomic", 684 | "isServiceUser": true, 685 | "isFriend": true, 686 | "lastSeenAt": 0, 687 | "imageUri": "https://cdn-image-e0d67c509fb203858ebcb2fe3f88c2aa.baas.nintendo.com/1/b55b17be67346d04", 688 | "id": 4877687744102400, 689 | "isFavoriteFriend": true 690 | }, 691 | { 692 | "name": "Shags", 693 | "isServiceUser": false, 694 | "isFriend": true, 695 | "lastSeenAt": 0, 696 | "imageUri": "https://cdn-image-e0d67c509fb203858ebcb2fe3f88c2aa.baas.nintendo.com/1/34924d955f2dbe21", 697 | "id": 0, 698 | "isFavoriteFriend": false 699 | }, 700 | { 701 | "name": "acid treez", 702 | "isServiceUser": true, 703 | "isFriend": true, 704 | "lastSeenAt": 0, 705 | "imageUri": "https://cdn-image-e0d67c509fb203858ebcb2fe3f88c2aa.baas.nintendo.com/1/c8e8ed04dfb82b52", 706 | "id": 5830558567366656, 707 | "isFavoriteFriend": false 708 | }, 709 | { 710 | "name": "Arsanus", 711 | "isServiceUser": false, 712 | "isFriend": true, 713 | "lastSeenAt": 0, 714 | "imageUri": "https://cdn-image-e0d67c509fb203858ebcb2fe3f88c2aa.baas.nintendo.com/1/1b98b0d3e78dffb0", 715 | "id": 0, 716 | "isFavoriteFriend": true 717 | }, 718 | { 719 | "name": "Vertsix", 720 | "isServiceUser": false, 721 | "isFriend": true, 722 | "lastSeenAt": 0, 723 | "imageUri": "https://cdn-image-e0d67c509fb203858ebcb2fe3f88c2aa.baas.nintendo.com/1/c1765003c338efc8", 724 | "id": 0, 725 | "isFavoriteFriend": false 726 | }, 727 | { 728 | "name": "гεd☆sкγε", 729 | "isServiceUser": true, 730 | "isFriend": true, 731 | "lastSeenAt": 0, 732 | "imageUri": "https://cdn-image-e0d67c509fb203858ebcb2fe3f88c2aa.baas.nintendo.com/1/d5152ad313c572d4", 733 | "id": 5164065190051840, 734 | "isFavoriteFriend": false 735 | }, 736 | { 737 | "name": "King Udyr", 738 | "isServiceUser": true, 739 | "isFriend": true, 740 | "lastSeenAt": 0, 741 | "imageUri": "https://cdn-image-e0d67c509fb203858ebcb2fe3f88c2aa.baas.nintendo.com/1/495508ab65149923", 742 | "id": 6223255610327040, 743 | "isFavoriteFriend": false 744 | }, 745 | { 746 | "name": "UncleBones", 747 | "isServiceUser": true, 748 | "isFriend": true, 749 | "lastSeenAt": 0, 750 | "imageUri": "https://cdn-image-e0d67c509fb203858ebcb2fe3f88c2aa.baas.nintendo.com/1/8609da5bf75c1ae8", 751 | "id": 5333171474268160, 752 | "isFavoriteFriend": true 753 | }, 754 | { 755 | "name": "FishPhd", 756 | "isServiceUser": true, 757 | "isFriend": true, 758 | "lastSeenAt": 0, 759 | "imageUri": "https://cdn-image-e0d67c509fb203858ebcb2fe3f88c2aa.baas.nintendo.com/1/fa7ee5bbdd1730be", 760 | "id": 6208096925908992, 761 | "isFavoriteFriend": false 762 | }, 763 | { 764 | "name": "SillyChip", 765 | "isServiceUser": false, 766 | "isFriend": true, 767 | "lastSeenAt": 0, 768 | "imageUri": "https://cdn-image-e0d67c509fb203858ebcb2fe3f88c2aa.baas.nintendo.com/1/2d62166c88c180a7", 769 | "id": 0, 770 | "isFavoriteFriend": true 771 | }, 772 | { 773 | "name": "ramtower", 774 | "isServiceUser": true, 775 | "isFriend": true, 776 | "lastSeenAt": 0, 777 | "imageUri": "https://cdn-image-e0d67c509fb203858ebcb2fe3f88c2aa.baas.nintendo.com/1/839f84e45d6c503c", 778 | "id": 5876604337127424, 779 | "isFavoriteFriend": true 780 | }, 781 | { 782 | "name": "Kev | HDK", 783 | "isServiceUser": true, 784 | "isFriend": true, 785 | "lastSeenAt": 0, 786 | "imageUri": "https://cdn-image-e0d67c509fb203858ebcb2fe3f88c2aa.baas.nintendo.com/1/ec9c900c5bd98a18", 787 | "id": 5928458282598400, 788 | "isFavoriteFriend": false 789 | }, 790 | { 791 | "name": "Weeee", 792 | "isServiceUser": false, 793 | "isFriend": true, 794 | "lastSeenAt": 0, 795 | "imageUri": "https://cdn-image-e0d67c509fb203858ebcb2fe3f88c2aa.baas.nintendo.com/1/fc40cf8eab622bf4", 796 | "id": 0, 797 | "isFavoriteFriend": false 798 | }, 799 | { 800 | "name": "Sora", 801 | "isServiceUser": true, 802 | "isFriend": true, 803 | "lastSeenAt": 1506986817, 804 | "imageUri": "https://cdn-image-e0d67c509fb203858ebcb2fe3f88c2aa.baas.nintendo.com/1/ec0cd600097a8dec", 805 | "id": 6525512310587392, 806 | "isFavoriteFriend": true 807 | } 808 | ] 809 | } 810 | ``` 811 | 812 | ## Show User Fast [/v1/User/ShowFast] 813 | 814 | ### Show User Fast (for VoIP) [POST] 815 | 816 | Web API Access Token should be webApiServerCredential["accesstoken"] from [POST /v1/Account/Login](#LoginAccount). 817 | 818 | ID should be a user ID 819 | 820 | + Request 821 | 822 | + Headers 823 | 824 | ``` 825 | X-ProductVersion: 1.1.0 826 | X-Platform: Android 827 | User-Agent: com.nintendo.znca/1.1.0 (Android/7.0) 828 | Accept: application/json 829 | Authorization: Bearer [Web API Access Token] 830 | Content-Type: application/json; charset=utf-8 831 | Content-Length: 230 832 | Host: api-lp1.znc.srv.nintendo.net 833 | Connection: Keep-Alive 834 | Accept-Encoding: gzip 835 | ``` 836 | 837 | + Body 838 | 839 | ```json 840 | { 841 | "parameter":{ 842 | "id":5409588421591040 843 | } 844 | } 845 | ``` 846 | 847 | + Response 200 (application/json) 848 | 849 | + Body 850 | 851 | ```json 852 | { 853 | "result": { 854 | "id": 5409588421591040, 855 | "name": "TPoS-Shin", 856 | "imageUri": "https://cdn-image-e0d67c509fb203858ebcb2fe3f88c2aa.baas.nintendo.com/1/26f4a1e2a08ee69b" 857 | }, 858 | "correlationId": "b9917772-b68d5bff", 859 | "status": 0 860 | } 861 | ``` -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Reverse Engineered Nintendo Switch App REST API 2 | 3 | ## Introduction 4 | 5 | This is documentation of the REST APIs used for the Nintendo Switch app, and embedded Splatoon 2 web app. 6 | 7 | All testing was done on an iPhone 7 running iOS 10.3.3 using version 1.0.4 of the Nintendo Switch app on 07/30/17. I reverse-engineered using [mitmproxy](https://mitmproxy.org). It was quite easy as the app does not use cert-pinning at all. I have not tested using the Android app at all, but I would assume that everything is identical (besides obvious user-agent differences). I am using a US account with the language set to English. There may be small differences for other regions. 8 | 9 | A [Paw](https://paw.cloud) project is included for macOS users which should help tinkering with the API. I highly recommend trying this out first to figure out how the API works. Take a look at the environment variables to see what you need to fill in. Once you fill in `Client ID`, `Login Page Token Code`, `Login Page Token Code Verifier`, and `Birthday` you can execute the auth requests in order and you should be good to go. 10 | 11 | Note: I recommend setting the `User-Agent` on all requests to the Splatoon 2 API to the following string to blend in. There doesn't appear to be any checking for this but better safe than sorry. `Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_3 like Mac OS X) AppleWebKit/603.3.8 (KHTML, like Gecko) Mobile/14G60` 12 | 13 | ## Blueprints 14 | * [Nintendo Account](NintendoAccountBlueprint.md) 15 | * [Nintendo Switch](SwitchBlueprint.md) 16 | * [Splatoon 2](Splatoon2Blueprint.md) 17 | 18 | ## Open Source Components 19 | 20 | If you are curious about the open source components used in the app, I have compiled them [here](OpenSource.md). 21 | 22 | ## Authentication Steps 23 | 24 | 1. Visit authorization link in browser 25 | 26 | This page is an HTML page which loads the auth flow which you would normally see first when logging into the app. Follow through the flow by logging in with an account. 27 | 28 | https://accounts.nintendo.com/connect/1.0.0/authorize?state=[state here]&redirect_uri=[... continues] 29 | 30 | I currently have no idea how this URL is generated. I recommend signing out of the Switch app, then sign back in and open the sign flow link in Safari. You can then open it on your computer and follow from there. 31 | 32 | Once you sign in, you will be redirected to a page like `npf71b963c1b7b6d119://auth#session_state=[SessionStateReturnedHere]&session_token_code=[codehere]&state=[StateReturnedHere]` 33 | 34 | 2. Get a session token 35 | 36 | Extract the session_state and state from that url, and request from [POST /connect/1.0.0/api/session_token](NintendoAccountBlueprint.md#GetSessionToken) 37 | 38 | 3. Get a service access token 39 | 40 | Make a request to [POST /connect/1.0.0/api/token](NintendoAccountBlueprint.md#GetServiceToken) using `session_token` from 2. 41 | 42 | 4. Login to account 43 | 44 | Make a request to [POST /v1/Account/Login](SwitchBlueprint.md#LoginAccount). Use `id_token` from 3. 45 | 46 | 5. Get game list 47 | 48 | Use your access token to retrieve the game list from [GET /v1/Game/ListWebServices](SwitchBlueprint.md#GetGameList). Use `webApiServerCredential["accesstoken"]` from 4. 49 | 50 | 6. Get access token for Splatoon 51 | 52 | Make a request to [GET /v1/Game/GetWebServiceToken](SwitchBlueprint.md#GetGameWebServiceToken). Use the ID of Splatoon 2 from 5 and `webApiServerCredential["accesstoken"]` from 4. 53 | 54 | 7. Get cookie to use for splatoon requests 55 | 56 | Make a request to [GET /](Splatoon2Blueprint.md#GetHomepage). Use the `accessToken` from 6. 57 | 58 | 8. Play with the Splatoon 2 API 59 | 60 | You can now make any request from the [Splatoon 2 API](Splatoon2Blueprint.md) using the cookie retrieved from 7. Have fun! 61 | --------------------------------------------------------------------------------