NAV
Command Line Ruby Python PHP Perl Java C NodeJS Javascript

Introduction

Welcome to the EKM METERING API!

We at EKM see easy access to your data, and the scalable systems behind the EKM Push, as crucial to moving our products into the future. To that end, we do what is unheard of in our industry, we give you your data for FREE.

The EKM API is organized around Representational State Transfer, or REST. You can use our Application Programming Interface, or API, to access EKM API endpoints, which can get you information on various EKM Push meter data and utilize it in your own application, database, billing system, or building automation system.

We have language bindings in Shell (cURL), Ruby, Python, PHP, Java, Javascript, Nodejs and C! You can view code examples in the dark area to the right, and you can switch the programming language of the examples with the tabs in the top right.

Our API is designed to have predictable, resource-oriented URLs and to use HTTP response codes to indicate API errors. We use built-in HTTP features, like HTTP authentication and HTTP verbs, which can be understood by off-the-shelf HTTP clients, and we support cross-origin resource sharing to allow you to interact securely with our API from a client-side web application (though you should remember that you should never expose your secret EKM Push API key in any public website’s client-side code). JSON will be returned in all responses from the API, including errors (though if you’re using API bindings, we will convert the response to the appropriate language-specific object).

Authentication

To authorize, make sure to use your personal EKM Push account key.

The examples in this API documentation use the demo key of MTAxMDoyMDIw. Please make sure you remove this key and place your personal key in the https address if you are trying to access the meters in your account.

With shell, you can just pass the correct address with each request
curl -s "URL Here"
Authorization: "EKM Push Key"
# Load required modules
require 'net/http'
require 'json'

# Call the callApi method to create a usable
# object named apiObject from the API request URI
# Put the API request URI in the call
def callApi(apiRequest)
    json = Net::HTTP.get('io.ekmpush.com',apiRequest)
    return JSON.parse(json)
end

# Call the callApi method to create a usable
# object named apiObject from the API request URI
# Put the API request URI in the call
# URI only NOT URL - Do not include https://io.ekmpush.com
apiObject = callApi('URI Here')

# This just displays the object but you can use what ever
# code you would like to work with the object here
require 'pp'
pp apiObject
# Required Python Modules
import urllib.request, urllib.error, urllib.parse
import json

# This function accesses the apiRequest URL and converts
# the contents to a usable Python object and returns it
def callApi ( apiRequest ):
        response = urllib.request.urlopen(apiRequest)
        response = response.read()
        jsonObject = json.loads(response.decode())
        return jsonObject

# Call the callApi function to create a usable
# object named apiObject from the API request URL.
# Put the API request URL in the call
apiObject = callApi("URL Here")

# This just displays the object but you can use what ever
# code you would like to work with the object here
import pprint
pprint.pprint(apiObject)
<?php
// Call the callApi function to create a usable
// object named $apiObject from the API request URL.
// Put the API request URL in the call
$apiObject=callApi('URL Here');

// This just displays the object but you can use what ever
// code you would like to work with the object here
var_dump($apiObject);

// This function accesses the apiRequest URL and converts
// the contents to a usable PHP object and returns it
function callApi ($apiRequest='') {

        $json=@file_get_contents($apiRequest);
        $jsonObject=json_decode($json);
        return ($jsonObject);

}
?>
/*
 Download the correct org.json jar version for your
 needs from: https://mvnrepository.com/artifact/org.json/json

 This example uses version 20190722 accessible here:
 https://repo1.maven.org/maven2/org/json/json/20190722/json-20190722.jar

 Instructions to run this program

 1. Put this code in a file named EKM.java
 2. Copy the downloaded org.json jar and EKM.java to the same directory
 3. Compile
  javac -cp .:./json-20190722.jar ./EKM.java
 4. Run
  java -cp .:./json-20190722.jar EKM
*/


//Import required classes
import java.net.*;
import java.io.*;
import org.json.*;

public class EKM {
    public static JSONObject callApi(String apiRequest) throws Exception {

        // This code accesses the apiRequest URL and converts
        // the contents to a usable JSON object

        URL url = new URL(apiRequest);
        URLConnection connection = url.openConnection();
        BufferedReader in = new BufferedReader(
                                               new InputStreamReader(
                                                                     connection.getInputStream()));

        StringBuilder response = new StringBuilder();
        String inputLine;

        while ((inputLine = in.readLine()) != null)
            response.append(inputLine);

        in.close();

        JSONObject jsonObject = new JSONObject(response.toString());
        return jsonObject;
    }

    public static void main(String[] args) throws Exception {
        /*
         Call callApi to create a usable
         object named apiObject from the API request URL.
         Put the API request URL in the call
         */
        JSONObject apiObject = EKM.callApi("URL Here");

        /*
         You can access any part of the apiObject using code like this:
         JSONArray  readData = apiObject.getJSONObject("readMeter").getJSONArray("ReadSet").
         getJSONObject(0).getJSONArray("ReadData");
        */

        // This just outputs the whole apiObject
        System.out.println(apiObject.toString(4));
    }
}
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">

// The example function is called from the 
// body tag when the page loads
function example(){

// Call the callApi function to create a usable
// object named apiObject from the API request URL.
// Put the API request URL in the call
callApi('URL Here',function(apiObject){

       // This just displays the object in the result div
       // you can use what ever code you would like to work 
       // with the object here
       document.getElementById("result").innerHTML = "<pre>"+JSON.stringify(apiObject, null, 4)+"</pre>";
       });

};

// This code accesses the apiRequest URL and converts
// the contents to a usable JSON object named apiObject
function callApi(apiRequest,callback) {
    var xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function() {
      if (xhttp.readyState == 4 && xhttp.status == 200) {
        var jsonObject = JSON.parse(xhttp.responseText);
        callback(jsonObject);
      }
    };
    xhttp.open("GET", apiRequest, true);
    xhttp.send();
}
</script>

</head>
  <body onload="example()">
    <div id="result"/>
  </body>
</html>
// NodeJS requires the "request" module to access the API
// Install by running "npm install request" from the shell prompt

// Load "request" module
var request = require("request");

// Call the callApi function to create a usable
// object named apiObject from the API request URL.
// Put the API request URL in the call
callApi('URL Here', function (apiObject) {


        // This just displays the object but you can use what ever
        // code you would like to work with the object here
        console.log(JSON.stringify(apiObject, null, 4));
});

// This code accesses the apiRequest URL and converts
// the contents to a usable JSON object named apiObject
function callApi(apiRequest,callback){

        var options = { method: 'GET'
                        , uri: apiRequest
                        , timeout: 1000*15
                        , strictSSL: false
                        , rejectUnhauthorized : false
                      };

        request(options, function (error, response, body) {
                if(error){
                        console.log(error);
                        throw error;
                }else{
                     var jsonObject = JSON.parse(body);
                     callback(jsonObject);
                }
        });
}
/*
 *  Install json-c if its not installed
 *  https://github.com/json-c/json-c/wiki
 *
 *  Below is command to install json-c on centos
 *  yum install json-c-devel
 *
 *  Saved this example code to a file named ekm.c
 *  - Compile
 *  gcc ekm.c -o ekm -lcurl  -ljson-c
 *  - Run
 *  ./ekm
 *
 */
// Required Includes
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h> //your directory may vary depending on your OS
#include <json/json.h> //your directory may vary
// End Includes

// Code reqired for curl
struct string {
    char *data;
    size_t len;
};

void init_string(struct string *response) {
    response->len = 0;
    response->data = (char*)malloc(response->len+1);
    if (response->data == NULL) {
        fprintf(stderr, "malloc() failed\n");
        exit(EXIT_FAILURE);
    }
    response->data[0] = '\0';
}

size_t curlData(void *data, size_t size, size_t nmemb, struct string *response)
{
    size_t new_len = response->len + size*nmemb;
    response->data = (char*)realloc(response->data, new_len+1);
    if (response->data == NULL) {
        fprintf(stderr, "realloc() failed\n");
        exit(EXIT_FAILURE);
    }
    memcpy(response->data+response->len, data, size*nmemb);
    response->data[new_len] = '\0';
    response->len = new_len;

    return size*nmemb;
}
// End required Curl coding

// This function accesses the api URL and converts
// the contents to a usable JSON-C object and returns it
struct json_object* callAPI(const char * url){
    CURL *curl;
    CURLcode res;
    json_object * jsonObject;
    curl = curl_easy_init();
    if(curl) {
        struct string response;
        init_string(&response);

        curl_easy_setopt(curl, CURLOPT_URL, url);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlData);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
        res = curl_easy_perform(curl);
        if(CURLE_OK == res){
            jsonObject = json_tokener_parse(response.data);
        }
        free(response.data);
    }

    curl_easy_cleanup(curl);
    curl_global_cleanup();
    return jsonObject;
}

int main(void)
{

    // Call the callApi function to create a usable
    // object named apiObject from the API request URL.
    // Put the API request URL in the call
    json_object * apiObject = callAPI("URL Here");

    // This just displays the object but you can use what ever
    // code you would like to work with the object here
    json_object * readmeter_json;
    json_object_object_get_ex(apiObject,"readMeter",&readmeter_json);
    printf("Complete readMeter Object: \n%s", json_object_to_json_string_ext(readmeter_json,JSON_C_TO_STRING_PRETTY));

    // This example digs deaper into the JSON and displays the first
    // kwh_tot value for the first read of the first meter
    json_object * readset_json;
    json_object * readset_0_json;
    json_object * readdata_json;
    json_object * readdata_0_json;
    json_object * kwh_tot;
    json_object_object_get_ex(readmeter_json,"ReadSet",&readset_json);
    readset_0_json = json_object_array_get_idx(readset_json,0);
    json_object_object_get_ex(readset_0_json,"ReadData",&readdata_json);
    readdata_0_json = json_object_array_get_idx(readdata_json,0);
    json_object_object_get_ex(readdata_0_json,"kWh_Tot",&kwh_tot);
    printf("\nkWh_Tot: %s", json_object_to_json_string_ext(kwh_tot,JSON_C_TO_STRING_PRETTY));       

    return 0;
}

Make sure to replace the sample key: MTAxMDoyMDIw, with your API key in the https address.

EKM uses API keys to allow access to the API. You authenticate to the EKM API by providing one of your unique API keys in each request. Each Push account holder is provided with an EKM Push User Key, which provides access to all meters in their account. This key carries lots of privileges so we encourage you to keep it secret. In addition to this master key, additional keys are also provided to give access to each meter individually, and keys can be created to provide access to sub groups of meters upon request. These secondary keys can be used to share single meters, or a subset of meters, without sharing access to all meters in an account. For example, if you are a landlord with multiple rentals and meters, you could share specific meter keys with each of your tenants, so that they could have access to only the data that pertains to their usage.

Authentication to the API occurs via HTTP Basic Auth. Provide your API key as the basic authorized username. You do not need to provide a password. You must authenticate for all requests.

The EKM Push API expects the API key to be included in all requests to the server. The key is included in the URL in the following way:

Authorization: key=MTAxMDoyMDIw

Realtime API

Click here to go to Realtime Documentation

If you are developing your own app, cloud-to-cloud solution, billing system, or other SAS solution, our Real-Time API allows you to easily access your EKM Push data in any format that you need. Below you will find descriptions regarding how to access the data, and about the filters you can apply so the data comes to you in a format that is easily digested and inserted into your software solution.

The real-time API provides the 1000 latest meter reads for each of your meters. If your meter is being read once per minute, the data will be made available once per minute, per meter. Whether you have 1 meter or 10,000 meters, this is the easiest and most scalable way to access your data.

The EKM Dash, EKM Widget, encompass.io, wattvision.com, pvoutput.org, the other solutions in our Push App Store, as well as other customers that have their own custom solutions, all use this API to access their data. We use the same API as you and do not give ourselves any special permissions, we see what you see, which forces us to make the API as great as possible for everyone. We have even given you code examples that can be copy and pasted into your own software language to make the data access that much easier.

Use the API definition, metered values definition, code snippet suggestion, and guide to get you on your way to developing your next killer app. If you create something great, let us know; we’re open to adding all useful apps into the Push App Store.

We also have a Realtime API Request Builder Tool found here: https://apibuilder.ekmmetering.com

We also have Documentation for our Legacy Realtime API here: Legacy Realtime API

Summary API

Click here to go to Summary Documentation

Our Summary API takes every Real-Time read, over 15 minute time periods, and summarizes them into single 15 minute summaries. We store this data forever to provide a long term historical dataset for each meter. Our system can then combine these summaries together to summarize hours, days, weeks, and months. This dataset is often the best way to get historical values like kWh, pulse counts, etc. It also provides averages, min. and max. values, difference, and more. We make this data available to you via our Summary API in a very similar way to our Real-Time API.

You can use the Summary API definition to access the data you need, from 15 minutes to years of data. We have gone to great lengths to provide this data for free in order to add value to our metering systems. The Summary API, the Real-Time API, great affordable hardware, and scalable access to your data are all components of the most powerful, and highest value metering system available in the world.

We also have a Summary API Request Builder Tool found here: https://apibuilder.ekmmetering.com/summary.html

RS-485 Communications

Click here to go to RS-485 Documentation

This section is for developers, or individuals, that want to communicate with their EKM Meters directly using their own software or embedded solution.

The code examples found in this section are in the simplest possible method to get you started. You are welcome to make them more robust.

First we start you out just connecting to the meter. You will find there is a very simple command line process to help you get started.

After that we cover the CRC method required for most communication to the meter.

Then we put it all together, in a simple test script that will show reads, and also open and close the relays.

Last we cover how to convert the 255 character strings that the meter responds with to a usable array containing field names and their values. It is our hope that after you go through these steps you will have all the information you need, to build whatever tools you like to access the meter.

Our meters use an IEC 62056-21 communication standard that has been optimized for our own needs. We are more than happy to share this with you. With this you can write your own software or embedded solution to access your meter data.

IEC 62056 is a set of standards for Electricity metering data exchange by International Electrotechnical Commission.

To learn more about the IEC 62056 standard click the button below to visit the WikiPedia website.

Additional PDF docs are available:

v.3 Meter Settings Protocol

v.3 Meter Parsing

v.4 Meter Settings Protocol

v.4 Meter Parsing

v.4 Meter Alternate Modbus Protocol

If you are coding in Python you can also make use of our ekmmeters.py API.

Errors

EKM uses conventional HTTP response codes to indicate the success or failure of an API request. In general, codes in the 2xx range indicate success, codes in the 4xx range indicate an error that failed given the information provided, and codes in the 5xx range indicate an error with EKM’s servers (these are rare). Not all errors map cleanly onto HTTP response codes, however. When a request is valid but does not complete successfully, we return a 402 error code.

The EKM API uses the following error codes:

Error Code Meaning
400 Bad Request – Your request is invalid
401 Unauthorized – Your API key is wrong
402 Request Failed – The parameters were valid but the request failed.
403 Forbidden – The meter requested is hidden for administrators only
404 Not Found – The specified meter could not be found
405 Method Not Allowed – You tried to access a meter with an invalid method
406 Not Acceptable – You requested a format that isn’t html, xml, csv or json
410 Gone – The meter requested has been removed from our servers
418 Unknown
429 Too Many Requests – You’re requesting too many meter readings! Slow down!
500 Internal Server Error – We had a problem with our server. Try again later.
502 Bad Gateway – The proxy server received an invalid response
503 Service Unavailable – We’re temporarily offline for maintenance. Please try again later.