This is a development version of the documentation. Content may change without notice.
Voke Documentation
Partner API

Addressing sites by EAN

Look up a site and read its current meter state using the Czech metering-point EAN — no internal IDs or mapping tables required.

Overview

Every Voke site can carry up to two Czech-market metering-point identifiers:

  • eanCons — consumption EAN (odběrný EAN), where electricity flows in from the grid.
  • eanProd — production EAN (výrobní EAN), where electricity flows out to the grid.

Both are exactly 18 digits (e.g. 859182400123456789). If your system models customers by EAN — for example from an EDC sharing export — you can address Voke sites directly by EAN without maintaining any EAN → site mapping table.

The canonical site identifier on the wire stays the site UUID (siteId in AMQP envelopes and REST paths). EANs are lookup attributes: resolve once, cache the UUID, and fall back to a fresh lookup if a site disappears.


One-call meter state — GET /vcp/meter-state?ean=

The fastest path from "I have an EAN" to "what does the meter say right now":

curl -H "X-API-Key: <your-key>" \
  "https://api.voke.turena.cz/api/v1/vcp/meter-state?ean=859182400123456789"
{
  "siteId": "d290f1ee-6c54-4b01-90e6-d701748f0851",
  "eanCons": "859182400123456789",
  "eanProd": "859182400987654321",
  "reading": {
    "readingAt": "2026-06-13T15:49:50.355Z",
    "meters": [
      {
        "deviceId": "GRID",
        "role": "GRID",
        "importRegisterKwh": 34897.145,
        "productionRegisterKwh": 109018.273
      }
    ],
    "dataQuality": "GOOD"
  }
}

This is a real response captured from a live plant. Which register fields appear depends on what the meter physically exposes — a grid meter may report importRegisterKwh / exportRegisterKwh / productionRegisterKwh, a battery chargeRegisterKwh / dischargeRegisterKwh, etc. Only the registers the device actually has are included.

Behavior:

  • The EAN matches either eanCons or eanProd of a site in your organization.
  • Registers are absolute, monotonically increasing kWh counters — derive deltas by subtracting a previous reading.
  • reading is null when no telemetry is fresh enough (site offline or no register-tagged signals yet).
  • An unknown EAN (or one belonging to another organization) returns 404 SITE_NOT_FOUND.
  • A malformed EAN (not exactly 18 digits) returns 400 VALIDATION_ERROR.

Requires the vcp:read scope — the same key you use for all /vcp/sites/* reads.


Catalog lookup — GET /vcp/sites?ean=

To resolve an EAN to the full site record (sub-devices, supported commands, status):

curl -H "X-API-Key: <your-key>" \
  "https://api.voke.turena.cz/api/v1/vcp/sites?ean=859182400123456789"

The response is the standard plant list filtered to the matching site. Every site in the unfiltered catalog also carries its eanCons / eanProd, so a single unfiltered GET /vcp/sites at boot gives you the complete EAN ↔ siteId map.

An unknown EAN returns an empty plants array (it is a filter, not a lookup — no 404).


EANs on the AMQP meter stream

The 1-minute MeterReadingPayload on routing key {slug}.event.telemetry.meter.{siteId} carries the site's eanCons / eanProd directly in the payload:

{
  "version": "1.1",
  "siteId": "d290f1ee-6c54-4b01-90e6-d701748f0851",
  "payload": {
    "readingAt": "2026-06-12T09:00:00.000Z",
    "eanCons": "859182400123456789",
    "eanProd": "859182400987654321",
    "meters": [{ "deviceId": "GRID", "role": "GRID", "importRegisterKwh": 124530.487 }],
    "dataQuality": "GOOD"
  }
}

Consumers can route readings into an EAN-keyed model with zero extra calls. Fields are null for sites that have no EAN configured.

Can I subscribe to one EAN's stream?

Not by EAN directly — but you can subscribe per site, which gets you the same result. The telemetry routing key now ends with the site UUID (…telemetry.realtime.{siteId} / …telemetry.meter.{siteId}), and the vcp exchange is a topic exchange, so you can bind a dedicated queue to one PLC's siteId instead of consuming the shared firehose. See Subscribe to one PLC for the binding example.

The EAN is not in the routing key (it's nullable, can change with a metering-point contract, and is absent on realtime). The mapping is one stable boot-time step:

  1. Call GET /vcp/sites once and build your EAN → siteId map (every site carries eanCons / eanProd).
  2. Bind a queue to the siteId(s) you care about — or keep the default firehose queue and route in-process.

Whichever you choose, key your business logic on what's in every message:

  • envelope.siteId — the plant UUID, present on every message (stable, never changes).
  • payload.eanCons / payload.eanProd — present on meter readings, for your EAN-keyed accounting.

Bind and route by siteId: it's a stable UUID that's on every message type and is the only thing in the routing key. EANs are only on meter readings, can be unset (null), and can change if a metering point's contract changes — so they stay in the payload, not the routing key.


Identifier cheat sheet

IdentifierWhereMeaning
siteIdREST paths, AMQP envelopeVoke site (plant) UUID — the canonical wire id.
eanCons / eanProd/vcp/sites, /vcp/meter-state, meter payloadsCzech metering-point EANs (18 digits) — lookup attributes.
deviceIdsubDevices[], DeviceTelemetry, MeterEntry, command targetsSub-device externalId (e.g. GRID, PV1) — one rule, everywhere.
externalPlantId/vcp/sitesOptional partner-assigned alias for your own catalog reconciliation.

On this page