{"id":19846527,"url":"https://github.com/hekmon/go-netatmo","last_synced_at":"2025-10-13T00:48:00.444Z","repository":{"id":99435632,"uuid":"367571662","full_name":"hekmon/go-netatmo","owner":"hekmon","description":"Netatmo API Golang bindings","archived":false,"fork":false,"pushed_at":"2021-09-09T12:01:12.000Z","size":151,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-02-28T22:52:14.415Z","etag":null,"topics":["api","api-client","api-client-go","bindings","golang","golang-library","netatmo","netatmo-api","netatmo-energy","netatmo-weather-station"],"latest_commit_sha":null,"homepage":"","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/hekmon.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":"security/README.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-05-15T07:49:38.000Z","updated_at":"2022-02-02T18:59:38.000Z","dependencies_parsed_at":"2023-05-26T22:30:30.341Z","dependency_job_id":null,"html_url":"https://github.com/hekmon/go-netatmo","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/hekmon/go-netatmo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hekmon%2Fgo-netatmo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hekmon%2Fgo-netatmo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hekmon%2Fgo-netatmo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hekmon%2Fgo-netatmo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hekmon","download_url":"https://codeload.github.com/hekmon/go-netatmo/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hekmon%2Fgo-netatmo/sbom","scorecard":{"id":459970,"data":{"date":"2025-08-11","repo":{"name":"github.com/hekmon/go-netatmo","commit":"89b2a280c4fa143d80d1e7a14d4434a6d90ace79"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.9,"checks":[{"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":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Code-Review","score":0,"reason":"Found 0/30 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":"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":"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":"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":"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":"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":"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":"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 'main'"],"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":"Vulnerabilities","score":9,"reason":"1 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GO-2025-3488 / GHSA-6v2p-p543-phr9"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-19T10:50:45.006Z","repository_id":99435632,"created_at":"2025-08-19T10:50:45.006Z","updated_at":"2025-08-19T10:50:45.006Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279013643,"owners_count":26085298,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-12T02:00:06.719Z","response_time":53,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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","api-client","api-client-go","bindings","golang","golang-library","netatmo","netatmo-api","netatmo-energy","netatmo-weather-station"],"created_at":"2024-11-12T13:11:44.703Z","updated_at":"2025-10-13T00:48:00.425Z","avatar_url":"https://github.com/hekmon.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Netatmo API Golang bindings\n\n[![Go Reference](https://pkg.go.dev/badge/github.com/hekmon/go-netatmo.svg)](https://pkg.go.dev/github.com/hekmon/go-netatmo) [![Go report card](https://goreportcard.com/badge/github.com/hekmon/transmissionrpc)](https://goreportcard.com/report/github.com/hekmon/go-netatmo)\n\n*WIP DO NOT USE*\n\nNetatmo API version: 1.1.2\n\nThis lib is splitted into several packages in order for the user to only import what matters to him. The main package (this one) handles everything linked to oauth2 (authentification and token refreshing): it allows to create a client which automatically handles the authentification workflow but does not know any Netatmo product APIs. This main client is then to be used with sub package specific products API:\n\n* [weather](https://github.com/hekmon/go-netatmo/tree/main/weather#readme)\n* [energy](https://github.com/hekmon/go-netatmo/tree/main/energy#readme)\n* [security](https://github.com/hekmon/go-netatmo/tree/main/security#readme)\n* [aircaire](https://github.com/hekmon/go-netatmo/tree/main/aircaire#readme)\n\nThe first thing you should do is read the [Netatmo developers guidelines](https://dev.netatmo.com/guideline) and [create an app](https://dev.netatmo.com/apps/createanapp#form) in order to retreive a `client id`, a `client secret` but also setup the application `redirect URI` if you plan to use the standard oauth2 workflow.\n\n## Getting started\n\nFirst you need to know how you will authenticate against the Netatmo API. There is 2 methods supported:\n\n* The [\"authorization code\"](https://dev.netatmo.com/apidocumentation/oauth#authorization-code) workflow which is the standard but also the most complex. You will need a reachable webserver (your go program ?) in order to catch the callback URL once the user has been authentified on Netatmo website and allowed your app to access your users data on their behalf. When you plan multi-tenancy (handling multiples users) by opening your service on the internet, this is the one you should consider.\n* The [\"client credentials\"](https://dev.netatmo.com/apidocumentation/oauth#client-credential) workflow, simplier, which allow to get an oauth2 token directly by submiting a user/password combination. Perfect for personnal projects, you should still consider to not use your admin/main account but instead create a secondary account with limited privileges, invite it to your main account and then use the secondary account credentials for your program.\n\nBoth methods require an oauth2 configuration which you configure like this:\n\n```golang\noauthConfig := netatmo.GenerateOAuth2Config(netatmo.OAuth2BaseConfig{\n    ClientID:     ClientID, // retreived in your developers app netatmo page\n    ClientSecret: SecretID, // retreived in your developers app netatmo page\n    Scopes: []string{\n        netatmo.ScopeStationRead,\n        netatmo.ScopeThermostatRead,\n    }, // see the the scopes.go file for all availables scopes\n    RedirectURL: \"https://yourdomain.tld/netatmocallback\", // set up in your developers app netatmo page\n})\n```\n\nIf you do not plan to use the authorization code workflow, I still recommend you to setup an arbitraty redirect URL (ideally on a domain you own, even if the endpoint is fake) and set it up on your oauth config as well in order for netatmo to match your app profil on theirs servers (I got silent fails during testing because of it).\n\n### Client credentials\n\nSimply init the client with username/password:\n\n```golang\nclient, err := netatmo.NewClientWithClientCredentials(context.TODO(), config, username, password, nil)\nif err != nil {\n    panic(err)\n}\n```\n\nKeep in mind that should never used/store your admin account credentials ! (prefer a low privileges, secondary account)\n\n### Authorization code\n\nAs described by the [Netatmo website](https://dev.netatmo.com/apidocumentation/oauth#authorization-code), oauth2 three-legged workflow needs several steps.\n\n#### Getting the authorization URL\n\nTo get valid tokens to act as your user, you will need to redirect him on the oauth2 authorization page at netatmo servers:\n\n```golang\nuserRandomID := \"somethingrandomthatyouwillstore\"\nauthURL := netatmo.GetUserAuthorizationURL(oac oauth2.Config, userRandomID string)\n```\n\nThis will yield you an URL in order to your user to validate on the netatmo servers that it allows your app to act on its behalf for the scopes you declared on your oauth configuration. Unfortunatly, the URL is not reachable by GET but POST only; this POST will then yield the real GETable URL in the `Location` HTTP header by issuing a 302 response. This can be fine if you want to redirect your user on the netatmo servers using browser side javascript but can be anoying if you need to recover (and for example print) the real GETable URL yourself. This lib contains an helper function which will do it for you if you need it to:\n\n```golang\nuserRandomID := \"somethingrandomthatyouwillstore\"\nauthURL, err := netatmo.RetreiveUserRealAuthorizationURL(context.TODO(), oauthConfig, userRandomID, nil)\nif err != nil {\n    panic(err)\n}\nfmt.Println(authURL)\n```\n\n#### Receiving the auth code from Netatmo\n\nOnce your user validates the scopes and your app on the Netatmo Oauth2 page, the Netatmo servers will send an authentication code back to your redirect URL along with the userID you setup (allowing you to match which user this auth code belongs to). You will need an HTTP handler to catch them as they are passed as query parameters: `[YOUR_REDIRECT_URI]?state=[USER_RANDOM_ID_YOU_PROVIDED]\u0026code=[NETATMO_GENERATED_CODE]`\n\nOnce retreived, you can use the uniq ID in the `state` query parameter to match the user you assigned it to and use the auth code to retreive the oauth2 tokens and finally have the authenticated netatmo client:\n\n```golang\nauthedClient, err := netatmo.NewClientWithAuthorizationCode(context.TODO(), oauthConfig, netatmoGeneratedCode, nil)\nif err != nil {\n    panic(err)\n}\n```\n\nThe lib will handle the oauth2 process, retreives the oauth2 tokens from this auth code and yield an authenticated client.\n\n### Restoring a client from tokens\n\nOnce initialized, no matter if it was from the client credentials or authorization code workflow, you can (and should) store the oauth2 tokens somewhere in order for you to re init an auth client without redoing the whole auth process.\n\nTo retreive a client's oauth2 tokens simply do:\n\n```golang\ntokens := authedClient.GetTokens()\n```\n\nThis will yield you a struct with JSON tags. Store it anyway you like. Then in order to restore a client, restore this struct and directly init the client:\n\n```golang\ntokens := retreivedSavedTokens(user)\nauthedClient, err := netatmo.NewClientWithTokens(context.TODO(), oauthConfig, tokens, nil)\nif err != nil {\n    panic(err)\n}\n```\n\n## I have my authenticated client, now what ?\n\nYou can now init products API clients using the `authedClient` that will handle API requests authentication and oauth2 tokens auto refresh.\n\n* [weather](https://github.com/hekmon/go-netatmo/tree/main/weather#readme)\n* [energy](https://github.com/hekmon/go-netatmo/tree/main/energy#readme)\n* [security](https://github.com/hekmon/go-netatmo/tree/main/security#readme)\n* [aircaire](https://github.com/hekmon/go-netatmo/tree/main/aircaire#readme)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhekmon%2Fgo-netatmo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhekmon%2Fgo-netatmo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhekmon%2Fgo-netatmo/lists"}