HomeGuidesRecipesAPI ReferenceChangelog
Log In
Guides

Plug Intervals

Overview

The Intervals API endpoint allow you to interact programmatically with the Intervals data offering of the Arc Platform to connect to and retrieve utility provided intervals data for electric meters. Through this REST API you can perform a variety of actions, from activating an account for intervals to accessing up to 1 year of historical intervals data of a meter. This solution allows you to leverage utility data to conduct granular energy analysis. Use-cases for this includes but are not limited to solar and storage prospecting, sizing the right DER system and measuring the effectiveness of demand response programs. The intervals data API endpoints delivers up to a year’s historical data initially and then continues to and deliver the latest meter readings on an on-going basis as made available the provider.

How we collect and deliver intervals data

Arcadia accesses utility data by obtaining credentials for online electric utility provider accounts. Up to a year of historical data is collected once intervals data is activated for a meter and is then collected in an on-going fashion as made available by the provider. Once data is collected from online provider portals, Arcadia stores the data and makes it available for access anytime via API.

Coverage of the intervals data product

At present, the intervals API supports data collected from electric utilities only. The complete list of providers supported can be found on this link Provider Coverage for intervals data

Setting up the API

Below is a typical workflow defined as a series of API calls that would be needed to get access to intervals data via API. The steps can be described as:

  1. Requesting authorization to make API calls via an access token
  2. Creating a credential
  3. Filter meters by the ID of that credential
  4. Activating the interval data product for a particular meter
  5. Requesting interval data for a particular meter once it's collected.

Let's jump into more detail for each step below.

1. Create an Access token

Use API ID and Secret from your Arc Dashboard to create an Access Token that has permission to use all Arc API endpoints. Access Tokens are valid for one hour.

Access token creation request

curl --request POST \
     --url https://api.arcadia.com/oauth2/token \
     --header 'accept: application/json' \
     --header 'content-type: application/x-www-form-urlencoded' \
     --data grant_type=client_credentials \
     --data client_id=001 \
     --data client_secret=001

Access token creation response

{
  "access_token": "foobar",
  "expires_in": 300,
  "refresh_expires_in": 0,
  "token_type": "Bearer",
  "not-before-policy": 0,
  "scope": "profile email"
}

2. Creating a credential

You can either submit credentials by using Connect or by submitting username and password via the API. Connect is our off-the-shelf user interface that end-users can use to select their utility provider and submit their login credentials. Using Connect is typically faster and easier for getting up and running.

2a. Creating a credential with Connect

You'll want to send a link to the end-user to submit their login credentials via Connect We have a guide for how to send a Connect URL with a correlationId here!

Once the login details are submitted into Connect, you'll need to locate the credential entity created within Arc because the Credential.id will be necessary for locating meters associated with this credential.

List Credentials Request

curl --request GET  
     --url '<https://api.arcadia.com/plug/credentials?search=correlationId%3Dfoo&page=0&size=20'>  
     --header 'Arc-Version: 2024-02-01'  
     --header 'X-Sandbox-Mode: false'  
     --header 'accept: application/json'  
     --header 'content-type: application/json' \\

List Credentials Response

{
  "credentials": [
    {
      "correlationId": "foo",
      "createdAt": "2024-03-06T18:50:35.101Z",
      "createdBy": "string",
      "id": "crd_1234",
      "isActive": true,
      "isCustomerActionRequired": false,
      "isThirdPartyPortal": false,
      "lastModifiedAt": "2024-03-06T18:50:35.101Z",
      "lastModifiedBy": "string",
      "nextScheduledAccountRunAt": "2024-03-06T18:50:35.101Z",
      "provider": {
        "country": "string",
        "id": "string",
        "name": "string",
        "supportsCredentialValidation": true
      },
      "status": "CONNECTION_SUCCESS",
      "statusDetail": "LOGIN_AND_DATA_DISCOVERY_SUCCESS",
      "totalAccounts": 0,
      "username": "string",
      "username2": "string",
      "username3": "string",
      "username4": "string"
    }
  ],
  "page": {
    "number": 0,
    "size": 0,
    "totalElements": 0,
    "totalPages": 0
  }
}

Once you have the Credential.id (crd_1234 in this example) you can skip to the Listing Meters step below.

2b. Creating a credential with the API

Once an access token is created, use the token to create a credential by submitting the login information associated with that credential. We recommend providing a correlationId as well so that it's easy to find the data related to this user. The correlationId is an arbitrary string provided by API clients to associate resulting utility data with a user in their system. Typically, this is a unique ID in their database associated with the user.

πŸ“˜

NOTE: providerId is a mandatory field for creating a credential. This field is an Arcadia generated unique identifier for the utility provider the credential is associated with. To obtain the providerId, use the list provider endpoint to search the providerId using the provider name.

curl --request POST \
     --url https://api.arcadia.com/plug/credentials \
     --header 'Arc-Version: 2024-02-21' \
     --header 'accept: application/json' \
     --header 'authorization: Bearer foobar' \
     --header 'content-type: application/json' \
     --data '
{
  "password": "password",
  "username": "username",
  "providerId": "36e14462ea0a11e0b6bb12313d2b6294",
  "correlationId": "foo"
}
'

Credential creation response

{
  "correlationId": "foo",
  "createdAt": "2024-02-27T17:11:55.071Z",
  "createdBy": "string",
  "id": "crd_1234",
  "isActive": true,
  "isCustomerActionRequired": true,
  "isThirdPartyPortal": true,
  "lastModifiedAt": "2024-02-27T17:11:55.071Z",
  "lastModifiedBy": "string",
  "nextScheduledRunAt": "2024-02-27T17:11:55.071Z",
  "provider": {
    "country": "string",
    "id": "string",
    "name": "string",
    "supportsCredentialValidation": true
  },
  "status": "CONNECTION_SUCCESS",
  "statusDetail": "LOGIN_AND_DATA_DISCOVERY_SUCCESS",
  "totalAccounts": 0,
  "username": "string",
  "username2": "string",
  "username3": "string",
  "username4": "string"
}

3. Listing meters

After a credential is submitted, Arc will automatically start collecting data about the accounts and meters associated with the credential. You can poll the List Meters endpoint using the credentialId that was assigned to the credential that was created via Connect or via API.

List Meters Request

curl --request GET \
     --url 'https://api.arcadia.com/plug/meters?search=credentialIds%3Dcrd_1234&page=0&size=20'
     --header 'Arc-Version: 2024-02-01' \
     --header 'X-Sandbox-Mode: false' \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \

List Meters Response

{
  "accounts": [
    {
      "accountNumber": "string",
      "id": "string"
    }
  ],
  "bulbType": "string",
  "createdAt": "2024-02-29T19:54:03.357Z",
  "createdBy": "string",
  "currentTariff": {
    "provider": {
      "country": "string",
      "id": "string",
      "name": "string",
      "supportsCredentialValidation": true
    },
    "tariffName": "string"
  },
  "customData": {},
  "generalDescriptionAsPrinted": "string",
  "id": "mtr_1234",
  "intervalsLatestDateTime": "null",
  "isIntervalsProductActive" : "false",
  "isCustomerActionRequired": true,
  "lastModifiedAt": "2024-02-29T19:54:03.357Z",
  "lastModifiedBy": "string",
  "latestStatementDate": "2024-02-29",
  "meterConstantMultiplier": 0,
  "meterNumber": "string",
  "nextExpectedPostDate": "2024-02-29",
  "normalizedMeterNumber": "string",
  "normalizedPointOfDeliveryNumber": "string",
  "pipeType": "string",
  "pointOfDeliveryNumber": "string",
  "previousMeterConstantMultiplier": 0,
  "previousMeterNumber": "string",
  "provider": {
    "country": "string",
    "id": "string",
    "name": "string",
    "supportsCredentialValidation": true
  },
  "serviceAddress": {
    "addressType": "FULL",
    "city": "string",
    "country": "string",
    "fullAddress": "string",
    "postalCode": "string",
    "recipient": "string",
    "state": "string",
    "streetLine1": "string",
    "streetLine2": "string"
  },
  "serviceType": "string",
  "serviceTypeClassification": "CORE",
  "status": "INTERVALS_NOT_REQUESTED",
  "statusDetail": "INTERVAL_EXTRACTION_NOT_REQUESTED",
  "site": {
    "createdAt": "2024-02-29T19:54:03.357Z",
    "createdBy": "string",
    "facilityType": "string",
    "id": "string",
    "lastModifiedAt": "2024-02-29T19:54:03.357Z",
    "lastModifiedBy": "string",
    "meterIds": [
      "string"
    ],
    "region": "string",
    "serviceAddress": {
      "addressType": "FULL",
      "city": "string",
      "country": "string",
      "fullAddress": "string",
      "postalCode": "string",
      "recipient": "string",
      "state": "string",
      "streetLine1": "string",
      "streetLine2": "string"
    },
    "siteCode": "string",
    "siteName": "string",
    "siteNumber": "string",
    "subRegion": "string"
  }
}

You'll want to examine theserviceAddress or any other fields that would indicate that this is a meter you want data for. You'll also want to ensure that the Meter.status is set to INTERVALS_NOT_REQUESTED before moving on to the next step.

You'll need to use the id of the meter you'd like to collect interval data for in the next step.

4. Activating intervals

To be able to access intervals data for a meter, the meter needs to be activated for data collection to be initiated. This can be done using the below command:

Intervals data activation for a meter request

curl --request PATCH \
     --url https://api.arcadia.com/plug/meters/mtr_1234 \
     --header 'Arc-Version: 2024-02-01' \
     --header 'X-Sandbox-Mode: false' \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '
{
  "isIntervalsProductActive": true
}

Intervals data activation for a meter response

{
  "meters": [
    {
      "accounts": [
        {
          "accountNumber": "string",
          "id": "string"
        }
      ],
      "bulbType": "string",
      "createdAt": "2024-03-01T09:45:56.826Z",
      "createdBy": "string",
      "currentTariff": {
        "provider": {
          "country": "string",
          "id": "string",
          "name": "string",
          "supportsCredentialValidation": true
        },
        "tariffName": "string"
      },
      "customData": {},
      "generalDescriptionAsPrinted": "string",
      "id": "mtr_1234",
      "latestIntervalAt": "null",
      "isIntervalsProductActive":true,
      "isCustomerActionRequired": true,
      "lastModifiedAt": "2024-03-01T09:45:56.826Z",
      "lastModifiedBy": "string",
      "latestStatementDate": "2024-03-01",
      "meterConstantMultiplier": 0,
      "meterNumber": "string",
      "nextExpectedPostDate": "2024-03-01",
      "normalizedMeterNumber": "string",
      "normalizedPointOfDeliveryNumber": "string",
      "pipeType": "string",
      "pointOfDeliveryNumber": "string",
      "previousMeterConstantMultiplier": 0,
      "previousMeterNumber": "string",
      "provider": {
        "country": "string",
        "id": "string",
        "name": "string",
        "supportsCredentialValidation": true
      },
      "serviceAddress": {
        "addressType": "FULL",
        "city": "string",
        "country": "string",
        "fullAddress": "string",
        "postalCode": "string",
        "recipient": "string",
        "state": "string",
        "streetLine1": "string",
        "streetLine2": "string"
      },
      "serviceType": "string",
      "serviceTypeClassification": "CORE",
      "status": "INTERVALS_IN_PROGRESS",
      "statusDetail": "INTERVALS_EXTRACTION_IN_PROGRESS",
      "site": {
        "createdAt": "2024-03-01T09:45:56.826Z",
        "createdBy": "string",
        "facilityType": "string",
        "id": "string",
        "lastModifiedAt": "2024-03-01T09:45:56.826Z",
        "lastModifiedBy": "string",
        "meterIds": [
          "string"
        ],
        "region": "string",
        "serviceAddress": {
          "addressType": "FULL",
          "city": "string",
          "country": "string",
          "fullAddress": "string",
          "postalCode": "string",
          "recipient": "string",
          "state": "string",
          "streetLine1": "string",
          "streetLine2": "string"
        },
        "siteCode": "string",
        "siteName": "string",
        "siteNumber": "string",
        "subRegion": "string"
      }
    }
  ],
  "page": {
    "number": 0,
    "size": 0,
    "totalElements": 0,
    "totalPages": 0
  }
}

Intervals data activation for a meter response

In case the activation request was made incorrectly, for example due to incorrect meterId, you may expect to see an error response as below.

{
  "error": "invalid_meter_activation",
  "error_description": "Invalid meterId or meter not in appropriate state for activation"
}

5. Accessing intervals data

Once a meter is activated for intervals, Arcadia uses the provider credentials to collect intervals data for this meter. You'll need to wait for theMeter.statusto be set toINTERVALS_SUCCESS. This data can then be accessed using the GET/intervals/meters/{meterId} or the GET /normalizedIntervals/meters/meterId endpoints.

The intervals API endpoint returns the data as we collect it from the utility (raw utility published data). We do not make any transformations to the data.

Intervals data request

curl --request GET \
     --url 'https://api.arcadia.com/plug/intervals/meters/mtr_1234' \
     --header 'Arc-Version: 2024-02-21' \
     --header 'accept: application/json' \
     --header 'authorization: Bearer foobar'

Intervals data success response

If the request was made correctly, you can expect to get a json response as below with the requested intervals data.

{
   "correlationIds": ["string"],
    "credentialIds": ["string"],
    "meterId": "mtr_1234",
    "meterNumber": 23220,
    "intervalsCreatedAt": "2024-08-28T09:56:12.000+00:00",
    "intervalsUpdatedAt": "2024-08-28T09:56:12.000+00:00",
    "earliestIntervalAt": "2023-08-29T07:00:00.000+00:00",
    "latestIntervalAt": "2024-08-23T06:45:00.000+00:00",
    "providerName": "string",
    "providerId": "string",
    "serviceType": "string",
    "electricMeterMultiplier": 0,
    "readType": "string",
    "localTimezone": "string",
    "readings": [
      {
        "startAt": "2023-08-29T07:00:00.000+00:00",
        "endAt": "2023-08-29T07:01:00.000+00:00",
        "direction": "import",
        "kwh": 0,
        "kw": 0
      }
               ]
}

The normalized version of the interval endpoint makes API integration simpler by consistently delivering interval data of 15 minute intervals irrespective of the length of timestamp in the source data collected from utility.

Normalized Intervals data request

curl --request GET \
     --url 'https://api.arcadia.com/plug/normalizedIntervals/meters/mtr_1234' \
     --header 'Arc-Version: 2024-02-21' \
     --header 'accept: application/json' \
     --header 'authorization: Bearer foobar'

Normalized Intervals data success response

If the request was made correctly, you can expect to get a json response as below with the requested intervals data.

{
    "correlationIds": ["string"],
    "credentialIds": ["string"],
    "meterId": "mtr_1234",
    "meterNumber": 23220,
    "intervalsCreatedAt": "2024-08-28T09:56:12.000+00:00",
    "intervalsUpdatedAt": "2024-08-28T09:56:12.000+00:00",
    "earliestIntervalAt": "2023-08-29T07:00:00.000+00:00",
    "latestIntervalAt": "2024-08-23T06:45:00.000+00:00",
    "providerName": "string",
    "providerId": "string",
    "serviceType": "string",
    "electricMeterMultiplier": 0,
    "readType": "string",
    "localTimezone": "string",
    "intervalDurationMinutes" : 15,
  	"sourceIntervalDurationMinutes" : [ 60 ],
    "startAt" : "2023-08-29T07:00:00.000+00:00",
  	"endAt" : "2024-05-23T06:45:00.000+00:00",
    "readings": [
         {
          "electricMeterMultiplier" : [ 1,1],
          "importKwh" : [ 2,2 ],
          "exportKwh" : [ 1,1],
          "netKwh" : [ 1,1]
         }  
               ]
}

Intervals data access error

If the request was made incorrectly, for reasons such as incorrect meterId, you can expect to get a json response error message as below

{
  "error": "invalid_intervals_request",
  "error_description": "Invalid meterId or inactive meter"
}