energy-api
Rust client and server bindings for the German energy market API-Webdienste (MaKo — Marktkommunikation).
Module layout
energy_api
├── models/ OpenAPI/AsyncAPI types shared by all APIs
├── transport/ HTTP + mTLS builder, JWS sign/verify
├── directory/ Verzeichnisdienst — REST client, WebSocket client, server
├── client/ Electricity API clients (feature = "client")
│ ├── control_measures NB/LF and MSB send calls
│ └── malo_ident LF and NB callback calls
└── server/ Electricity API servers (feature = "server")
├── control_measures MSB and NB/LF receive handlers + axum router
└── malo_ident NB and LF receive handlers + axum router
Feature flags
| Feature | Enables |
|---|---|
client |
HTTP clients for all APIs (reqwest + rustls) |
server |
Axum router factories for server implementations |
websocket |
WebSocket subscription client (tokio-tungstenite) |
crypto |
JWS ECDSA-SHA256 sign/verify for directory records (p256) |
Quick start
Look up an endpoint via the directory
# #[cfg(feature = "client")]
# async fn example() -> Result<(), energy_api::Error> {
use energy_api::directory::DirectoryServiceClient;
use url::Url;
let base = Url::parse("https://verzeichnisdienst.example.de/")?;
let client = DirectoryServiceClient::new_insecure(base)?;
let (record, _cert, _sig) = client
.get_record("1234567890123", "controlMeasuresV1", 1)
.await?;
println!("{}", record.url);
# Ok(())
# }
Send a grid control command
# #[cfg(feature = "client")]
# async fn example() -> Result<(), energy_api::Error> {
use energy_api::client::ControlMeasuresClient;
use energy_api::models::electricity::{
CommandControl, LocationId, NeloId, MaximumPowerValue,
};
use url::Url;
use uuid::Uuid;
let client = ControlMeasuresClient::new(
Url::parse("https://msb.example.de/")?,
reqwest::Client::new(),
);
client.send_konfiguration(
Uuid::new_v4(),
"2025-06-01T10:00:00.000Z",
&LocationId::NetworkLocation(NeloId("E1234848431".into())),
&CommandControl {
maximum_power_value: MaximumPowerValue("10.5".into()),
execution_time_from: "2025-06-01T10:00:00Z".into(),
execution_time_until: None,
},
None,
).await?;
# Ok(())
# }