{"id":37747102,"url":"https://github.com/jrmycanady/nokiahealth","last_synced_at":"2026-01-16T14:18:10.900Z","repository":{"id":72603779,"uuid":"112422594","full_name":"jrmycanady/nokiahealth","owner":"jrmycanady","description":"Go library for the Nokia Health API with full API coverage and documentation.","archived":false,"fork":false,"pushed_at":"2019-01-05T04:43:05.000Z","size":71,"stargazers_count":17,"open_issues_count":1,"forks_count":6,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-06-20T14:30:09.197Z","etag":null,"topics":["api","body","bpm","go","golang","health","nokia","nokiahealth","thermo","withings"],"latest_commit_sha":null,"homepage":"https://godoc.org/github.com/jrmycanady/nokiahealth","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jrmycanady.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2017-11-29T03:39:18.000Z","updated_at":"2023-06-26T01:28:10.000Z","dependencies_parsed_at":null,"dependency_job_id":"ca941bc9-07d7-4389-99e6-73ac6c6fb9b3","html_url":"https://github.com/jrmycanady/nokiahealth","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/jrmycanady/nokiahealth","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jrmycanady%2Fnokiahealth","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jrmycanady%2Fnokiahealth/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jrmycanady%2Fnokiahealth/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jrmycanady%2Fnokiahealth/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jrmycanady","download_url":"https://codeload.github.com/jrmycanady/nokiahealth/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jrmycanady%2Fnokiahealth/sbom","scorecard":{"id":536908,"data":{"date":"2025-08-11","repo":{"name":"github.com/jrmycanady/nokiahealth","commit":"f9d1532d13aafc4094076a774a4a8f467ed860b2"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Code-Review","score":0,"reason":"Found 1/27 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 4 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-20T07:12:45.859Z","repository_id":72603779,"created_at":"2025-08-20T07:12:45.859Z","updated_at":"2025-08-20T07:12:45.859Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28479369,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-16T11:59:17.896Z","status":"ssl_error","status_checked_at":"2026-01-16T11:55:55.838Z","response_time":107,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","body","bpm","go","golang","health","nokia","nokiahealth","thermo","withings"],"created_at":"2026-01-16T14:18:10.270Z","updated_at":"2026-01-16T14:18:10.893Z","avatar_url":"https://github.com/jrmycanady.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n\u003cimg align=\"right\" src=\"./nh_logo_small.png\"/\u003e\n\n# Go client for the Nokia Health API\n\nThis is a go client that allows easy access to the Nokia Health API and as of v2 supports the required Oauth2. More documentation regarding the Nokia Health API can be found [here](http://developer.health.nokia.com/oauth2/#tag/introduction). More detailed documentation of the client can be found in the [godocs](https://godoc.org/github.com/jrmycanady/nokiahealth).\n\n## v1 to v2 Changes\n\nNokia changed the API to allow Oauth2 while removing Oauth1 as an option. Due to this change, the client API has changed when it comes to handling authentication and tokens. For the most part the changes make things easier but they are breaking changes. The good new is there is no longer a dependency on the forked Ouath1 implementation. \n\n## Supported Resources\n* User Access Requests\n* Retrieving user body measurements\n* Retrieve activity measurements\n* Retrieve workouts\n* Retrieve intraday activities - Apparently requires additional authorization which I don't have yet so no testing.\n* Retrieve sleep measures - Limited testing so report any issues.\n* Retrieve sleep summary - Limited testing so report any issues.\n* Creating a notification\n* Retrieving a single notification\n* Retrieving all notifications for a user\n* Revoke notifications\n\n## Installation\n  go get github.com/jrmycanady/nokiahealth\n\n## Highlevel Usage Overview\nIt's best if you read up on Oauth2 if you are not familiar but the client should be simple enough to get working without understanding how Oauth2 works.\n\n### New User\n* Create a [nokia account and register your app](https://account.health.nokia.com/partner/dashboard_oauth2).\n* Create a client and perform the tasks to get the token/user struct.\n    * Send user to Oauth2 authorization URL.\n    * Catch the redirect back via a server or manually pulling the \"code\" from the path.\n    * Generate a user.\n* Execute queries!\n\n### Returning User\n* Create client (Assuming you have an account otherwise the user couldn't be returning...)\n* Generate user from stored token.\n* Execute queries!\n\n## Highlevel Usage Example\n\n### New User\n\n**1. Obtain your ClientID and ClientSecret**\n**2. Create a new client**\n```go\nclientID := \"id\"\nclientSecrete := \"secret\"\nclientRedirectURL := \"url\" // This is the URL nokia will redirect the client to \n                           // after they authorized your application. This is\n                           // the same URL you provided when you registered your\n                           // application with Nokia. \n                           // For any real world use you will need to have a\n                           // http server running and listening on that URL\n                           // so you can obtain the code that is retruned.\n                           // For simple testing you can just manually navigate\n                           // to the URL that will be generated and copy the\n                           // code.\n\nclient := nokiahealth.NewClient(clientID, clientSecret, clientRedirectURL)\n```\n**3. Generate the authorization URL.**\n```go\nauthURL, _, err := client.AuthCodeURL() // Ignoring the state in this example\n                                        // but in realworld use you will want\n                                        // to record this to compare to the\n                                        // state value returned by the redirect\n                                        // from nokia to verify its a redirect\n                                        // from your request. \n                                        // The stat is auto generated for you\n                                        // using cyrto/rand but the random\n                                        // generation can be replaced with your\n                                        // own function if you would like.\n```\n**4. User navigates to URL and the code and state are retrieved.**\n**5. Create new user using returned code.**\n```go\nu, err := client.NewUserFromAuthCode(context.Background(), code) // Obviously\n                                        // use whatever context you would like\n                                        // here.\nif err != nil {\n    panic(err) // Handle the error however is appropriate for your code.\n}\n```\n**6. DONE - you now have a user that can make data requests.**\n\n### Returning User\n\n**1. Create a new client**\n```go\nclientID := \"id\"\nclientSecrete := \"secret\"\nclientRedirectURL := \"url\" // This is the URL nokia will redirect the client to \n                           // after they authorized your application. This is\n                           // the same URL you provided when you registered your\n                           // application with Nokia. \n                           // For any real world use you will need to have a\n                           // http server running and listening on that URL\n                           // so you can obtain the code that is returned.\n                           // For simple testing you can just manually navigate\n                           // to the URL that will be generated and copy the\n                           // code.\n\nclient := nokiahealth.NewClient(clientID, clientSecret, clientRedirectURL)\n```\n**2. Generate a new user from the stored tokens.**\n```go\n// This creates a new user based on the tokens provided. Technically the \n// accessToken can be gibberish and the refresh Token is the one that is really\n// required.\nu, err := client.NewUserFromRefreshToken(context.Background(), accessToken, refreshToken)\n```\n**3. DONE - you now have a user that can make data requests.**\n\n\n## Making Requests\nRequests are performed from methods on the User. Each request accepts a specific query struct with the details for the request. For example:\n```go\np := nokiahealth.BodyMeasuresQueryParams{}\n\nt := time.Now().AddDate(0, 0, -14)\np.StartDate = \u0026t\n\nm, err := u.GetBodyMeasures(\u0026p)\n```\n\nIn most cases the response will contain all the information you need. Some methods provide additional optional processing that can provide a more usable form to the data. GetBodyMeasures is one of these methods. It's recommended to read the [docs](https://godoc.org/github.com/jrmycanady/nokiahealth) for each method to see how best to use them.\n\n```go\nmeasures := m.ParseData()\n```\n\n## Making context Requests\nEvery request method has a partner method ending with Ctx that takes a context\nthat will be used for the HTTP call. This allows you to provide a custom context\nif you desire.\n```go\np := nokiahealth.BodyMeasuresQueryParams{}\n\nt := time.Now().AddDate(0, 0, -14)\np.StartDate = \u0026t\n\nm, err := u.GetBodyMeasuresCtx(context.Background(), \u0026p)\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjrmycanady%2Fnokiahealth","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjrmycanady%2Fnokiahealth","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjrmycanady%2Fnokiahealth/lists"}