Green Button Connect My Data (GBCMD or GBC) specifies an online authorization process by which a utility customer can share their utility data with a third party. This online authorization process is based on the OAuth 2.0 framework (specifically the Authorization Code Grant process), so if you have developed a connection using OAuth before, you will probably be in familiar territory with Green Button OAuth.
Here are the utilities where we currently support Green Button OAuth:
At UtilityAPI, we support the Green Button OAuth process for utilities that have licensed our EE/DER Engagement Platform product. If you are a utility that needs to implement Green Button Connect, contact sales for more information.
To make things easier for you to learn how the OAuth process works for GBC, we've written an third party demo website that lets you use your GBC clients (i.e. third party registrations) with some built-in redirect handling and data processing.
Demo website: https://utilityapi.com/DataCustodian/thirdparty-demo
Note: In order to successfully use this demo website with your GBC clients, you need
to add a redirect_uri
to your GBC client's OAuth
settings
(see the demo website for which redirect_uri to add).
First, you will need to send a link or redirect your customer to a specific authorization url for a utility with several parameters letting us know who you are and what kind of authorization you are requesting. You can find your base authorization url, as well as your client_id and an editable list of redirect_uris, in your settings after you register as a third party.
As part of the authorization request url, you need to provide several url parameters (as defined by the OAuth standard):
response_type
-
Must always be code
.
client_id
-
This is the client identifier we assigned to you.
redirect_uri
-
(optional) Where you want us to redirect the customer after
they authorize. By default, we'll redirect
them to their receipt.
scope
-
(optional) The scope of the authorization request (see
Authorization Scope).
If not provided, we'll use your default settings.
state
-
(optional) A generated tracking string to include when redirecting back to you.
Here's an example authorization url with all the parameters added (notice how parameter values are percent-encoded):
https://utilityapi.com/DataCustodian/demo/oauth/authorize?response_type=code&client_id=12345&redirect_uri=https%3A%2F%2Fexample.com%2Fsomewhere&scope=FB%3D4_51&state=d71cebc8047a41a5b42661d9b2bf2f25
When you redirect a utility customer to an authorization url, we will authenticate them and then show them an authorization form pre-filled with your authorization scope. They can edit the scope if they want, then choose to Authorize or Decline.
For authenticating a customer (e.g. confirming it's really them), we ask them to login to their online utility account or provide some pieces of information about their account (account #, zip code, etc.). We may also send them a confirmation code (via text or email), to perform a Two-Factor Authentication (2FA). If we already authenticated a customer recently, this process is skipped, so you don't have to worry about them having to login multiple times if you need to redirect them back to the authorization url (e.g. if you want to change the authorization scope, etc.).
When a customer clicks Authorize or Decline, we will redirect them back to the redirect_uri you provided, along with some additional url parameters.
If they clicked Authorize, we'll include a code
parameter that can be used
to obtain an access_token in a later step. Also, if you provided a state
parameter, we'll include that, too. Here's an example authorization response based
on the example from Step 1:
https://example.com/somewhere?code=f38647d645d54be28ae3efaab9565a47&state=d71cebc8047a41a5b42661d9b2bf2f25
If they clicked Decline, we'll include an error
parameter with a value of
access_denied
. Also, if you provided a state
parameter, we'll include that, too. Here's an example decline response based
on the example from Step 1:
https://example.com/somewhere?error=access_denied&state=d71cebc8047a41a5b42661d9b2bf2f25
If we encounter an error during the authorization process we may redirect the
customer back to you with another type of error
(see the list of
OAuth 2.0 error types
). We may also include error_description
and/or error_uri
parameters to help you troubleshoot the issue.
If a customer clicked Authorize, you got back a code
parameter when we redirected
them back to you. You can use that code to obtain an access token that you can use
to access our
Green Button API.
To convert the code to an access token, you need to make a POST request to the OAuth Token endpoint listed in your settings for that utility. This request must be authenticated using your client_id and client_secret. The following parameters need to be in your POST body:
grant_type
-
Must always be authorization_code
.
code
-
The code you received in the redirect.
redirect_uri
-
The redirect_uri set in your original authorization url parameters.
Here's an example access token request and response using CURL:
# Request curl \ -u "$CLIENT_ID:$CLIENT_SECRET" \ -d "grant_type=authorization_code" \ -d "code=f38647d645d54be28ae3efaab9565a47" \ -d "redirect_uri=https%3A%2F%2Fexample.com%2Fsomewhere" \ "https://utilityapi.com/DataCustodian/demo/oauth/token" # Response { "token_type": "Bearer", "access_token": "64999645a0b5449b871ad0333df6cb114415c9a5522d41118a0f7939dd3f0208", "refresh_token": "76fd81fd6a3b42a592eed9ff9b8d5cfda9d53324919643f4a45fe34d664442f9", "expires_in": 3600, "scope": "FB=1_3_4_5_8_13_14_18_19_34_35_39_51;IntervalDuration=900_3600;BlockDuration=daily;HistoryLength=34128000;SubscriptionFrequency=daily;AccountCollection=2", "resourceURI": "https://utilityapi.com/DataCustodian/espi/1_1/resource/Subscription/1111", "customerResourceURI": "https://utilityapi.com/DataCustodian/espi/1_1/resource/RetailCustomer/1111", "authorizationURI": "https://utilityapi.com/DataCustodian/espi/1_1/resource/Authorization/1111", }
Here's what each of the returned JSON parameters mean:
token_type
-
How to use the access token. This will always be Bearer
.
access_token
-
The access token you can use to access data on our Green Button API.
refresh_token
-
When the access token expires, use this token to issue a new access token (see Step 6).
expires_in
-
How may seconds the access token is valid for (e.g. 3600 means valid for 1 hour).
scope
-
The final scope that was authorized (this may be different from your original scope string, see
Authorization Scope).
resourceURI
-
The Subscription url for the shared utility data.
customerResourceURI
-
The RetailCustomer url for the shared utility data.
authorizationURI
-
The Authorization url for the authorization record.
Congratulations! You now have a valid access token you can use to request data on the API. To see what endpoints are available, see our Green Button API documentation.
Here's an example API request with the access token from Step 4 using CURL:
curl \ -H "Authorization: Bearer 64999645a0b5449b871ad0333df6cb114415c9a5522d41118a0f7939dd3f0208" \ "https://utilityapi.com/DataCustodian/espi/1_1/resource/Subscription/1111/UsagePoint"
Access tokens are valid only for a limited period. In order to keep using the API,
you need to get a new access token using the previously provided refresh_token
.
To do this, make a POST request to the
OAuth Token endpoint
specified in your
settings
for that utility.
This request must be authenticated using your client_id and client_secret.
The following parameters need to be in your POST body:
grant_type
-
Must always be refresh_token
.
refresh_token
-
The refresh token previously received in Step 4.
Here's an example refresh token request and response using CURL (the response JSON format is the same as in Step 4):
# Request curl \ -u "$CLIENT_ID:$CLIENT_SECRET" \ -d "grant_type=refresh_token" \ -d "refresh_token=76fd81fd6a3b42a592eed9ff9b8d5cfda9d53324919643f4a45fe34d664442f9" \ "https://utilityapi.com/DataCustodian/demo/oauth/token" # Response { "token_type": "Bearer", "access_token": "47ff9a6285d24b07a6390b9a705993b176b7bed3c8d844f6a93b3f0a7d475ca9", "refresh_token": "f9755a87dd8d4307a0b44d8e06f8db632c5996a08d0f426f8922b4e3fcbe1c36", "expires_in": 3600, "scope": "FB=1_3_4_5_8_13_14_18_19_34_35_39_51;IntervalDuration=900_3600;BlockDuration=daily;HistoryLength=34128000;SubscriptionFrequency=daily;AccountCollection=2", "resourceURI": "https://utilityapi.com/DataCustodian/espi/1_1/resource/Subscription/1111", "customerResourceURI": "https://utilityapi.com/DataCustodian/espi/1_1/resource/RetailCustomer/1111", "authorizationURI": "https://utilityapi.com/DataCustodian/espi/1_1/resource/Authorization/1111", }
POST
/oauth/token
(see your
settings
for the full token url for each utility)
Authorization: Basic base64(<client_id>:<client_secret>)
123
and your client_secret is abc
,
your authorization header would be
Authorization: Basic MTIzOmFiYw==
.
grant_type
- (always required)
client_credentials
-
Asking to grant a
client_access_token
used to access
Authorization Endpoints and
Bulk Endpoints.
refresh_token
-
Asking to re-grant a
access_token
used to access
Resource Endpoints and
Batch Endpoints.
code
-
(required when grant_type=authorization_code)
redirect_uri
-
(required when grant_type=authorization_code)
refresh_token
-
(required when grant_type=refresh_token)
authorization_code
, code is zzz
, and your redirect_uri is https://example.com/somewhere
,
your post body would be
grant_type=authorization_code&code=zzz&redirect_uri=https%3A%2F%2Fexample.com%2Fsomewhere
.
Here's an example for getting a
client_access_token
:
# Request POST /DataCustodian/demo/oauth/token HTTP/1.1 Authorization: Basic MTIzOmFiYw== grant_type=client_credentials # Response { "token_type": "Bearer", "access_token": "47ff9a6285d24b07a6390b9a705993b176b7bed3c8d844f6a93b3f0a7d475ca9", "expires_in": 3600, "scope": "FB=1_3_14_32", "resourceURI": "https://utilityapi.com/DataCustodian/espi/1_1/resource/Bulk/1111", "authorizationURI": "https://utilityapi.com/DataCustodian/espi/1_1/resource/Authorization/1111" }
Here's an example for getting a
access_token
using an authorization code (e.g. Step 4):
# Request POST /DataCustodian/demo/oauth/token HTTP/1.1 Authorization: Basic MTIzOmFiYw== grant_type=authorization_code&code=zzz&redirect_uri=https%3A%2F%2Fexample.com%2Fsomewhere # Response { "token_type": "Bearer", "access_token": "64999645a0b5449b871ad0333df6cb114415c9a5522d41118a0f7939dd3f0208", "refresh_token": "76fd81fd6a3b42a592eed9ff9b8d5cfda9d53324919643f4a45fe34d664442f9", "expires_in": 3600, "scope": "FB=1_3_4_5_8_13_14_18_19_34_35_39_51;IntervalDuration=900_3600;BlockDuration=daily;HistoryLength=34128000;SubscriptionFrequency=daily;AccountCollection=2", "resourceURI": "https://utilityapi.com/DataCustodian/espi/1_1/resource/Subscription/1111", "customerResourceURI": "https://utilityapi.com/DataCustodian/espi/1_1/resource/RetailCustomer/1111", "authorizationURI": "https://utilityapi.com/DataCustodian/espi/1_1/resource/Authorization/1111", }
Here's an example for getting a
access_token
using an refresh token (e.g. Step 6):
# Request POST /DataCustodian/demo/oauth/token HTTP/1.1 Authorization: Basic MTIzOmFiYw== grant_type=refresh_token&refresh_token=76fd81fd6a3b42a592eed9ff9b8d5cfda9d53324919643f4a45fe34d664442f9 # Response { "token_type": "Bearer", "access_token": "47ff9a6285d24b07a6390b9a705993b176b7bed3c8d844f6a93b3f0a7d475ca9", "refresh_token": "f9755a87dd8d4307a0b44d8e06f8db632c5996a08d0f426f8922b4e3fcbe1c36", "expires_in": 3600, "scope": "FB=1_3_4_5_8_13_14_18_19_34_35_39_51;IntervalDuration=900_3600;BlockDuration=daily;HistoryLength=34128000;SubscriptionFrequency=daily;AccountCollection=2", "resourceURI": "https://utilityapi.com/DataCustodian/espi/1_1/resource/Subscription/1111", "customerResourceURI": "https://utilityapi.com/DataCustodian/espi/1_1/resource/RetailCustomer/1111", "authorizationURI": "https://utilityapi.com/DataCustodian/espi/1_1/resource/Authorization/1111", }