Green Button OAuth

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>)

POST Body (form-encoded):

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",
}