IOmeter Partner API

IOmeter Partner GraphQL API Documentation

API Endpoints
# Production:
https://partner.prod.iometer.cloud/api/v1/query
Headers
Authorization: Basic BASE64(<TOKEN:SECRET>)

GraphQL

GraphQL is an open-source data query and manipulation language for APIs and a query runtime engine. GraphQL enables declarative data fetching where a client can specify exactly what data it needs from an API.

For general information about the GraphQL, see graphql.org

GraphQL is served via HTTP, which allows to send GraphQL queries via standard HTTP GET and POST requests. Details about the HTTP transport can be found here: https://graphql.org/learn/serving-over-http/

There is also a GraphQL Playground available, which provides a simple to use Web GUI to explore the GraphQL API and to try out GraphQL queries.

While GraphQL can be used directly, there is also a large amount of client libraries available which help with consuming GraphQL APIs: https://graphql.org/code/

GraphQL also supports subscriptions, which allow the API to push data to the client. The IOmeter API uses either the GraphQL over WebSocket Protocol or the GraphQL over Server-Sent Events Protocol to enable such subscriptions.

Authentication

The API supports two authentication methods:

Basic Auth

Basic Auth uses a simple basic authentication header generated as follows:

"Basic " + base64("<partner_id>:<partner_secret>")

Example

  • Partner ID: b1451a19-53c7-4e8a-87a0-7c45d3807e9d
  • Partner Secret: JjNQKxIYugVSqCrxkbNfQ8Onpvd07K2G
  • Header: Authorization: Basic YjE0NTFhMTktNTNjNy00ZThhLTg3YTAtN2M0NWQzODA3ZTlkOkpqTlFLeElZdWdWU3FDcnhrYk5mUThPbnB2ZDA3SzJH

WSSE

WSSE transmits a digest consisting of the secret, a nonce and a timestamp.

The nonce is a randomly generated value with 16 bytes, timestamp is a UTC timestamp in RFC3339 format, and the secret is the partner secret.

The header is generated as follows:

func GenerateWSSE(partnerID string, secret string) string {
               created := time.Now().UTC().Format(time.RFC3339)
            
               nonceBytes := make([]byte, 16)
               _, _ = rand.Read(nonceBytes)
               nonce := hex.EncodeToString(nonceBytes)
            
               text := nonce + created + secret
            
               digestHash := sha256.New()
               digestHash.Write([]byte(text))
               digestString := hex.EncodeToString(digestHash.Sum(nil))
            
               passwordDigest := base64.StdEncoding.EncodeToString([]byte(digestString))
            
               return fmt.Sprintf(
                  "UsernameToken Username=\"%s\", PasswordDigest=\"%s\", Nonce=\"%s\", Created=\"%s\"",
                  partnerID,
                  passwordDigest,
                  nonce,
                  created,
               )
            }
            

Example

  • Partner ID: 0da56783-39b2-4b43-adaa-301d247fcd59
  • Partner Secret: 1NNbSclq0ULA364TZBB4Hr0EYoRK
  • Created: 2025-10-20T12:38:50Z
  • Nonce: eb6c574e12fcfa4cd091a5b21ad0abdb
  • Password Digest: NWNiYTMyNzNmZGQ2NWU2ODhjZjc1Mzg3MzliZGE4MTgyMjhjY2Q3NWU1NmYxMzEyM2NhMmI3MWI0ZmMwODY3MA==
  • Header: Authorization: UsernameToken Username="0da56783-39b2-4b43-adaa-301d247fcd59", PasswordDigest="NWNiYTMyNzNmZGQ2NWU2ODhjZjc1Mzg3MzliZGE4MTgyMjhjY2Q3NWU1NmYxMzEyM2NhMmI3MWI0ZmMwODY3MA==", Nonce="eb6c574e12fcfa4cd091a5b21ad0abdb", Created="2025-10-20T12:38:50Z"

Account Linking

To start the account linking process, the Partner App needs to open the connection URL for the user.

The connection URL can be obtained from the connectUrl query:

query {
  connectUrl(
    redirectUrl: "https://example.com"
    state: "123456"
  )
}    

The URL will open the IOmeter App, where the user will be asked to confirm linking their account to the partner.

If the user accepts, the redirect URI is called with the following additional parameter:

  • installation_id, which represents the unique account ID of the user

If account linking fails, the redirect URI is called with an error parameter instead which may have one of the following values:

  • access_denied, if user declined linking their account
  • unauthorized_client, if the the partner isn’t authorized to link their account
  • server_error, if linking process failed for an unexpected reason

Once accounts are linked the Partner will have access to installation data using the Partner API.

Queries

connectUrl

use partner.connectUrl instead
Response

Returns a String!

Arguments
Name Description
redirectUrl - String!
state - String

Example

Query
query ConnectUrl(
  $redirectUrl: String!,
  $state: String
) {
  connectUrl(
    redirectUrl: $redirectUrl,
    state: $state
  )
}
Variables
{
  "redirectUrl": "xyz789",
  "state": "xyz789"
}
Response
{"data": {"connectUrl": "xyz789"}}

installation

use partner.installation instead
Response

Returns an Installation

Arguments
Name Description
id - Uuid!

Example

Query
query Installation($id: Uuid!) {
  installation(id: $id) {
    externalId
    id
    meter {
      id
      installation {
        ...InstallationFragment
      }
      number
      readings {
        ...MeterReadingsResponseFragment
      }
    }
    meters {
      id
      installation {
        ...InstallationFragment
      }
      number
      readings {
        ...MeterReadingsResponseFragment
      }
    }
    currentMeter {
      id
      installation {
        ...InstallationFragment
      }
      number
      readings {
        ...MeterReadingsResponseFragment
      }
    }
    device {
      id
      bridge {
        ...DeviceBridgeFragment
      }
      core {
        ...DeviceCoreFragment
      }
    }
    devices {
      id
      bridge {
        ...DeviceBridgeFragment
      }
      core {
        ...DeviceCoreFragment
      }
    }
    currentDevice {
      id
      bridge {
        ...DeviceBridgeFragment
      }
      core {
        ...DeviceCoreFragment
      }
    }
    readings {
      readings {
        ...MeterReadingFragment
      }
      cursor
    }
  }
}
Variables
{
  "id": "578936dc-8020-4022-a560-2f59d2dca9ee"
}
Response
{
  "data": {
    "installation": {
      "externalId": "abc123",
      "id": "578936dc-8020-4022-a560-2f59d2dca9ee",
      "meter": Meter,
      "meters": [Meter],
      "currentMeter": Meter,
      "device": Device,
      "devices": [Device],
      "currentDevice": Device,
      "readings": MeterReadingsResponse
    }
  }
}

installations

use partner.installations instead
Response

Returns [Installation!]!

Arguments
Name Description
pagination - Pagination

Example

Query
query Installations($pagination: Pagination) {
  installations(pagination: $pagination) {
    externalId
    id
    meter {
      id
      installation {
        ...InstallationFragment
      }
      number
      readings {
        ...MeterReadingsResponseFragment
      }
    }
    meters {
      id
      installation {
        ...InstallationFragment
      }
      number
      readings {
        ...MeterReadingsResponseFragment
      }
    }
    currentMeter {
      id
      installation {
        ...InstallationFragment
      }
      number
      readings {
        ...MeterReadingsResponseFragment
      }
    }
    device {
      id
      bridge {
        ...DeviceBridgeFragment
      }
      core {
        ...DeviceCoreFragment
      }
    }
    devices {
      id
      bridge {
        ...DeviceBridgeFragment
      }
      core {
        ...DeviceCoreFragment
      }
    }
    currentDevice {
      id
      bridge {
        ...DeviceBridgeFragment
      }
      core {
        ...DeviceCoreFragment
      }
    }
    readings {
      readings {
        ...MeterReadingFragment
      }
      cursor
    }
  }
}
Variables
{"pagination": Pagination}
Response
{
  "data": {
    "installations": [
      {
        "externalId": "xyz789",
        "id": "578936dc-8020-4022-a560-2f59d2dca9ee",
        "meter": Meter,
        "meters": [Meter],
        "currentMeter": Meter,
        "device": Device,
        "devices": [Device],
        "currentDevice": Device,
        "readings": MeterReadingsResponse
      }
    ]
  }
}

partner

Description

Returns the current partner

Response

Returns a Partner!

Example

Query
query Partner {
  partner {
    id
    name
    installations {
      externalId
      id
      meter {
        ...MeterFragment
      }
      meters {
        ...MeterFragment
      }
      currentMeter {
        ...MeterFragment
      }
      device {
        ...DeviceFragment
      }
      devices {
        ...DeviceFragment
      }
      currentDevice {
        ...DeviceFragment
      }
      readings {
        ...MeterReadingsResponseFragment
      }
    }
    installation {
      externalId
      id
      meter {
        ...MeterFragment
      }
      meters {
        ...MeterFragment
      }
      currentMeter {
        ...MeterFragment
      }
      device {
        ...DeviceFragment
      }
      devices {
        ...DeviceFragment
      }
      currentDevice {
        ...DeviceFragment
      }
      readings {
        ...MeterReadingsResponseFragment
      }
    }
    meters {
      id
      installation {
        ...InstallationFragment
      }
      number
      readings {
        ...MeterReadingsResponseFragment
      }
    }
    meter {
      id
      installation {
        ...InstallationFragment
      }
      number
      readings {
        ...MeterReadingsResponseFragment
      }
    }
    connectUrl
    readings {
      readings {
        ...MeterReadingFragment
      }
      cursor
    }
  }
}
Response
{
  "data": {
    "partner": {
      "id": "578936dc-8020-4022-a560-2f59d2dca9ee",
      "name": "Example Partner",
      "installations": [Installation],
      "installation": Installation,
      "meters": [Meter],
      "meter": Meter,
      "connectUrl": "xyz789",
      "readings": MeterReadingsResponse
    }
  }
}

readings

use partner.readings instead
Response

Returns a MeterReadingsResponse!

Arguments
Name Description
startTime - DateTime
limit - Int
cursor - String

Example

Query
query Readings(
  $startTime: DateTime,
  $limit: Int,
  $cursor: String
) {
  readings(
    startTime: $startTime,
    limit: $limit,
    cursor: $cursor
  ) {
    readings {
      meter {
        ...MeterFragment
      }
      time
      values {
        ...MeterReadingValueFragment
      }
    }
    cursor
  }
}
Variables
{
  "startTime": "2024-12-31T24:30:15Z",
  "limit": 123,
  "cursor": "xyz789"
}
Response
{
  "data": {
    "readings": {
      "readings": [MeterReading],
      "cursor": "abc123"
    }
  }
}

Mutations

disableInstallation

Description

Disables the partner for this installation

Response

Returns a Boolean!

Arguments
Name Description
installationID - String!

Example

Query
mutation DisableInstallation($installationID: String!) {
  disableInstallation(installationID: $installationID)
}
Variables
{"installationID": "xyz789"}
Response
{"data": {"disableInstallation": false}}

Subscriptions

liveReadings

Response

Returns a MeterReading!

Arguments
Name Description
installationId - ID!
obisCodes - [ObisCode]

Example

Query
subscription LiveReadings(
  $installationId: ID!,
  $obisCodes: [ObisCode]
) {
  liveReadings(
    installationId: $installationId,
    obisCodes: $obisCodes
  ) {
    meter {
      id
      installation {
        ...InstallationFragment
      }
      number
      readings {
        ...MeterReadingsResponseFragment
      }
    }
    time
    values {
      obisCode
      value
      unit
    }
  }
}
Variables
{
  "installationId": 4,
  "obisCodes": ["1-0:1.8.0"]
}
Response
{
  "data": {
    "liveReadings": {
      "meter": Meter,
      "time": "2024-12-31T24:30:15Z",
      "values": [MeterReadingValue]
    }
  }
}

meterReadings

Description

Returns a stream of readings for the currently logged in provider.

NOTE: In rare cases it's possible that the same reading might be returned multiple times

Response

Returns a MeterReading!

Arguments
Name Description
startTime - DateTime

At which timestamp to start returning readings from. Up to 24h supported.

Time is based on when readings were received, which might diverge from the time the reading was taken

Example

Query
subscription MeterReadings($startTime: DateTime) {
  meterReadings(startTime: $startTime) {
    meter {
      id
      installation {
        ...InstallationFragment
      }
      number
      readings {
        ...MeterReadingsResponseFragment
      }
    }
    time
    values {
      obisCode
      value
      unit
    }
  }
}
Variables
{"startTime": "2024-12-31T24:30:15Z"}
Response
{
  "data": {
    "meterReadings": {
      "meter": Meter,
      "time": "2024-12-31T24:30:15Z",
      "values": [MeterReadingValue]
    }
  }
}

Types

Boolean

Description

The Boolean scalar type represents true or false

ConnectionStatus

Values
Enum Value Description

connected

Device is connected

disconnected

Device is disconnected
Example
"connected"

CoreAttachmentStatus

Description

Current connection status of the core to the energy meter

Values
Enum Value Description

attached

Core is currently attached to an energy meter

detached

Core is currently not attached to an energy meter
Example
"attached"

CorePowerStatus

Description

Current power status of the core

Values
Enum Value Description

battery

Core is currently running on battery power

wired

Core is currently running on wired power
Example
"battery"

DateTime

Description

RFC 3339 Timestamp string (YYYY-MM-DDTHH:MM:SSZ)

Example
"2024-12-31T24:30:15Z"

Device

Description

Represents an IOmeter device in use by the user.

A device consists of two parts, the bridge and the core. The core is the piece attached to the meter, whereas the bridge is what is used to connect the meter to the local Wifi of the user

Fields
Field Name Description
id - Uuid! Unique ID of the device
bridge - DeviceBridge! Bridge, the part used to connect the core to the local Wifi of the user
core - DeviceCore! Core, the part attached to the energy meter
Example
{
  "id": "578936dc-8020-4022-a560-2f59d2dca9ee",
  "bridge": DeviceBridge,
  "core": DeviceCore
}

DeviceBridge

Description

The part of the device used to connect the core to the local Wifi of the user

Fields
Field Name Description
connectionStatus - ConnectionStatus! Current connection status of the bridge to the IOmeter backend
Example
{"connectionStatus": "connected"}

DeviceCore

Description

The part of the device attached to the energy meter

Fields
Field Name Description
connectionStatus - ConnectionStatus! Current connection status of the core to the bridge
attachmentStatus - CoreAttachmentStatus! Current connection status of the core to the energy meter
batteryLevel - Int! Current battery level of the device (0-100)
powerStatus - CorePowerStatus! Current power status of the core
pinStatus - PinStatus! Current pin status of the core
Example
{
  "connectionStatus": "connected",
  "attachmentStatus": "attached",
  "batteryLevel": 100,
  "powerStatus": "battery",
  "pinStatus": "missing"
}

Float

Description

The Float scalar type represents signed double-precision fractional values as specified by IEEE 754

Example
987.65

ID

Description

The ID scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as "4") or integer (such as 4) input value will be accepted as an ID

Example
"4"

Installation

Description

Reflects a single installation (or user) which may own a number of (energy) meters and IOmeter devices.

Each installation is identified by either an InstallationID or optionally an ExternalID given by the provider when creating the registration token

Fields
Field Name Description
externalId - String No longer supported
id - Uuid! Unique ID of the installation, automatically generated for each installation
meter - Meter Return single meter. Either id or number required
Arguments
id - Uuid
number - String
meters - [Meter!]! List of energy meters the installation has obtained readings from
currentMeter - Meter Most recent meter the installation has received data from
device - Device Return single device by id
Arguments
id - Uuid
devices - [Device!]! List of IOmeter devices the installation has registered
currentDevice - Device Most recent device used by the installation
readings - MeterReadingsResponse!

Returns readings for this installation.

Will at maximum return limit readings. If more readings are available, a cursor value is returned, which can be used in a subsequent call to return remaining readings.

If no more readings are available, cursor will be null

Arguments
startTime - DateTime

Return readings starting from this time stamp. By default, all readings are returned

endTime - DateTime

Return readings until this timestamp. By default, all readings are returned

limit - Int

Limit of readings to return per call. Defaults to 100. Maximum value 200

cursor - String

If more than limit readings are available, a cursor value is returned, which can be used in a subsequent call to return remaining readings

Example
{
  "externalId": "xyz789",
  "id": "578936dc-8020-4022-a560-2f59d2dca9ee",
  "meter": Meter,
  "meters": [Meter],
  "currentMeter": Meter,
  "device": Device,
  "devices": [Device],
  "currentDevice": Device,
  "readings": MeterReadingsResponse
}

Int

Description

The Int scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1

Example
987

Meter

Description

Reflects an energy meter, identified by a unique ID and its meter number.

A single installation may have IOmeter devices attached to multiple meters at the same time

Fields
Field Name Description
id - Uuid! Unique ID of the meter, automatically generated
installation - Installation! Installation this meter belongs to
number - MeterNumber! Meter number of the meter
readings - MeterReadingsResponse!

Returns readings for this meter.

Will at maximum return limit readings. If more readings are available, a cursor value is returned, which can be used in a subsequent call to return remaining readings.

If no more readings are available, cursor will be null

Arguments
startTime - DateTime

Return readings starting from this time stamp. By default, all readings are returned

endTime - DateTime

Return readings until this timestamp. By default, all readings are returned

limit - Int

Limit of readings to return per call. Defaults to 100. Maximum value 200

cursor - String

If more than limit readings are available, a cursor value is returned, which can be used in a subsequent call to return remaining readings

Example
{
  "id": "578936dc-8020-4022-a560-2f59d2dca9ee",
  "installation": Installation,
  "number": "1EMH0007058153",
  "readings": MeterReadingsResponse
}

MeterNumber

Description

Energy meter number

Example
"1EMH0007058153"

MeterReading

Fields
Field Name Description
meter - Meter! Energy meter this reading was taken from
time - DateTime! Time this reading was taken
values - [MeterReadingValue!]! List of reading values, one for each OBIS code
Example
{
  "meter": Meter,
  "time": "2024-12-31T24:30:15Z",
  "values": [MeterReadingValue]
}

MeterReadingValue

Fields
Field Name Description
obisCode - ObisCode!

OBIS code of this reading value

Format defaults to dec

Arguments
format - ObisFormat
value - Float! Reading value
unit - String! Unit of the reading value
Example
{
  "obisCode": "1-0:1.8.0",
  "value": 987.65,
  "unit": "Wh"
}

MeterReadingsResponse

Fields
Field Name Description
readings - [MeterReading!]!
cursor - String If more than limit readings are available, a cursor value is returned, which can be used in a subsequent call to return remaining readings
Example
{
  "readings": [MeterReading],
  "cursor": "xyz789"
}

ObisCode

Description

ObisCode according to IEC 62056-6-1

Format: A-B:C.D.E

  • A: Medium (for electricity=1, for thermal energy (gas) = 7)
  • B: Channel (internal or external channel)
  • C: Measured value (energy, voltage, etc)
  • D: Measurement type (maximum, current value, etc)
  • E: Tariff

Examples:

  • 1-0:1.8.0: Positive active energy (A+) total [kWh]
  • 1-0:1.8.1: Positive active energy (A+) in tariff T1 [kWh]
  • 1-0:1.8.2: Positive active energy (A+) in tariff T2 [kWh]
  • 1-0:2.8.0: Negative active energy (A-) total [kWh]
  • 1-0:16.7.0: Sum active instantaneous power (A+ - A-) [kW]

Also supports hexadecimal format, example: 01-00:01.08.00*ff

See also https://de.wikipedia.org/wiki/OBIS-Kennzahlen

Example
"1-0:1.8.0"

ObisFormat

Values
Enum Value Description

hex

Returns OBIS code in hexadecimal format with 6 value groups (A-B:C.D.E*F), example: 01-00:01.08.00*ff

dec

Returns OBIS code in decimal format with 5 value groups (A-B:C.D.E), example: 1-0:1.8.0

dec3

Returns OBIS code in decimal format with 3 value groups (C.D.E), example: 1.8.0

dec6

Returns OBIS code in decimal format with 6 value groups (A-B:C.D.E*F), example: 1-0:1.8.0*255
Example
"hex"

Pagination

Fields
Input Field Description
offset - Int
limit - Int
Example
{"offset": 0, "limit": 20}

Partner

Fields
Field Name Description
id - Uuid!
name - String!
installations - [Installation!]! Returns list of installations that belong to this partner
Arguments
pagination - Pagination
installation - Installation Returns a single installation
Arguments
id - Uuid!
meters - [Meter!]!

Returns list of meters that belong to this partner

Note that there might be multiple meters with the same meter number if multiple installations have used the same physical meter. In this case the most recent meter is returned

Arguments
number - String
pagination - Pagination
meter - Meter Returns single meter. Either id or meter number required
Arguments
id - Uuid
number - String
connectUrl - String!

Generate a connect URL

URL will open the IOmeter app, in which the user may grant access of their installation to the partner.

If access is granted, the redirect URL is called with an additional installation_id query parameter identifying the installation.

If the request is refused, the redirect URL is called with an additional error query parameter which may be one of the following values:

  • access_denied, if user declined linking their account
  • unauthorized_client, if the partner isn't authorized to link their account
  • server_error, if linking process failed for an unexpected reason

If provided the value of the state parameter will also be appended as a query parameter to the redirect URL

Arguments
redirectUrl - String!
state - String
readings - MeterReadingsResponse!

Returns readings for the current partner.

Will at maximum return limit readings. If more readings are available, a cursor value is returned, which can be used in a subsequent call to return remaining readings.

If no more readings are available, cursor will be null

Arguments
startTime - DateTime

Return readings starting from this time stamp. By default, all readings are returned

endTime - DateTime

Return readings until this timestamp. By default, all readings are returned

limit - Int

Limit of readings to return per call. Defaults to 100. Maximum value 200

cursor - String

If more than limit readings are available, a cursor value is returned, which can be used in a subsequent call to return remaining readings

Example
{
  "id": "578936dc-8020-4022-a560-2f59d2dca9ee",
  "name": "Example Partner",
  "installations": [Installation],
  "installation": Installation,
  "meters": [Meter],
  "meter": Meter,
  "connectUrl": "abc123",
  "readings": MeterReadingsResponse
}

PinStatus

Description

Current pin status of the core

Values
Enum Value Description

missing

PIN has not been entered

pending

PIN is currently being entered

entered

PIN has been entered
Example
"missing"

String

Description

The String scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text

Example
"abc123"

Uuid

Description

RFC 4122 Universally unique identifier

Example
"578936dc-8020-4022-a560-2f59d2dca9ee"