Gentrack Integration Resources

How to Call Gentrack APIs

Introduction

API calls to Gentrack is an optional extra capability in Salesforce Sales Cloud Connector that allows Salesforce applications to directly call Gentrack APIs.

This page is a guidance of how to call Gentrack APIs from Salesforce.

Pre-requisites

  • A new connector instance has been created
  • API calls to Gentrack has been enabled (Named Credential has been created)

Named Credentials in Salesforce

Once API calls to Gentrack is enabled, Salesforce Sales Cloud Connector will create the following Named Credentials in Salesforce.

Gentrack Cloud Access Credentials (Gentrack_Access)

This Named Credential is used to request access token from Gentrack.

  • Name: Gentrack_Access
  • Label: Gentrack Cloud Access Credentials
  • URL: https://[sovereignty].id.gentrackcloud.com/v1/token. Sovereignty is uk or au, depending on where your organisation resides.
  • Identity Type: Named Principal
  • Authentication Protocol: Password Authentication
  • Username: client ID, e.g. fc2b9be9-d72f-469e-8433-1746506856d0
  • Password: client secret, e.g. ss4XILSIMpO1r0POm5AVCccs68BW5pcZ9VDiboer1PU=
  • Generate Authorization Header: true
  • Allow Merge Fields in HTTP Header: false
  • Allow Merge Fields in HTTP Body: false

The following is an example of a NamedCredential component.

<?xml version="1.0" encoding="UTF-8"?>
<NamedCredential xmlns="http://soap.sforce.com/2006/04/metadata">
  <fullName>Gentrack_Access</fullName>
  <label>Gentrack Cloud Access Credentials</label>
  <endpoint>https://au.id.gentrackcloud.com/v1/token</endpoint>
  <principalType>NamedUser</principalType>
  <protocol>Password</protocol>
  <username>fc2b9be9-d72f-469e-8433-1746506856d0</username>
  <password>ss4XILSIMpO1r0POm5AVCccs68BW5pcZ9VDiboer1PU=</password>
  <generateAuthorizationHeader>true</generateAuthorizationHeader>
  <allowMergeFieldsInHeader>false</allowMergeFieldsInHeader>
  <allowMergeFieldsInBody>false</allowMergeFieldsInBody>
</NamedCredential>

How to Call Gentrack APIs

The following are the steps to call Gentrack APIs:

Configure Remote Site Settings

Depending on where your organisation resides, the following Gentrack API endpoint needs to be configured in Remote Site Settings.

  • https://api-[sovereignty].integration.gentrack.cloud

Note: The sovereignty is the same as the one in the URL field of the Gentrack_Access Named Credential.

Request Access Token from Gentrack

Gentrack authentication uses OAuth 2.0, and it supports Client Credentials grant type. Gentrack access token is JSON Web Token which is used as OAuth 2.0 Bearer Token.

The following is an example of how to request access token using cURL:

curl --request POST 'https://c6nx1vci83.execute-api.ap-southeast-2.amazonaws.com/v1/token' \
--user "fc2b9be9-d72f-469e-8433-1746506856d0:ss4XILSIMpO1r0POm5AVCccs68BW5pcZ9VDiboer1PU=" \
--data-urlencode 'grant_type=client_credentials'

The following is an example of the response:

{
    "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjA2NDYxODczLTFlOWMtNGVkMy1iZWZkLTU3NGY5ZmEwYjExYyIsIm9yZ0lkIjoiQzAwMDAi
  LCJ0b2tlbl91c2UiOiJhY2Nlc3MiLCJpYXQiOjE1MzA1ODkwODcsImV4cCI6MTUzMDU5MjY4NywiaXNzIjoiaHR0cHM6Ly9hcGkuZ2VudHJhY2suaW8vIn0.WUAFYWTTEAyQ0Bt4YXu-m
  xCXd-Y9ehwdZcYvcGNnyLTZH_hiJjtXWWfsx69M606pvCP6lLMT7MfK-F3E4rLO6KAlGsuz4A_7oVWQf4QNeR178GnwgmqQRw5OnLxwPbPrRa9nODngwGq8dcWejhmEYU6iw02bvYdQBH
  nnsc3Kpyzw7Wdv_3jnBS4TPYS20muQOgG6KxRp9hLJM7ERLoAbsULwqdPOV8eUJJhGrq1NDuH_lA83YRDZmCWEzw96tSm3hb7y88kXs-4OvamnO1m5wFPBx69VximlS4Ltr3ztqU2s3fH
  oj0OJLIafge9JvTgvuB6noHfs1uSRaahvstGJAA",
    "expires_in": 3600,
    "token_type": "Bearer"
}

Note: Access token expires in one hour, or 3600 seconds as indicated by expires_in in the response.

The following is an example of how to request access token from Gentrack in Salesforce using Named Credentials as Callout Endpoints.

HttpRequest request = new HttpRequest();
request.setEndpoint('callout:Gentrack_Access');
request.setMethod('POST');
request.setBody('grant_type=client_credentials');
Http http = new Http();
HTTPResponse response = http.send(request);
if (response.getStatusCode() >= 200 && response.getStatusCode() < 300) {
    JSONParser parser = JSON.createParser(response.getBody());
    while (parser.nextToken() != null) {
        if (parser.getCurrentToken() == JSONToken.FIELD_NAME && parser.getText() == 'access_token') {
            parser.nextToken();
            accessToken = parser.getText();
        }
    }
} else {
    throw new GentrackException('Failed to get access token from Gentrack');
}

Using Access Token to call Gentrack APIs

Calling Velocity APIs

The following is an example of how to use access token to retrieve pricing plans from the Billing system (Velocity) in NZ.

HttpRequest request = new HttpRequest();
request.setEndpoint('http://api-au.integration.gentrack.cloud/v1/velocity/pricing-plans?utility=G&pricingClass=GAS.RESIDENTIAL');
request.setMethod('GET');
request.setHeader('Authorization', 'Bearer ' + accessToken);
Http http = new Http();
HTTPResponse response = http.send(request);
if (response.getStatusCode() >= 200 && response.getStatusCode() < 300) {
    velocityPricingPlans = response.getBody();
} else {
    throw new GentrackException('Failed to retrieve pricing plans from Gentrack' + response.getBody());
}

Calling Junifer APIs

The following is an example of how to use access token to get electricity products from the Billing system (Junifer) in UK.

HttpRequest request = new HttpRequest();
request.setEndpoint('http://api-uk.integration.gentrack.cloud/v1/junifer/products/electricity?rateCount=1&billingEntity=JUN');
request.setMethod('GET');
request.setHeader('Authorization', 'Bearer ' + accessToken);
Http http = new Http();
HTTPResponse response = http.send(request);
if (response.getStatusCode() >= 200 && response.getStatusCode() < 300) {
    juniferElectricityProducts = response.getBody();
} else {
    throw new GentrackException('Failed to get electricity products from Gentrack' + response.getBody());
}

Cache Access Token

Client shall always cache the access token and request a new one ONLY when it is necessary, for example a few minutes before its expiry time. This will avoid unexpected API throttling issues and improve performance of API calls.

Please check Platform Cache for more information about how to use cache in Salesforce.

The following is a full example of how to cache access token in Salesforce, and how to use it to call Gentrack APIs.

// Custom exception class: "GentrackException.apxc"
public class GentrackException extends Exception {
}

// Custom Apex class: "GentrackCloudClient.apxc"
public with sharing class GentrackCloudClient {
    // Gentrack API URL in UK sovereignty
    private static String GENTRACK_API_URL_UK = 'http://api-uk.integration.gentrack.cloud';
    // Gentrack API URL in AU sovereignty
    private static String GENTRACK_API_URL_AU = 'http://api-au.integration.gentrack.cloud';

    public String accessToken {set; get;}
    public String velocityPricingPlans {set; get;}
    public String juniferElectricityProducts {set; get;}

    public GentrackCloudClient(ApexPages.StandardController stdController) {
    }

    // Platform Cache Partition: GentrackCloud
    private String tokenCacheKey() {
        return 'local.GentrackCloud.accessToken';
    }

    public void refreshAccessToken() {
        if (Cache.Org.contains(tokenCacheKey())) {
            System.debug('Get access token from cache');
            accessToken = (String) Cache.Org.get(tokenCacheKey());
            return;
        }
        System.debug('Request access token from Gentrack');
        HttpRequest request = new HttpRequest();
        request.setEndpoint('callout:Gentrack_Access');
        request.setMethod('POST');
        request.setBody('grant_type=client_credentials');
        Http http = new Http();
        HTTPResponse response = http.send(request);
        if (response.getStatusCode() >= 200 && response.getStatusCode() < 300) {
            JSONParser parser = JSON.createParser(response.getBody());
            while (parser.nextToken() != null) {
                if (parser.getCurrentToken() == JSONToken.FIELD_NAME && parser.getText() == 'access_token') {
                    parser.nextToken();
                    accessToken = parser.getText();
                    Cache.Org.put(tokenCacheKey(), accessToken, 50 * 60);
                }
            }
        } else {
            throw new GentrackException('Failed to get access token from Gentrack');
        }
    }

    public void getJuniferElectricityProducts() {
        juniferElectricityProducts = get(GENTRACK_API_URL_UK + '/v1/junifer/products/electricity?rateCount=1&billingEntity=JUN');
    }

    public void getVelocityPricingPlans() {
        velocityPricingPlans = get(GENTRACK_API_URL_AU + '/v1/velocity/pricing-plans?utility=G&pricingClass=GAS.RESIDENTIAL');
    }

    private String get(string url) {
        refreshAccessToken();
        HttpRequest request = new HttpRequest();
        request.setEndpoint(url);
        request.setMethod('GET');
        request.setHeader('Authorization', 'Bearer ' + accessToken);
        Http http = new Http();
        HTTPResponse response = http.send(request);
        if (response.getStatusCode() >= 200 && response.getStatusCode() < 300) {
            return response.getBody();
        } else {
            throw new GentrackException('Failed to get: ' + response.getBody());
        }
    }
}
Last updated on 6 May 2021