API-Webdienste Strom
BDEW API-Webdienste Strom — REST/JSON iMS channel vs. EDIFACT/AS4 channel. energy-api crate for iMS control measures, MaLo-ID queries, and directory service integration.
BDEW API-Webdienste Strom
The German energy market uses two distinct communication channels for electricity market processes. This document explains both, clarifies which processes use which channel, and shows how to integrate both crates in a single application.
Two parallel channels
graph LR
subgraph EDIFACT["EDIFACT / AS4 channel"]
direction TB
MSH["Trading Partner MSH"]
makod["makod<br/>(AS4 :4080)"]
engine["mako-engine<br/>+ domain crates"]
MSH -->|"AS4/SOAP EDIFACT"| makod
makod --> engine
engine -->|"AS4/SOAP EDIFACT"| MSH
end
subgraph REST["REST / JSON channel (iMS)"]
direction TB
NB["Netzbetreiber<br/>(MSB initiates)"]
webdienste["makod<br/>(Webdienste :8090)"]
energy_api["energy-api<br/>server/client"]
NB -->|"HTTPS JSON"| webdienste
webdienste --> energy_api
energy_api -->|"HTTPS JSON"| NB
end
style EDIFACT fill:#f0f4ff,stroke:#99b
style REST fill:#f0fff4,stroke:#9b9| Channel | Crates | Transport | Processes |
|---|---|---|---|
| EDIFACT/AS4 | edi-energy + mako-engine + makod | SOAP/MTOM, TLS, WS-Security | UTILMD, MSCONS, APERAK, CONTRL, INVOIC, REMADV, ORDERS, ORDRSP, and all other MaKo message types |
| REST/JSON (API-Webdienste) | energy-api | HTTPS, JWS signatures | iMS control measures, MaLo-ID queries, directory service |
The REST channel is a parallel channel introduced for intelligente Messsysteme (iMS) processes as of 2026-01-29 (BDEW API-Webdienste Strom, valid from 2026-01-29). It does not replace EDIFACT for electricity market processes. Both channels are mandatory for market participants who are in scope for iMS.
When to use each crate
EDIFACT/AS4 channel — edi-energy + mako-engine + makod
[dependencies]
edi-energy = { version = "0.14", features = ["utilmd", "mscons"] }
mako-engine = { version = "0.14", features = ["slatedb"] }
mako-gpke = "0.14" # or mako-wim / mako-geli-gas / mako-mabis
Use these crates for:
- Parsing and validating EDIFACT messages received over AS4 (
edi-energy). - Building outgoing EDIFACT messages (
edi-energybuilders). - Running long-lived market processes with event sourcing, regulatory deadlines, and atomic outbox enqueue (
mako-engine+ domain crates). - Production AS4 inbound reception with WSS verification and deduplication (
makodviaasx-rs).
See the Process Engine Guide for mako-engine architecture and the Getting Started guide for a first workflow example.
energy-api — for iMS REST processes
[dependencies]
energy-api = { version = "0.14", features = ["client"] } # HTTP client
energy-api = { version = "0.14", features = ["server"] } # Axum server handler
Use this crate for:
- Sending and receiving iMS grid control commands (
controlMeasuresV1). - MaLo-ID queries (
maloIdentV1). - Looking up endpoint URLs via the Verzeichnisdienst (directory service).
- JWS signing and verification of directory records (
cryptofeature).
Processes mapped to channels
| BDEW process | Channel | Crate | Notes |
|---|---|---|---|
| Lieferbeginn/-ende (GPKE) | EDIFACT/AS4 | edi-energy | UTILMD |
| Zählpunktregistrierung (WiM) | EDIFACT/AS4 | edi-energy | UTILMD |
| Fahrplankommunikation | EDIFACT/AS4 | edi-energy | MSCONS |
| Lastgangkommunikation | EDIFACT/AS4 | edi-energy | MSCONS |
| iMS Steuerbefehle (Konfiguration, Abschalten, Zuschalten) | REST/JSON | energy-api | ControlMeasuresClient |
| iMS Rückmeldungen | REST/JSON | energy-api | ControlMeasuresClient |
| MaLo-ID-Abfrage | REST/JSON | energy-api | MaloIdentClient |
| iMS Universalbestellprozess — Anmeldung (PID 11021) | REST/JSON | energy-api | WimOrderHandler::on_anmeldung |
| iMS Universalbestellprozess — Bestätigung (PID 11022) | REST/JSON | energy-api | WimOrderHandler::on_bestaetigung |
| iMS Universalbestellprozess — Ablehnung (PID 11023) | REST/JSON | energy-api | WimOrderHandler::on_ablehnung |
| Endpunkt-Lookup | REST/JSON | energy-api | DirectoryServiceClient |
Integration pattern
A market participant acting as Netzbetreiber (NB) typically needs both channels simultaneously: EDIFACT for GPKE/WiM process messages and REST for iMS control measure reception.
sequenceDiagram
participant MSB as Messstellenbetreiber
participant NB_AS4 as makod :4080<br/>(AS4 inbound)
participant NB_WEB as makod :8090<br/>(Webdienste)
participant engine as mako-engine<br/>(GPKE / WiM)
participant dir as Verzeichnisdienst<br/>(BDEW)
Note over MSB,dir: Channel 1 — EDIFACT/AS4 (Gerätewechsel)
MSB->>NB_AS4: POST /as4/inbox<br/>UTILMD PID 11002
NB_AS4->>engine: WimDeviceChangeWorkflow::Initiate
engine-->>NB_AS4: events + APERAK outbox
NB_AS4-->>MSB: AS4 Receipt + APERAK
Note over MSB,dir: Channel 2 — REST/JSON (iMS Steuerbefehl)
MSB->>dir: GET /v1/organisations/NB-GLN<br/>(endpoint lookup)
dir-->>MSB: endpoint URL + JWS cert
MSB->>NB_WEB: POST /controlMeasures/v1/configure<br/>(iMS Konfigurationsbefehl)
NB_WEB-->>MSB: 200 OK (receipt)use edi_energy::{parse_interchange, EdiEnergyMessage};
use energy_api::directory::DirectoryServiceClient;
use energy_api::server::control_measures;
use url::Url;
// ── EDIFACT/AS4 channel ──────────────────────────────────────────────────────
// Incoming AS4 payload bytes arrive from the message queue:
fn handle_as4_message(payload: &[u8]) -> Result<(), edi_energy::Error> {
for msg in parse_interchange(std::io::Cursor::new(payload)) {
let msg = msg?;
let pid = msg.detect_pruefidentifikator()?;
let report = msg.validate()?;
println!("MSG {pid}: valid={}", report.is_valid());
}
Ok(())
}
// ── REST/JSON channel ────────────────────────────────────────────────────────
// Look up the MSB endpoint for a given MaLo before sending a control command:
#[cfg(feature = "client")]
async fn lookup_msb_endpoint() -> Result<(), energy_api::Error> {
let dir = DirectoryServiceClient::new_insecure(
Url::parse("https://verzeichnisdienst.example.de/").unwrap(),
)?;
let (record, _cert, _sig) = dir
.get_record("1234567890123", "controlMeasuresV1", 1)
.await?;
println!("MSB endpoint: {}", record.url);
Ok(())
}
The two channels operate independently: the edi-energy crate has no runtime
dependency on energy-api and vice versa. They share no types; the only shared
concern is the MaLo/MeLo identifier strings that appear in both EDIFACT segments
and REST payloads.
energy-api feature flags
| Feature | What it enables |
|---|---|
client | ControlMeasuresClient, MaloIdentClient, DirectoryServiceClient HTTP clients (reqwest + rustls) |
server | Axum router factories for ControlMeasuresHandler, MaloIdentHandler, and WimOrderHandler receive handlers |
websocket | WebSocket subscription client for real-time directory updates (tokio-tungstenite) |
crypto | JWS ECDSA-SHA256 sign/verify for directory records (p256) |
Scope boundary: Electricity only (Gas API status)
The energy-api crate is scoped to the BDEW API-Webdienste Strom (REST/JSON,
valid from 2026-01-29). As of the 2026 annual update cycle, BDEW has not
published an equivalent Gas API-Webdienste specification. Gas iMS processes
continue to use EDIFACT over AS4 via the edi-energy crate.
When BDEW publishes a Gas API specification, the intent is to add a gas feature
flag to energy-api alongside the existing client/server features, keeping
the electricity and gas implementations independently opt-in.
Monitor the BDEW document portal at https://www.bdew-mako.de/documents for Gas API-Webdienste announcements.
Identifier validation
Every BDEW identifier crossing this boundary is a validated rubo4e::identifiers
type. Deserialize enforces the check digit, so a malformed MaLo-, MeLo-, NeLo-,
SR- or TR-ID is rejected with 400 before it reaches a handler.
This matters most for MaLo-Ident: it is the first binding API process in German MaKo (mandatory since 06.06.2025, 2-hour deadline) and a precondition for every supplier switch, so it is exactly where a bad identifier would enter and propagate.
MarketPartnerId is a string, not an integer — BDEW codes may carry leading
zeros.
Specification versions
energy-api implements 1.0.0, the only tag in either spec repository.
Release 2.0.0 was consulted via Mitteilung Nr. 55 for 01.10.2026 and then
excluded by Mitteilung Nr. 56; only API Guideline 1.0b binds on that
date. The 2.0.0 material lives on a consultation branch that is still moving, and
no 2.0.0 tag exists. energy-api::spec_version::RELEASE_2_0_0_SCOPE records
what it will change when it freezes.
Note the specs are split across two repositories: EDI-Energy/api-electricity
(electricity APIs) and EDI-Energy/api-directory-service (Verzeichnisdienst).
Further reading
- Getting Started — EDIFACT parsing and process engine first steps
- Process Engine Guide —
mako-enginearchitecture, stores, deadlines, outbox - Platform guide — multi-tenant EDIFACT processing
- Validation guide
- BDEW MaKo document portal: https://www.bdew-mako.de/documents